esp-open-rtos/core/include/esp/timer_regs.h

126 lines
3.9 KiB
C
Raw Normal View History

/* esp/timer_regs.h
*
* ESP8266 Timer register definitions
*
* Not compatible with ESP SDK register access code.
*/
#ifndef _ESP_TIMER_REGS_H
#define _ESP_TIMER_REGS_H
#include "esp/types.h"
#include "common_macros.h"
#define TIMER_BASE 0x60000600
#define TIMER(i) (*(struct TIMER_REGS *)(TIMER_BASE + (i)*0x20))
#define TIMER_FRC1 TIMER(0)
#define TIMER_FRC2 TIMER(1)
/* TIMER registers
*
* ESP8266 has two hardware timer counters, FRC1 and FRC2.
*
* FRC1 is a 24-bit countdown timer, triggers interrupt when reaches zero.
* FRC2 is a 32-bit countup timer, can set a variable match value to trigger an interrupt.
*
* FreeRTOS tick timer appears to come from XTensa core tick timer0,
* not either of these. FRC2 is used in the FreeRTOS SDK however. It
* is set to free-run, interrupting periodically via updates to the
* ALARM register. sdk_ets_timer_init configures FRC2 and assigns FRC2
* interrupt handler at sdk_vApplicationTickHook+0x68
*/
struct TIMER_REGS { // FRC1 FRC2
uint32_t volatile LOAD; // 0x00 0x20
uint32_t volatile COUNT; // 0x04 0x24
uint32_t volatile CTRL; // 0x08 0x28
uint32_t volatile STATUS; // 0x0c 0x2c
uint32_t volatile ALARM; // 0x30
} __attribute__ (( packed ));
_Static_assert(sizeof(struct TIMER_REGS) == 0x14, "TIMER_REGS is the wrong size");
#define TIMER_FRC1_MAX_LOAD 0x7fffff
/* Details for LOAD registers */
/* Behavior for FRC1:
*
* When TIMER_CTRL_RELOAD is cleared in TIMER(0).CTRL, FRC1 will
* reload to its max value once underflowed (unless the load
* value is rewritten in the interrupt handler.)
*
* When TIMER_CTRL_RELOAD is set in TIMER(0).CTRL, FRC1 will reload
* from the load register value once underflowed.
*
* Behavior for FRC2:
*
* If TIMER_CTRL_RELOAD is cleared in TIMER(1).CTRL, writing to
* this register will update the FRC2 COUNT value.
*
* If TIMER_CTRL_RELOAD is set in TIMER(1).CTRL, the behaviour
* appears to be the same except that writing 0 to the load register
* both sets the COUNT register to 0 and disables the timer, even if
* the TIMER_CTRL_RUN bit is set.
*
* Offsets 0x34, 0x38, 0x3c all seem to read back the LOAD_REG value
* also (but have no known function.)
*/
/* Details for CTRL registers */
/* Observed behaviour is like this:
*
* * When TIMER_CTRL_INT_HOLD is set, the interrupt status bit
* TIMER_CTRL_INT_STATUS remains set when the timer interrupt
* triggers, unless manually cleared by writing 0 to
* TIMER(x).STATUS. While the interrupt status bit stays set
* the timer will continue to run normally, but the interrupt
* (INUM_TIMER_FRC1 or INUM_TIMER_FRC2) won't trigger again.
*
* * When TIMER_CTRL_INT_HOLD is cleared (default), there's no need to
* manually write to TIMER(x).STATUS. The interrupt status bit
* TIMER_CTRL_INT_STATUS automatically clears after the interrupt
* triggers, and the interrupt handler will run again
* automatically.
*/
/* The values for TIMER_CTRL_CLKDIV control how many CPU clock cycles amount to
* one timer clock cycle. For valid values, see the timer_clkdiv_t enum below.
*/
/* TIMER_CTRL_INT_STATUS gets set when interrupt fires, and cleared on a write
* to TIMER(x).STATUS (or cleared automatically if TIMER_CTRL_INT_HOLD is not
* set).
*/
#define TIMER_CTRL_INT_HOLD BIT(0)
#define TIMER_CTRL_CLKDIV_M 0x00000003
#define TIMER_CTRL_CLKDIV_S 2
#define TIMER_CTRL_RELOAD BIT(6)
#define TIMER_CTRL_RUN BIT(7)
#define TIMER_CTRL_INT_STATUS BIT(8)
typedef enum {
TIMER_CLKDIV_1 = 0,
TIMER_CLKDIV_16 = 1,
TIMER_CLKDIV_256 = 2,
} timer_clkdiv_t;
/* Details for STATUS registers */
/* Reading this register always returns the value in
* TIMER(x).LOAD
*
* Writing zero to this register clears the FRC1
* interrupt status.
*/
/* Details for FRC2.ALARM register */
/* Interrupt match value for FRC2. When COUNT == ALARM,
the interrupt fires.
*/
#endif /* _ESP_TIMER_REGS_H */