3
\$\begingroup\$

I am using a dsPIC33E MUC to interface an UART camera(VGA) at 115.2Kbps. The purpose is to save an image to a SD card.

The program I wrote works well except that it's inside a loop checking if the buffer(512 bytes buffer is for one sector) is full or not. If the buffer is full, it will be written to a SD card. I am wondering how I can adapt this code to a time critical data acquisition project. Since it's UART interrupt driven, I am not sure if the best way to save images to a SD card is to use a flag. Here is the code with the loop checking flag to see if the buffer is full.

unsigned char buff[512];//buffer to store bytes comming from the camera
unsigned int bufferPtr=0;//pointer for the buffer. It will be incremented for each byte
while(1){
    if(bufferPtr==512){Write_Sector(SectorNumber,Buff);}//if the buffer is full, Write a it to SD card
    bufferPtr=0;//reset buffer Pointer so next byte will be save to the beginning of the buffer
}

interrupt routine

void ISR(){
    Uart.FlagBit=0;//clear flag bit first
    buffer[bufferPtr++]=UART_Read();//read a byte and put it into the buffer
}

As you can see, the program is kinda waiting for bytes to arrive and save it to a buffer. It works very well but I have a question about timing. In terms of writing speed, it needs roughly 3.6sec for 2000 sectors(each sector 512 bytes). So writing one sector needs 3600/2000=1.8ms. The baudrate tells me that 115200/10=11520Byte/Sec, which means 11.52 Bytes/ms. How is it possible to write one sector to SD card(needs 1.8ms) without overflowing UART FIFO buffer? During that 1.8ms period, there will be 11.52*1.8=20.736 bytes comming in.

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Buffer = sector RAM buffer. UART buffer = UART internal buffer.

"Just a matter of programming" :-)

I've not looked at the fine detail of your method or specific device resources - the following general solution applies as long as the available RAM is not crucially limited:

Arrival rate is about 1,000,000/ 115,200 uS/bit = 8.68 uS/bit or 87 uS/byte

SD card write rate is 1800 uS/512 bytes ~= 3.5 uS/byte.

So long term if there are no other major overheads you have a write rate far faster than the arrival rate. The only problem is trying to walk and chew gum while storing the buffer.

If you can write SD and read UART easily at the same time you can use an exact size buffer. As long as you get the first byte out of the buffer within 87 uS of it being written the UART will never know you are there.

If the code is very time critical elsewhere you may be able to turn off interupts and poll a "talk to me" flag when you have time. As long as you can do this and respond before the UART buffer is full each time you can win

A death defying high wire method is to work out when the buffer is just full enough that if you start transferring THEN, the UART will deliver the final buffer byte as the SD card requires it. Good luck achieving that. It does have the advantage of not requiring any extra buffer resources IF you can manage it 'just right'.

A far easier method (assuming a wrap around buffer) is to increase the buffer size by enough bytes plus a little more such that when the buffer has enough data in it for an SD write you start writing SD data while the UART writes the "extra" buffer space. When the bufffer writer hits the buffer top it just restarts at buffer bottom, blissfully unaware that you are snaffling 512 byte blocks when they are ready. This requires you to repoint the buffer reader top and bottom pointers and to manage the "buffer full" pointer or counter etc - but is otherwise "trivially easy" [tm].

Easier again is to use two buffers and flip the writer to the other one when the current onbe is full. This doubles the buffer RAM needed which may or may not be a problem.

\$\endgroup\$
3
\$\begingroup\$

Well, code looks almost ok. But, while storing the buffer to SD card, if new byte arrived, you will have a problem. To be on a safe side, you could create a ring buffer of larger size of needed buffer and flush it every xy values.

int head = 0, tail = 0, cnt = 0;
bool overflow = false;
#define BUFFSIZE 1024
char buff [BUFFSIZE];
#define MEMBUFSIZE 512
char memoryBuff[MEMBUFSIZE];

void appendToBuff(char a_byte)
{
   buff[head++] = a_byte;
   if (head >= BUFFSIZE) {
       head = 0;
       }
   if (head == tail) {
       overflow = true;
       flushBuffer();
       }
}
void flushBuffer ()
{
    while (tail != head || overflow){
        overflow = false;
        memoryBuff[cnt++] = buff[tail++];
        if (tail >= BUFFSIZE) tail = 0;
        if (cnt >= MEMBUFSIZE) {
             Write_Sector(SectorNumber,Buff);
             cnt = 0;
             }
        }
}
void main() 
{
    while (1) {
       flushBuffer();
       }
}

i havent try this code, so it might have bug or two, but it will help with an overview what you should handle ...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.