This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

About timing in mesh processing

Hello team,

I'm working on system development using Mesh SDK and I have some questions so please let me know.

###############
Development environment
IDE : Segger Embedded Stuido
SoC : nRF52840
SDK : Mesh v2.2.0
          normal SDK v15.0.0
Base project : light switch example (modifying for our system)
###############

1. If a node belonging to a group receives a message for that group address, which of the following will be performed first?
    ・Processing for messages, such as replies
    ・Transfer message to another node
    ・Anything else.


2. There is possiblity to rewrite the same variable in the receive callback of Mesh message and the timer interrupt handler, in main.c.
    As such, I do not want to generate other interrupts during this process, includes receiving mesh messages.
    How can I realize this?
    Are the following functions and macros useful?
    ・CRITICAL_REGION_ENTER () / CRITICAL_REGION_EXIT ()
    ・nrf_mesh_disable () / nrf_mesh_enable ()


3. About interrupt
    As far as the document is referred to, when the Mesh message is received during execution of the application interrupt process,
    the application interrupt is interrupted and the Mesh reception interrupt is processed.
    I think that system will return to the interrupted application interrupt after the processing of the reception interrupt is finished.
    Is this recognition correct?

    I will assume that it is correct and ask a question.
    Is there a way to see this series of processes?
    
    I put a loop processing with an end condition to make the waiting time in the timer interrupt handler.
    I tried sending Mesh messages during looping, but the timer interrupt handler was not interrupted by the receipt of Mesh messages.
    On the contrary, mesh message reception interrupt did not occur even after loop termination.
    Does that mean that the system has not received a message?
    Or did the system receive it but did not put the interrupt on hold?

    The code in the timer interrupt handler is described below for reference.

void timer_handler(void * p_context)
{
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%s called.\n", __func__);
    
    for (uint8_t i = 100; i > 0; i--)
    {
        printf("loop %d\n", i);
    }
}



Thanks in advance.

Wataru

Parents
  • Hi Wataru

    1. First the packet will be decrypted. Then there will be a check to see if it should be relayed, after which the TTL will be decremented, the packet encrypted again, and put in the outgoing packet buffer. 

    After that the packet will be processed locally. 

    Still, depending on the state of the outgoing buffer there might be some delay before the packet is retransmitted, so whether or not this happens before the local processing is impossible to say. 

    2. An interrupt of the same priority as another can not interrupt it. This also means that an interrupt can not interrupt itself. 

    The only thing that can interrupt you when you are in an interrupt handler is another interrupt of higher priority (lower IRQ priority number). 

    If the timer interrupt has a higher interrupt priority than the mesh interrupt then I would suggest disabling this particular interrupt before you access the shared variable. 

    3. If an application interrupt of lower priority is interrupted by the mesh interrupt, then execution will return to the application interrupt after the mesh interrupt is completed, that is correct. An interrupt of similar priority will not be interrupted. 

    You could visualize this by using a debugger with trace functionality, such as the Segger J-Trace.

    Regarding your timer_handler, I expect that this is running at an interrupt priority similar or higher than that of the mesh interrupts, which means you are blocking the mesh operation while sending your messages. This is not recommended, as the mesh will not be able to operate as normal. 

    Maybe you could try to defer the execution to the main context instead, either by using the app_scheduler module, or by setting a flag in the timer_handler that you later check in your main loop?

    Best regards
    Torbjørn

  • Hi, Ovrebekk

    Thanks for your reply. And sorry for the late my reply.

    1. My understanding that the order to execute first is not decided, is it correct?
        (Processing of messages or relaying of messages)

        Even in that case, both processes will be performed?

    2. If an interrupt with the same priority occurs while processing in the interrupt handler,
        will interrupt processing that occurs later be on hold?

        In other words, will interrupt processing that occurs later be executed
        after the current interrupt handler has ended?


    By the way, in the light_example example, what is the priority of mesh interrupts?
    I think the priority is "0". Does that mean not?
    The timer interrupt priority is set to LOWEST (7).

    Although it is not intended, if you can block mesh interrupts,
    do you think that blocking mesh interrupts is not a problem
    if it is an algorithm that can collect data in multiple communications?

    I don't want to do this now because using the app_scheduler is likely to result in many system changes.
    I would like to consider again at the timing of the big update,
    so please inform me about how app_scheduler works and how to use it.

    Best regards
    Wataru

  • HI, Torbjørn

    I'm sorry for my late reply.

    I understand that the interrupt vector only has a status of pending or not.
    By the way, can the status of the interrupt vector be checked by outputting it in LOG during processing?
    In the systems we operate, it has been found that, very rarely, timer interrupts do not occur at the expected time.
    In order to prove this, I want to know the state of the vector table and so on.
    Alternatively, please let me know at the same time if there are other registers useful for debugging.


    Yes, It is a physical transfer by radio.
    There seems to be no problem with message hoping.
    I do not intend to process the contents of the relay message payload.


    I also understood the priority of mesh processing in the main application.
    I was a little surprised at the lowest priority, but it does not interfere with the time critical processing of lower layers.


    Best regards
    Wataru

  • Hi Wataru

    Are you able to connect your kit to an oscilloscope?

    Then you can toggle a pin at the start and end of the interrupt vector, and use the oscilloscope to monitor when the interrupt triggers, and how long it runs. 

    While a bit primitive, this is a very non intrusive and reliable way to measure the interrupt activity. Writing to the log can be quite slow, and might not be able to keep up with the interrupt activity. 

    Best regards
    Torbjørn

  • Hi Torbjørn

    It is possible to connect to an oscilloscope.
    Are you saying to toggle any GPIO when an interrupt occurs?
    If possible, I would like to check the register of each interrupt directly. . .
    Is it impossible to make it with logs?

    I think that the some delay may be tolerance to knowing the status of the interrupt register in software..
    By the way, can you give us information about which register to look at? I would to know this information at least.



    BTW, as I mentioned earlier that no timer interrupt has occurred, is the possibility of my misunderstanding.
    I was doing each processing in a fixed cycle, but rearly, I had not had an event that should have happened on a rare cycle so I judged.

    But, The time stamp output from the LOG in the timer interrupt handler proved that it was operating at the intended interval.

    Is there a possibility that this information (timestamp) is unbelievable?
    If so, I think that means that RTC sometimes stops.

    It has not yet been confirmed that the operation cycle of one timer in the system was correct.
    But I have a question.
    Does it happen occasionally that the timer interrupt generation cycle deviates from the intended one?

    Best regards,
    Wataru

  • Hi Wataru

    Yes, my proposal is to set a pin at the start of the interrupt handler, and clear the pin at the end of the interrupt handler. Then you can see accurately when the interrupt handler starts, and for how long it runs. 

    I am not quite sure what register you are referring to. You should be able to read the pending state of the various interrupts from the ISPR registers in the NVIC peripheral, where each bit stores the pending state of one peripheral. 

    ISPR[0] covers peripheral ID's 0-31, ISPR[1] covers ID's 32-63, and so forth. 

    As for the RTC stopping this won't happen unless you do a system reset, enter system OFF sleep mode, or disable the low frequency clock source from the application. You could also manually stop the RTC from the code, but there is no reason the mesh stack should do this, and I assume you don't access the RTC registers either in the application code?

    In other words I don't see how the timer interrupt generation could be affected, but the execution of the timer handler interrupt could be delayed if a higher priority interrupt is currently running. 

    Best regards
    Torbjørn

  • Hi Torbjørn

    I see. If I need to measure the time it takes to process the interrupt, I follow your idea.

    I did not refer to any register yet.
    I was just looking for information on where to look.
    I searched for the specification of nrf52840, but I did not know which NVIC register should I actually watch .
    In addition, information on peripheral device ID was not found as well. . .


    There is no reset or system OFF status. Even the application does not access the RTC register. (Other than timer)
    At the application level, all interrupt processes are executed with the same priority (7).

    In this case, high priority interrupts are considered to be time critical processes closer to the physical layer, are they correct?


    Best regards, 
    Wataru

Reply
  • Hi Torbjørn

    I see. If I need to measure the time it takes to process the interrupt, I follow your idea.

    I did not refer to any register yet.
    I was just looking for information on where to look.
    I searched for the specification of nrf52840, but I did not know which NVIC register should I actually watch .
    In addition, information on peripheral device ID was not found as well. . .


    There is no reset or system OFF status. Even the application does not access the RTC register. (Other than timer)
    At the application level, all interrupt processes are executed with the same priority (7).

    In this case, high priority interrupts are considered to be time critical processes closer to the physical layer, are they correct?


    Best regards, 
    Wataru

Children
  • Hi Wataru

    How to calculate the peripheral ID is documented here

    As you can see it is based on the base address of each peripheral, which is documented at the top of the "registers" section for each of the peripherals in the nRF52840 (like here for the SPIM modules). 

    If all the application interrupts are executed at the same priority it means they will all have to wait for each other. One will not be able to interrupt another. 

    "In this case, high priority interrupts are considered to be time critical processes closer to the physical layer, are they correct?"

    Yes, this is correct. Normally the timing is more critical the closer you get to the physical layer, and it is the same for Bluetooth mesh. 

    Best regards
    Torbjørn

  • Hi, Torbjørn

    Sorry for my late reply.

    I understood the peripheral ID information to some extent.
    ・Is interrupt pending: ISPR register of NVIC
    ・Whether interrupts are enabled: INTENSET of peripheral register
    ・Whether interrupts are disabled: INTENCLR in peripheral register

    Above is my recognition that where should be confirmed about interruption. Correct?

    Best regards
    Wataru

  • Hi Wataru

    Your understanding is mostly correct, just a small clarification on INTENSET and INTENCLR:

    Both INTENSET and INTENCLR is used to access the internal INTEN register, which is the register that actually enables interrupts. 

    INTENSET allows you to set bits in INTEN, while INTENCLR allows you to clear them. 

    Reading either INTENSET or INTECLR will return the same thing, namely the state of INTEN. 
    It is only when you write to these registers that they behave differently. 

    Best regards
    Torbjørn

  • Hi, Torbjørn

    Thank you for your reply.
    I feel that knowledge about Nordic products is being accumulated little by little. :)

    I prepared a debugging environment to check the register information a little.
    It seems there are peripherals that can and cannot be referenced the INTEN register directory from SDK.
    Is this right?

    I referenced the NRF_TWI0-> ENABLE and NRF_TWI0-> INTENSET register for TWI.
    Before enabling TWI, both registers were "0", and after enabling TWI, ENABLE was "6" and INTENSET was "0".

    The TWI interrupt (NACK event) is generated intentionally, but looking at the register, I do not think that the interrupt is enabled.

    Is something wrong with the operation or understanding?

    Best regards
    Wataru

  • Hi Wataru

    You are correct, the INTEN register can not be accessed directly, only indirectly through the INTENSET and INTENCLR registers. 

    To read INTEN you just need to read INTENSET or INTENCLR, they will return the same thing. 

    To write to INTEN you have to either set or clear bits independently by writing to INTENSET/INTENCLR. 

    How do you enable TWI in your example?

    Do you use one of the standard drivers?

    Best regards
    Torbjørn

Related