Difference between revisions of "Nrf52-timer-config"

From Wiki at Neela Nurseries
Jump to: navigation, search
m (^ nRF5x shutting down timer)
(^ offsetof() routine definition)
Line 110: Line 110:
 
== [[#top|^]] offsetof() routine definition ==
 
== [[#top|^]] offsetof() routine definition ==
  
 +
Looks like this <code>offsetof()</code> is defined in components/libraries/util/app_util.h:
  
 +
<pre>
 +
./components/libraries/util/app_util.h:190:#undef offsetof
 +
./components/libraries/util/app_util.h:191:#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
 +
</pre>
 +
 +
Here are the lines and some conditional directives to activate or disable the possible redefinition of <code>offsetof()</code>:
 +
 +
<pre>
 +
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
 +
</pre>
 +
 +
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.
  
 
<!-- comment -->
 
<!-- comment -->

Revision as of 00:12, 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? . . .


^ 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: