dibosco wrote on Thursday, February 14, 2013:
I suspect my question is largely a question of naivety so please be gentle!
I have a set up where I am successfully reading files from an SD card, but I need to make it more efficient. I believe that I should be reading a sector of my SD card in 48us, so with files that are 2048 bytes long should, best case scenario take around 192us. They are not and I am pretty sure I know why, it’s just a case of how to fix this elegantly in FreeRTOS.
So, my sector read routine, sends the applicable command out to the SD card and just waits for the 512 bytes to be read from the SD card. I figured that although this wasn’t efficient at all in a run-to-complete program, with FreeRTOS, the OS would switch out of the thread that was calling the sector read routine and then come back at the next time slice by which time that sector would be read. This does work and it works very nicely; the problem I have is that now we are upping the rate this read data is sent out of the serial port, I am waiting for the next file to be read from the SD card. It’s actually taking many milliseconds to read s small file. I guess this is understandable because the fat file reading thread will be doing the following in pseudo-code:
Open file
while sector to read
{
Start DMA to read sector
Wait for sector <-- presumably task switching here
}
File is read and is available to send out to our screen.
Now, with all this context switching, I am sure that is why it’s taking so long to read file (and the files are about to go up to 3k, not 2k, to further compound this).
So, I am wondering what is the way to do this to make this as elegant and fast as possible. Once I have requested a sector read and the thread is just sat waiting for the DMA completion there is no point in it sitting there eating up processor time I would think. So, is it wise/possible to force a context switch at this point? Or will it happen automatically? In some ways a wait of 192us seems nothing when a time slice is 1ms and therefore much longer. So, I am actually wondering whether FreeRTOS is smart enough to switch anyway when it’s waiting like that (for a DMA transfer completion).
I have a feeling that I should be setting a DMA handler and doing something that wakes the appropriate thread ASAP but I must confess my understand of this is hazy. I am not sure enough of this hunch to plough on down this route without asking though. Also, with the USART routine interrupt examples it only has one byte to pull out of the UART receive, with 512 bytes coming out I’m not clear on how the interrupt routine knows where the DMA controller would have stored that 512 bytes (although this is probably a hardware issue more than a FreeRTOS issue as it’s possible the DMA controller value that was passed to tell the controller the first address to start storing data is kept there and the interrupt routine would know from that register value.
If this interrupt method is the best way, should I simply pass the 512 bytes into a queue and then would the calling FAT routine be woken up straight away the queue was filled? As an aside, would copying 512 bytes into a queue not actually be a pretty hefty waste of time in itself? As far as I understand writing to a queue actually copies data across to the queue and doesn’t just give a pointer to this data I’ve read from the SD card.
I would add that, the routine that is doing the read of the sector on the SD card is a subroutine of a subroutine of a subroutine of…well you get the idea. I assume that doesn’t matter in terms of context switching, but again am not sure about this.
I’m also wondering whether I need to give higher priority to the FAT thread, although whenever I’ve tried something like this I always find the OS gets stuck in the highest priority thread and never comes out!
So, would someone be able to advise on the way to go about something like this please? I hope I have explained this clearly enough, but please ask for clarification if not.
Many thanks in advance.