nRF54L15 Errata 24, also applicable for wrap-around of counter?

I see this errata: https://docs.nordicsemi.com/bundle/errata_nRF54L15_Rev2/page/ERR/nRF54L15/Rev2/latest/anomaly_L15_24.html#anomaly_L15_24

It says this:

"Symptoms

The PPI enabled by PUBLISH_COMPARE[n] is not generated.

Conditions

DPPI channel is using TIMER EVENTS_COMPARE as an event with CC[n]=1.

Consequences

The PPI is missing.

Workaround

Apply one of the following workarounds:
  • Do not use CC=1.
  • Use SHORT register to stop and clear TIMER.
  • Use PPI and START and CLEAR tasks at the same time."

First, I haven't been able to reproduce the issue, given the stated conditions. For example, I tried with this code but the event seems to be generated despite the conditions are satisfied:

#define DPPI_EN(chidx) ((chidx) | (1U << 31))

NRF_TIMER10->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
NRF_TIMER10->PRESCALER = 4;
NRF_TIMER10->MODE = TIMER_MODE_MODE_Timer;
NRF_TIMER10->TASKS_CLEAR = 1;
NRF_TIMER10->TASKS_STOP = 1;
NRF_TIMER10->EVENTS_COMPARE[0] = 0;
NRF_TIMER10->CC[0] = 1;

NRF_EGU10->EVENTS_TRIGGERED[0] = 0;

NRF_TIMER10->PUBLISH_COMPARE[0] = DPPI_EN(0);
NRF_EGU10->SUBSCRIBE_TRIGGER[0] = DPPI_EN(0);
NRF_DPPIC10->CHENSET = DPPIC_CHENSET_CH0_Msk;

NRF_TIMER10->TASKS_START = 1;
while (!NRF_EGU10->EVENTS_TRIGGERED[0]) {
}

// this line is reached

Are there any additional conditions that need to be fulfilled in order to reproduce this?


In any case, the workarounds suggest/hint that the problem seem to relate to what happens when the timer is cleared (reset to 0) and the CC is set to 1, i.e. one tick just after. But is this the only scenario when the issue can be observed? I am particularly wondering about the scenario where the TIMER has been running for quite some time, then we set CC[n]=1 and wait for this event to be triggered just after the counter has wrapped around. Let's say we simply set CC[n] to current timer value + x, and this happens to be 1 modulo 2^32. Can the issue be observed also in this case? In that case, we need to always check when the result would be 1 modulo 2^32 and in that case, set some other value, e.g. 0 or 2 instead. Is this needed? Is this done e.g. by all the nrf sdks?

Parents
  • Hi,

     

    Thank you for sharing the code and how to reproduce (or; not to reproduce) the erratum scenario.

    I see the same as you, even when I try to adjust back-and-forth to try to recreate the scenario.

     

    Here is my current test:

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <soc.h>
    #define DPPI_EN(x) ((1 << 31) | x)
    
    #define TEST_TIMER 	NRF_TIMER10
    #define TEST_EGU	NRF_EGU10
    #define TEST_EGU_IRQn	EGU10_IRQn
    #define TEST_DPPIC	NRF_DPPIC10
    #define WAIT_STATE()	(void)NRF_TIMER20->EVENTS_COMPARE[0]
    
    volatile bool irq_triggered = false;
    volatile uint32_t cnt;
    
    void egu_handler(void)
    {
    	cnt++;
    	irq_triggered = true;
    	TEST_EGU->EVENTS_TRIGGERED[0] = 0;
    }
    
    int main(void)
    {
    	IRQ_CONNECT(TEST_EGU_IRQn, IRQ_PRIO_LOWEST, egu_handler, NULL, 0);
    	irq_enable(TEST_EGU_IRQn);
    	printf("Hello World! %s\n", CONFIG_BOARD_TARGET);
    	for (int i = 0; i < 100; i ++) {
    		TEST_TIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
    		TEST_TIMER->PRESCALER = 0;
    		TEST_TIMER->MODE = TIMER_MODE_MODE_Timer;
    		TEST_TIMER->TASKS_CLEAR = 1;
    		TEST_TIMER->TASKS_STOP = 1;
    		TEST_TIMER->EVENTS_COMPARE[0] = 0;
    		//TEST_TIMER->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk | TIMER_SHORTS_COMPARE0_STOP_Msk;
    		TEST_TIMER->CC[0] = 1;
    		WAIT_STATE();
    		TEST_EGU->EVENTS_TRIGGERED[0] = 0;
    		WAIT_STATE();
    		TEST_TIMER->PUBLISH_COMPARE[0] = DPPI_EN(0);
    		TEST_EGU->SUBSCRIBE_TRIGGER[0] = DPPI_EN(0);
    		TEST_EGU->INTENSET = (1 << 0);
    		WAIT_STATE();
    		TEST_DPPIC->CHENSET = DPPIC_CHENSET_CH0_Msk;
    		WAIT_STATE();
    		TEST_TIMER->TASKS_START = 1;
    		while (irq_triggered == false)
    		{
    		}
    		irq_triggered = false;
    		//printf("%d\n", i);
    	}
    	printf("Hello again! %s Count: %d\n", CONFIG_BOARD_TARGET, cnt);
    	return 0;
    }
    

     

    I have asked internally if there is a condition missing from the erratum in question, and for them to comment on the test case you shared.

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    Thank you for sharing the code and how to reproduce (or; not to reproduce) the erratum scenario.

    I see the same as you, even when I try to adjust back-and-forth to try to recreate the scenario.

     

    Here is my current test:

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <soc.h>
    #define DPPI_EN(x) ((1 << 31) | x)
    
    #define TEST_TIMER 	NRF_TIMER10
    #define TEST_EGU	NRF_EGU10
    #define TEST_EGU_IRQn	EGU10_IRQn
    #define TEST_DPPIC	NRF_DPPIC10
    #define WAIT_STATE()	(void)NRF_TIMER20->EVENTS_COMPARE[0]
    
    volatile bool irq_triggered = false;
    volatile uint32_t cnt;
    
    void egu_handler(void)
    {
    	cnt++;
    	irq_triggered = true;
    	TEST_EGU->EVENTS_TRIGGERED[0] = 0;
    }
    
    int main(void)
    {
    	IRQ_CONNECT(TEST_EGU_IRQn, IRQ_PRIO_LOWEST, egu_handler, NULL, 0);
    	irq_enable(TEST_EGU_IRQn);
    	printf("Hello World! %s\n", CONFIG_BOARD_TARGET);
    	for (int i = 0; i < 100; i ++) {
    		TEST_TIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
    		TEST_TIMER->PRESCALER = 0;
    		TEST_TIMER->MODE = TIMER_MODE_MODE_Timer;
    		TEST_TIMER->TASKS_CLEAR = 1;
    		TEST_TIMER->TASKS_STOP = 1;
    		TEST_TIMER->EVENTS_COMPARE[0] = 0;
    		//TEST_TIMER->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk | TIMER_SHORTS_COMPARE0_STOP_Msk;
    		TEST_TIMER->CC[0] = 1;
    		WAIT_STATE();
    		TEST_EGU->EVENTS_TRIGGERED[0] = 0;
    		WAIT_STATE();
    		TEST_TIMER->PUBLISH_COMPARE[0] = DPPI_EN(0);
    		TEST_EGU->SUBSCRIBE_TRIGGER[0] = DPPI_EN(0);
    		TEST_EGU->INTENSET = (1 << 0);
    		WAIT_STATE();
    		TEST_DPPIC->CHENSET = DPPIC_CHENSET_CH0_Msk;
    		WAIT_STATE();
    		TEST_TIMER->TASKS_START = 1;
    		while (irq_triggered == false)
    		{
    		}
    		irq_triggered = false;
    		//printf("%d\n", i);
    	}
    	printf("Hello again! %s Count: %d\n", CONFIG_BOARD_TARGET, cnt);
    	return 0;
    }
    

     

    I have asked internally if there is a condition missing from the erratum in question, and for them to comment on the test case you shared.

     

    Kind regards,

    Håkon

Children
No Data
Related