Difference between revisions of "Nrf52-timer-config"
Line 1: | Line 1: | ||
+ | |||
Line 137: | Line 138: | ||
== [[#top|^]] SIMPLE_TIMER definition == | == [[#top|^]] SIMPLE_TIMER definition == | ||
− | <code>nrf_drv_timer_t</code> is a typedef of <code></code> | + | <code>nrf_drv_timer_t</code> is a typedef of <code>nrfx_timer_t</code>, defined in ./modules/nrfx/drivers/include/nrfx_timer.h |
+ | |||
+ | <pre> | ||
+ | </pre> | ||
+ | |||
+ | <!-- comment --> | ||
+ | |||
+ | == [[#top|^]] Sources and leads to review == | ||
+ | Things to review: | ||
+ | |||
+ | * Following code seems to reference timer task counting, might this relate to using two or more capture/compare registers with a given nRF timer? | ||
+ | |||
+ | ./components/libraries/experimental_libuarte/nrf_libuarte.c:183: nrfx_timer_task_address_get(&p_libuarte->timer, NRF_TIMER_TASK_COUNT), | ||
+ | |||
+ | * Let's look into this as well, code to obtain address of a timer task: | ||
+ | |||
+ | ./integration/nrfx/legacy/nrf_drv_timer.h:107:#define nrf_drv_timer_task_address_get nrfx_timer_task_address_get | ||
+ | <!-- comment --> |
Revision as of 17:28, 26 April 2021
2021-04-25
Looking at some example code in nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/components/app_simple_timer.c
, there are routines to init, start, stop (pause) and to uninitialize. Given a task to assure that a Nordic chip goes into lower or lowest possible power mode, we'll first examine the 'stop' and 'uninit' routines in this Nordic demo code.
The routine uint32_t app_simple_timer_stop(void)
is a wrapper to nrf_drv_timer_pause(nrfx_timer_t const * const p_instance)
. Going through reverse engineering steps this routine is first defined via a macro:
./integration/nrfx/legacy/nrf_drv_timer.h:82:#define nrf_drv_timer_pause nrfx_timer_pause
The definition of nrfx_timer_pause()
is in the following .c file,
./modules/nrfx/drivers/include/nrfx_timer.h:186:void nrfx_timer_pause(nrfx_timer_t const * const p_instance); ./modules/nrfx/drivers/src/nrfx_timer.c:170:void nrfx_timer_pause(nrfx_timer_t const * const p_instance)
First Nordic demo code directories in which we're reviewing files:
nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/components/libraries/simple_timer nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/modules nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/modules/nrfx/drivers/include nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/modules/nrfx/drivers/src nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/integration/nrfx/legacy
Something interesting in file nrfx_timer.c, looks like a compile time evaluation may determine the size of an array of time_control_block_t
types:
64 static timer_control_block_t m_cb[NRFX_TIMER_ENABLED_COUNT];
. . . sure enough, in ../include/nrfx_timer.h
there is an enum whose members are conditionally compiled. Clever!:
enum { #if NRFX_CHECK(NRFX_TIMER0_ENABLED) NRFX_TIMER0_INST_IDX, #endif #if NRFX_CHECK(NRFX_TIMER1_ENABLED) NRFX_TIMER1_INST_IDX, #endif #if NRFX_CHECK(NRFX_TIMER2_ENABLED) NRFX_TIMER2_INST_IDX, #endif #if NRFX_CHECK(NRFX_TIMER3_ENABLED) NRFX_TIMER3_INST_IDX, #endif #if NRFX_CHECK(NRFX_TIMER4_ENABLED) NRFX_TIMER4_INST_IDX, #endif NRFX_TIMER_ENABLED_COUNT };
So the first demo routine of interest, to pause or equivalently stop a timer is:
void nrfx_timer_pause(nrfx_timer_t const * const p_instance) { NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED); nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_STOP); NRFX_LOG_INFO("Paused instance: %d.", p_instance->instance_id); }
We're looking at this to determine whether stopping a timer removes power from the timer peripheral in the nRF52 SoC. Looks like there is another layer of routine nesting with the call here to nrf_timer_task_trigger()
. There may be some clue as to how this routine works, and possibly one of the parameters it accepts will power off a given timer. Here are all calls to it in the nrfx/drivers directory:
ted@localhost$ ./nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/modules/nrfx/drivers $ grep -nr nrf_timer_task_trigger ./* ./src/nrfx_timer.c:144: nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START); ./src/nrfx_timer.c:152: nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_SHUTDOWN); ./src/nrfx_timer.c:166: nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START); ./src/nrfx_timer.c:173: nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_STOP); ./src/nrfx_timer.c:180: nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_CLEAR); ./src/nrfx_timer.c:188: nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_COUNT); ./src/nrfx_timer.c:197: nrf_timer_task_trigger(p_instance->p_reg,
From the file ./hal/nrf_timer.h
looks also like nrf_timer_task_trigger() is normally an in-lined routine:
#ifndef SUPPRESS_INLINE_IMPLEMENTATION __STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_reg, nrf_timer_task_t task) { *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; }
So this routine writes a timer peripheral control register with the value 1. Seems a little odd, is there some syntax I am misreading here? . . .
Contents
^ nRF5x shutting down timer
Well here is something interesting and promising, the comment along side the following definition of NRF_TIMER_TASK_SHUTDOWN
implies that this action powers off the timer:
/nRF5SDK153059ac345/nRF5_SDK_15.3.0_59ac345/modules/nrfx $ grep -nr NRF_TIMER_TASK_SHUTDOWN ./* ./drivers/src/nrfx_timer.c:152: nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_SHUTDOWN); ./hal/nrf_timer.h:108: NRF_TIMER_TASK_SHUTDOWN = offsetof(NRF_TIMER_Type, TASKS_SHUTDOWN), ///< Task for powering off the timer.
So then where and how is offsetof()
defined?
^ offsetof() routine definition
Looks like this offsetof()
is defined in components/libraries/util/app_util.h:
./components/libraries/util/app_util.h:190:#undef offsetof ./components/libraries/util/app_util.h:191:#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
Here are the lines and some conditional directives to activate or disable the possible redefinition of offsetof()
:
187 /*Segger embedded studio originally has offsetof macro which cannot be used in macros (like STATIC_ASSERT). 188 This redefinition is to allow using that. */ 189 #if defined(__SES_ARM) && defined(__GNUC__) 190 #undef offsetof 191 #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) 192 #endif
A couple of references to explain offsetof() purpose:
- https://gcc.gnu.org/onlinedocs/gcc/Offsetof.html
- https://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtin-offsetof-operator#:~:text=The%20purpose%20of%20a%20built-in%20__offsetof%20operator%20is,when%20%28%26lvalue%29%20returned%20the%20address%20of%20that%20rvalue.
^ SIMPLE_TIMER definition
nrf_drv_timer_t
is a typedef of nrfx_timer_t
, defined in ./modules/nrfx/drivers/include/nrfx_timer.h
^ Sources and leads to review
Things to review:
- Following code seems to reference timer task counting, might this relate to using two or more capture/compare registers with a given nRF timer?
./components/libraries/experimental_libuarte/nrf_libuarte.c:183: nrfx_timer_task_address_get(&p_libuarte->timer, NRF_TIMER_TASK_COUNT),
- Let's look into this as well, code to obtain address of a timer task:
./integration/nrfx/legacy/nrf_drv_timer.h:107:#define nrf_drv_timer_task_address_get nrfx_timer_task_address_get