| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- /******************************************************************************
- * Copyright 2013-2014 Espressif Systems (Wuxi)
- *
- * FileName: hw_time.c
- *
- * Description: hw_time driver
- *
- * Modification history:
- * 2014/5/1, v1.0 create this file.
- *******************************************************************************/
- #include "ets_sys.h"
- #include "os_type.h"
- #include "osapi.h"
- #if 1
- #define US_TO_RTC_TIMER_TICKS(t) \
- ((t) ? \
- (((t) > 0x35A) ? \
- (((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
- (((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
- 0)
- #define FRC1_ENABLE_TIMER BIT7
- #define FRC1_AUTO_LOAD BIT6
- //TIMER PREDIVED MODE
- typedef enum {
- DIVDED_BY_1 = 0, //timer clock
- DIVDED_BY_16 = 4, //divided by 16
- DIVDED_BY_256 = 8, //divided by 256
- } TIMER_PREDIVED_MODE;
- typedef enum { //timer interrupt mode
- TM_LEVEL_INT = 1, // level interrupt
- TM_EDGE_INT = 0, //edge interrupt
- } TIMER_INT_MODE;
- typedef enum {
- FRC1_SOURCE = 0,
- NMI_SOURCE = 1,
- } FRC1_TIMER_SOURCE_TYPE;
- static void (* user_hw_timer_cb)(void) = NULL;
- static u8 TimeType = 0;
- static u8 AutoLoad = 0;
- static u8 Cando = 0;
- static void hw_timer_isr_cb(void)
- {
- //if(user_hw_timer_cb!=NULL)
- // (*(user_hw_timer_cb))();
- if(AutoLoad == 1)
- {
- if (user_hw_timer_cb != NULL) {
- (*user_hw_timer_cb)();
- }
- }
- else if(AutoLoad == 0)
- {
- if(Cando)
- {
- Cando = 0;
- if (user_hw_timer_cb != NULL) {
- (*user_hw_timer_cb)();
- }
- }
- }
- }
- /******************************************************************************
- * FunctionName : hw_timer_arm
- * Description : set a trigger timer delay for this timer.
- * Parameters : uint32 val :
- in autoload mode
- 50 ~ 0x7fffff; for FRC1 source.
- 100 ~ 0x7fffff; for NMI source.
- in non autoload mode:
- 10 ~ 0x7fffff;
- * Returns : NONE
- *******************************************************************************/
- void hw_timer_arm(u32 val)
- {
- RTC_REG_WRITE(FRC1_LOAD_ADDRESS, US_TO_RTC_TIMER_TICKS(val));
- if(AutoLoad == 0)
- {
- Cando = 1;
- }
- }
- /******************************************************************************
- * FunctionName : hw_timer_set_func
- * Description : set the func, when trigger timer is up.
- * Parameters : void (* user_hw_timer_cb_set)(void):
- timer callback function,
- * Returns : NONE
- *******************************************************************************/
- void hw_timer_set_func(void (* user_hw_timer_cb_set)(void))
- {
- user_hw_timer_cb = user_hw_timer_cb_set;
- }
- /******************************************************************************
- * FunctionName : hw_timer_init
- * Description : initilize the hardware isr timer
- * Parameters :
- FRC1_TIMER_SOURCE_TYPE source_type:
- FRC1_SOURCE, timer use frc1 isr as isr source.
- NMI_SOURCE, timer use nmi isr as isr source.
- u8 req:
- 0, not autoload,
- 1, autoload mode,
- * Returns : NONE
- *******************************************************************************/
- void ICACHE_FLASH_ATTR hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type,u8 req)
- {
- if(req == 1){
- RTC_REG_WRITE(FRC1_CTRL_ADDRESS, FRC1_AUTO_LOAD|
- DIVDED_BY_16
- | FRC1_ENABLE_TIMER
- | TM_EDGE_INT);
- AutoLoad = 1;
- }
- else{
- RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
- DIVDED_BY_16
- | FRC1_ENABLE_TIMER
- | TM_EDGE_INT);
- AutoLoad = 0;
- }
-
- if(source_type == NMI_SOURCE)
- {
- // #define NMI_SOURCE_SEL_REG 0x3ff00000
- // WRITE_PERI_REG(NMI_SOURCE_SEL_REG, (READ_PERI_REG(NMI_SOURCE_SEL_REG)&~0x1F)|(0x1+0x7*2) );
- // NmiTimSetFunc(hw_timer_isr_cb);
- ETS_FRC_TIMER1_NMI_INTR_ATTACH(hw_timer_isr_cb);
- TimeType = 1;
- }
- else{
- ETS_FRC_TIMER1_INTR_ATTACH( hw_timer_isr_cb,NULL);
- TimeType = 0;
- }
-
- TM1_EDGE_INT_ENABLE();
- ETS_FRC1_INTR_ENABLE();
- }
- void hw_timer_stop(void)
- {
- //RTC_REG_WRITE(FRC1_CTRL_ADDRESS,DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
- os_printf("hw tim stop\n");
- // RemoveNmiISR();
- hw_timer_init(1, 0);
- // hw_timer_set_func(NULL);
- //hw_timer_arm(150);
-
- }
- //-------------------------------Test Code Below--------------------------------------
- #if 0
- Example1:
- #define REG_READ(_r) (*(volatile uint32 *)(_r))
- #define WDEV_NOW()\
- REG_READ(0x3ff20c00)
- static u32 tick_now2 = 0;
- void hw_test_timer_cb(void)
- {
- static uint16 j = 0;
- j++;
-
- if( (WDEV_NOW() - tick_now2) >= 1000000 )
- {
- static u32 idx = 1;
- tick_now2 = WDEV_NOW();
- os_printf("b%u:%d\n",idx++,j);
- j = 0;
- }
- //hw_timer_arm(50);
- }
- typedef enum {
- FRC1_SOURCE = 0,
- NMI_SOURCE = 1,
- } FRC1_TIMER_SOURCE_TYPE;
- void ICACHE_FLASH_ATTR user_init(void)
- {
- hw_timer_init(FRC1_SOURCE,1); //hw_timer_init(NMI_SOURCE,1);
- hw_timer_set_func(hw_test_timer_cb);
- hw_timer_arm(100);
- }
- Example2:
- /*
- Do not use ICACHE_FLASH_ATTR before this ISR Callback
- static void ICACHE_FLASH_ATTR stepper_timer_cb(void) is WRONG
- */
- static void stepper_timer_cb(void)
- {
- static u16 j=100;
- if(j-- ==0)
- {ets_printf("z%u\n",j); j=100;}
- hw_timer_arm(2500);
- }
- void ICACHE_FLASH_ATTR user_init(void)
- {
- hw_timer_init(0,0);
- hw_timer_set_func(stepper_timer_cb);
- hw_timer_arm(2500);
- }
- #endif
- /*
- NOTE:
- 1 if use nmi source, for autoload timer , the timer setting val can't be less than 100.
- 2 if use nmi source, this timer has highest priority, can interrupt other isr.
- 3 if use frc1 source, this timer can't interrupt other isr.
- */
- #endif
|