Timer group performance

wobblyboots
Posts: 19
Joined: Mon Sep 18, 2017 4:48 pm

Re: Timer group performance

Postby wobblyboots » Fri Sep 22, 2017 1:41 am

And if it helps, here's an openocd log with extra debugging turned on:

Code: Select all

bin/openocd -d 3 -s share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg 2>&1 | tee openocd.log
It certainly seems to me that events are being sent - they just don't seem to be making it into the SVDat file for some reason.
ESP_Alexey wrote:Hi wobblyboots,

Unfortunately I can not reproduce your problem. Could you provide logs from openocd console and also, please, re-upload you SVDat files as usual ones, not in hexdump format.

Regards,
Alexey
Attachments
openocd.log
(2.99 MiB) Downloaded 1034 times

ESP_Alexey
Posts: 24
Joined: Fri Dec 02, 2016 8:55 pm

Re: Timer group performance

Postby ESP_Alexey » Sat Sep 23, 2017 10:41 pm

wobblyboots wrote:And if it helps, here's an openocd log with extra debugging turned on:

Code: Select all

libusb_open() failed with LIBUSB_ERROR_NOT_SUPPORTED
This is from your previous log and it looks strange. I think you need to solve this issue at first.

Visually, your traces looks OK, logs also tells that events are parsed. I will have a deeper look at them. Strange problem... )))

ESP_Alexey
Posts: 24
Joined: Fri Dec 02, 2016 8:55 pm

Re: Timer group performance

Postby ESP_Alexey » Sat Sep 23, 2017 11:32 pm

Ian, could you also check it with most recent version of openocd-esp32?
What OS do you run openocd on?

wobblyboots
Posts: 19
Joined: Mon Sep 18, 2017 4:48 pm

Re: Timer group performance

Postby wobblyboots » Mon Sep 25, 2017 1:22 pm

Hi Alexey,

The LIBUSB errors seem to be a red herring - when I first saw them I searched else where and it seems that Openocd searches for USB devices and tried a few before finding the right one.

I downloaded the latest Openocd-esp32 source from Github for Windows under msys and built it - it's a different version from the pre-built binaries. That adventure I'll document elsewhere to make it easier on others, but it wasn't too painful.

Now I have systemview working! And I have to say, it's a bit like going from guessing what's going wrong talking to an i2c device to having a hardware analyser. Amazing.

The Segger tool Systemview which the readthedocs mentions only in passing - I missed the link initially - is actually much more readable and easy to use than Impulse (and requires much less magic incantations). It's only downside is not having both CPUs visible, but for our purposes here, it is like magic. I had some regular dropped events - presumably there's a buffer I can increase somewhere to get over this, but I have enough data to show things.

Image

So - back to the original problem. Occasional flickering during LED panel refresh.

You can clearly see here that the timer interrupt is firing and shortly after the panel_refresh is called. But notice how it goes into idle in between?

Code: Select all

    EventBits_t mybits = xEventGroupGetBitsFromISR( panel_event_group);
    if (mybits & PANEL_REFRESHING){
        xEventGroupSetBitsFromISR(panel_event_group, PANEL_REFRESH_CLASH, &xHigherPriorityTaskWoken2);
        
    } else {
        xEventGroupSetBitsFromISR(panel_event_group, PANEL_REFRESH_TRIGGER, &xHigherPriorityTaskWoken);
       if( xHigherPriorityTaskWoken) {
            portYIELD_FROM_ISR();
       }
    }
My understanding is that the xHigherPriorityTaskWoken should kick off the yield which should make the actual panel refresh happen pretty much immediately (that task is running at priority 25), but surprise, the "portYIELD_FROM_ISR()" is not being called (confirmed by adding an 'else' to the if statement). The PANEL_REFRESH_CLASH was extra code to try and check if the refresh was being called while the panel was actually being refreshed (it isn't). I'm not sure why FreeRTOS doesn't understand there's a higher priority task, waiting to run. Interesting, and this code is common throughout the IDF, so I'd like to solve it, but that isn't a show stopper.

I am interested in this FROM_CPU1 task is though - and that it's purpose is. I'm just surprised that it's not SysTick-Scheduler-PanelRefresh.

But otherwise, give or take, we have a timer and (shortly thereafter) we have a panel_refresh. Fine.

But have a look at this one:

Image

See how smack in the middle of doing a panel refresh, SysTick pops in to say hello. Now I have tried ALL sorts of things to stop this happening - to be clear I haven't tried these things and run SysView, but the result is the same (flickering), as mentioned in the original post. I really just want SysTick to take a holiday for a moment and let the panel_refresh happen as quickly as possible.

Any thoughts?

kind regards
Ian.

ESP_igrr
Posts: 2071
Joined: Tue Dec 01, 2015 8:37 am

Re: Timer group performance

Postby ESP_igrr » Mon Sep 25, 2017 4:53 pm

A few questions first:

Have you tried running the code in single core mode? That is not the solution, but it would probably make it easier to see the whole situation in Systemview.

Can you paste the line of code you are using in the panel refresh task to wait on panel_event_group?

Is the panel refresh task pinned to a particular core? (i.e. is it created using xTaskCreate or xTaskCreatePinnedToCore?)

Now to the answers.

FROM_CPU1 is an interrupt, not a task — this is indicated by a lightning icon next to it. This interrupt is used in FreeRTOS to notify the scheduler on CPU0 that it may need to re-evaluate which task to run. As the name indicates, this interrupt is triggered on CPU1. There is a similar interrupt, FROM_CPU0, which is used for notifications in the other direction. So if FROM_CPU1 triggers, it means that something has happened on CPU1, that made the scheduler think that CPU0 may need to know about that. Without knowing more about your application, i can't really say what that might be.

Regarding SysTick interrupt interrupting your task, what you can do is try disabling interrupts temporarily. This can be done e.g. using

Code: Select all

uint32_t state = portENTER_CRITICAL_NESTED();
// your code
portEXIT_CRITICAL_NESTED(state);

ESP_Sprite
Posts: 9719
Joined: Thu Nov 26, 2015 4:08 am

Re: Timer group performance

Postby ESP_Sprite » Sat Sep 30, 2017 10:13 am

FWIW I finished ane xample on how to use DMA/I2S-parallel to do the bitshifting to a LED-screen: viewtopic.php?f=17&t=3188

wobblyboots
Posts: 19
Joined: Mon Sep 18, 2017 4:48 pm

Re: Timer group performance

Postby wobblyboots » Mon Oct 02, 2017 7:15 pm

Spectacular sprite_tm - thank you so much for posting. We are digesting this as I write this.

kind regards
Ian.

wobblyboots
Posts: 19
Joined: Mon Sep 18, 2017 4:48 pm

Re: Timer group performance

Postby wobblyboots » Mon Oct 02, 2017 7:21 pm

Thanks ESP_igrr. I switched to single core mode and ... it's rock solid. No flicker. Switch the other core on, and it flickers, about every 10 seconds it goes through a flickering state for a second or so and then returns to normal.

However since sprite has been able to outsource the entire driving of the LED panel to the I2S DMA, including getting a few more bits of brightness on a per-pixel basis we will probably park out efforts here and leapfrog off his work.

In any case, an interesting learning experience.
Ian.
ESP_igrr wrote:A few questions first:

Have you tried running the code in single core mode? That is not the solution, but it would probably make it easier to see the whole situation in Systemview.

Can you paste the line of code you are using in the panel refresh task to wait on panel_event_group?

Is the panel refresh task pinned to a particular core? (i.e. is it created using xTaskCreate or xTaskCreatePinnedToCore?)

Now to the answers.

FROM_CPU1 is an interrupt, not a task — this is indicated by a lightning icon next to it. This interrupt is used in FreeRTOS to notify the scheduler on CPU0 that it may need to re-evaluate which task to run. As the name indicates, this interrupt is triggered on CPU1. There is a similar interrupt, FROM_CPU0, which is used for notifications in the other direction. So if FROM_CPU1 triggers, it means that something has happened on CPU1, that made the scheduler think that CPU0 may need to know about that. Without knowing more about your application, i can't really say what that might be.

Regarding SysTick interrupt interrupting your task, what you can do is try disabling interrupts temporarily. This can be done e.g. using

Code: Select all

uint32_t state = portENTER_CRITICAL_NESTED();
// your code
portEXIT_CRITICAL_NESTED(state);

Who is online

Users browsing this forum: No registered users and 43 guests