I have one task that periodically writes data by sector to 1MB flash memory until it is full. For each 4K sector, the sector is first erased and then 4K of data (16x by 256 bytes) is written to it using the Write function. After that, the built-in LED starts flashing. This is my modification of the example for SAMA5D2C-XULT for ATSAMD21-XPRO.
The program works, but I can’t use the vTaskDelayUntil() function to ensure that the sectors are written at a 100 ms frequency.
case APP_STATE_WRITE_WAIT:
{
if (appData.isTransferDone == true)
{
appData.isTransferDone = false;
write_index += appData.geometry.eraseBlockSize;
if (write_index == DRV_AT25DF_FLASH_SIZE) { // Reached ond of 1 MB flash ?
appData.state = APP_STATE_SUCCESS; // We are at end of 1 MB flash
} else {
appData.state = APP_STATE_INIT_DONE;
}
}
else if (DRV_AT25DF_TransferStatusGet(appData.handle) == DRV_AT25DF_TRANSFER_STATUS_ERROR)
{
appData.state = APP_STATE_ERROR;
}
vTaskDelayUntil(&xLastWakeTime, xFrequency);
break;
}
It seems now the program is working as expected i.e. one sector (4K) of flash memory is written each 100 ms.
Image 1 (I am not allowed to insert oscilloscope image)
The writing one sector of flash memory takes 82.2 ms, so I would expect to set vTaskDelayUntil to 18 ms. Because of some code overhead and tight timing I had to use 11 ms instead to achieve an approx 100 ms interval which is slightly increasing over the time.
I would expect that FreeRTOS scheduler will start that task at the exact 100 ms intervals without the need to use vTaskDelayUntil. Any thought about it?
Detail of timing:
Image 2 (I am not allowed to insert oscilloscope image)
If you are writing to the processor flash, on many processors, doing that while running from the flash will stall the processor until the operation finishes, so you may miss a lot of the tick interrupts.
I don’t think so. The writing of on sector (4k) which includes to erase the sector takes 82.2 ms. When I set the single task to 100 ms there is enough time to do the job.
I don’t understand why it is necessary to use the vTaskDelay function in FreeRTOS instead of setting the task 1 to be executed e.g. every 100 ms, task 2 every 50 ms and task 3 every 500 ms. Using vTaskDelay to achieve inaccurate task timing is nonsense.
The other task may not block the tick interrupt (or are you saying at the same time?)
Also, you are NOT using vTaskDelay in your sample program, but vTaskDelayUntil, which works a bit differently. That uses code that times the delay from the previous scheduled point, so should give you a consistent rate. I will note that time is given in “Ticks”, not milli-seconds, so if your tick rate is about 9-10ms per tick, you would get wha you see.
The reason you need to explicitly use a delay function is otherwise how would anything know where to make your program delay until the next time (or what that delay should be).
Using vTaskDelayUntil WILL give as accurate timing as possible, at the point the call is made.
Would you please elaborate this part? How do you want to set task1 to execute every 100 ms, task2 to 550ms and so on? What is your tick rate? Does the tick interrupt keep firing when the flash write is in progress?
I think I may try to program my own RTOS. Simply setting the TC (Timer Counter) to period 1 ms and enable the IRQ when the TC compare/capture channels (CC) for each task set time delay eg. 100 ms, 50 ms and 500 ms
The rest will be to enable time sharing of three tasks i.e. to run task according to their priorities and blocking them till IRQ TC_CC for a particular task will occur.
From my point of view, I don’t care if the task takes e.g. 100 ms. For me it is more important that the task always runs every 100 ms if possible. The obvious assumption is that it must take less than 100 ms to execute.
You don’t need a new RTOS to do that, it is easy to program in FreeRTOS. Setup a couple of Software Timers with the Timer module that do a Task Notification at the desired rate. Have your tasks just do a wait for Notification, and they we be continued at your desired rate.
Using vTaskDelayUntil should do exactly the same thing. If it isn’t, then your flash writes are actually blocking the processor for extended periods of time.
Actual sector writes to flash memory (first sector erase and than 16x 256 B data writes) takes 82.2 ms gap 17.2 ms, but I had to use 11 ms for vTaskDelayUntil to get approx. 100 ms intervals.
I am working on amateur rocket flight and control computer. Each 10 ms IRQ pulse triggered by Bosch BMI160 6DoF IMU I will get data (1.3 ms), than I need them to store to flash memory for post flight data analyses and servo PWM control 4 rocket wings to achieve stable flight without rotation.
It seems that for it I don’t need to use FreeRTOS but simple loop, timer and some IRQ.
I will probably use 16 Mb FRAM Memory EM016LXQAB313CS1T from Everspin Technologies, which don’t need to erase before write and can achieve up to 133 MHz SPI write speed. Writing of 256 bytes will take 42.7 µs @48MHz.
The mere fact that you are using 11 ms for vTaskDelayUntil tells me that your system is being hung up in a way that makes it non-responsive to interrupts for that 82 ms period.
That being so, there is NO way to “share” that time.
Either the routine you are using is disabling interrupts for that period, or this is the internal flash on the system and pausing the system execution for that period.
Note, you comment that you will “Time Share your three tasks”, that doesn’t easily happen with a “Big Loop” program, as each task once started won’t give up time to a higher priority operation that wants to run.
IF I am right that your flash write is blocking all interurrupts for that 82 ms, then there is no way that you can have a task run at a 50 ms period, as you have an 82 ms uninterruptible block.
There are certainly more than the flash write task running in your system, and interrupt handlers too? What are the relative priorities of those tasks/isrs?
In real time design, you need to consider every strand of execution that takes up CPU cycles. You may want to run your application under control of Tracealyzer, that will answer all of your timing questions sufficiently.
One more thought: As @aggarg already asked - what is your tick rate? If it is set very high, the sys tick timer irq may starve out your flash writing code; if, on the other hand, interrupts are disabled during flash write (as may very well be the case), you may lose ticks which may seriously throw off your timing.
1 ms sys tick frequency is fairly taxing on your plaform.
So you say your flash write cycle is 82ms and must be retriggered every 100ms. That leaves 18ms for the CPU to do everything else per cycle. At 1ms sys tick time, You need 100 timer ticks to complete during that time, computing to 18ms/100 = 180us per ISR AND overhead (eg decision whether to swetch tasks if configured preemptive) if you need to keep your 100ms deadline. If my math is correct, at 48MHz (which is the maximum frequency supported by the Cortex M0+ core) you have 864000 CPU cycles in the 18ms ~ 8640 cycles for each turnaround cycle - and remember, all of this assumes that the CPU does nothing else but write to the flash and do the bookkeeping for the OS. That is not very many cycles. You may want to experiment with optimization levels to cut down on the execution time; on Cortex PODs optimization can cause performance (runtime cycle count vs. ROM footprint) differences in the magnitude of several 10,000!
But, as Richard and I suggested earlier - if your flash write cycle indeed takes up 82ms AND there is reason to believe that those cycles are not interrupted, your problem is much graver as during the flash write, you lose 82% of your timer ticks (timer interrupts disabled). Since the timer ticks are the reference for the OS to compute timer expiration deltas, everything based on it (eg vTaskDelay/vTaskDelayUntil) will NOT work as expected; furthermore, all other timing based on the OS timer tick will be off.
You could rewrite the OS to use, say, a free running cycle counter as the reference for computing your delay deltas, but be aware that whichever platform you use, trying to squeeze everything else BUT the flash write code into 18ms in between your cycles is a very ambitious endeavour, especially on a slow processor like the M0+. Looks like your choice of HW platform may be suboptimal if your timing requirements are not negotiable.
My guess is that the SPI driver does a lot of work in an ISR that is set to a priority above the Tick, and is blocking the tick from running. The SPI bus is likely running fast enough that an interrupt driven data pump will stay in the ISR for the full period of the message being sent/received,
I bet if the GPIO toggle was added to a tick hook function, that toggling would stop during the message transmission,