Program determinism when toggling a pin
- January 28, 2020
- 2 replies
- 1326 views
Hello,
I have a strange behaviour that I cannot explain. It is regarding the determinism of running code.
My setup is simple. I have a save routine that save some setup in two seperate pages (two copys of same data). So my saveroutine consists of one write function that is called twice with different adressoffsets and then stores some 60 values. Nothing wild, just a simple copy.
Now I wanted to check how long the writeing takes. Naturally I would expect the write routine to take amount N time and the entire save 2xN (give or take a few µs). Interrupts are deactivated during the entire save.
Case 1: I set the pin at the beginning of the entire save and reset it at the end. I measure a time of 22 ms.
Case 2: I set the pin at the start of each of the two write routines and reset it at the end of each routine. I would have expectet two puleses of about 11 ms. But I get two puleses with 22 ms and a pause inbetween of 10 ms. Note that the only thing I changed in the code is the Line for changing pin state.
Case 3: I set the pin in the start of the entire save. Then reset it at the beginning of each write and set it again at the end of each write. Then reseting it at the end of the entire save. Now I get three small 0.7 µs peaks with 31 ms appart.
Case 4: To see how long a pin toggle takes I added some pintoggles at the end of Case 1. just some
GPIOB->BRR = 1<<12;
GPIOB->BSRR = 1<<12;
GPIOB->BRR = 1<<12;
GPIOB->BSRR = 1<<12;
GPIOB->BRR = 1<<12;
GPIOB->BSRR = 1<<12;
GPIOB->BRR = 1<<12;
and then I got a 22 ms pulse (like in case 1). A 40 ms pause and then the three pulses with just ~28 ns inbetween.
So all four cases run the same code exept for the line of pin toggling. And all cases (except 1 and 4) give me totally different pulse patterns. How is this explained?
void save(void)
{
uint32_t Interrupts0 = NVIC->Active[0];
NVIC->Disable[0] = Interrupts0;
uint32_t Interrupts1 = NVIC->Active[1];
NVIC->Disable[1] = Interrupts1;
GPIOB->BSRR = 1<<12;
uint32_t temp1 = read(OFFSET_PAGE_1 + FADR_SAVE_INIT_DONE);
uint32_t temp2 = read(OFFSET_PAGE_2 + FADR_SAVE_INIT_DONE);
if(temp1 == 0xFFFFFFFF)
{
_save(OFFSET_PAGE_1);
if(write_page == 0) _save(OFFSET_PAGE_2);
}else if(temp2 == 0xFFFFFFFF){
_save(OFFSET_PAGE_2);
if(write_page == 0) _save(OFFSET_PAGE_1);
}else if(temp1 > temp2){
_save(OFFSET_PAGE_2);
if(write_page == 0) _save(OFFSET_PAGE_1);
}else{
_save(OFFSET_PAGE_1);
if(write_page == 0) _save(OFFSET_PAGE_2);
}
if(write_page != 0) error(CONTROL_ERROR_WRITE);
GPIOB->BRR = 1<<12;
GPIOB->BSRR = 1<<12;
GPIOB->BRR = 1<<12;
GPIOB->BSRR = 1<<12;
GPIOB->BRR = 1<<12;
GPIOB->BSRR = 1<<12;
GPIOB->BRR = 1<<12;
NVIC->Enable[1] = Interrupts1;
NVIC->Enable[0] = Interrupts0;
}