Week 08 – HTTP2.c Meets SD-SPI.c
Continuing from the last week, the reason that why the connection will be timed out when uploading a larger file is due to the modification I made to calculate the data size uploaded. The method was removed for the mean time and tested the code out. It turns out that the minor modification to the tightest loop is working partially, some data was written into the SD card successfully with some other garbage data. There are two observations that I found.
- A 512 bytes data must be sent to the SD card while writing. It must then be followed by 2 CRC-bytes. Only then the SD card will save the data in it. If less than 512 bytes were sent and the program deselects the card immediately afterwards, the data will be lost.
- The data located in the EDATA or the TCP buffer, is less than 512 bytes. Because of this, although the connection did not reach a timeout but it stuck in the loop forever. The code given is only capable of exiting the loop if the block counter (that starts at 512) is equal to zero. This is not going to happen because the subtraction process is subtracting a number less than 512 (most likely not a factor of 512 as well) and very likely to put the counter into a negative number and continue subtracting from it. This also affects the writing process because after a block sector is finished up, some additional process are required to prepare the next sector for writing. Details can be found at the following link: How to Use MMC/SDC
Because of these reasons, a new method to integrate the HTTP process and the SD card writing process is required. By hopefully being able to take the easy way out, I tweaked the TCP socket buffer size. By tweaking the socket buffer size which is located in the file “TCPIP ETH97.h”, I was able to alter the buffer size. But soon I realize it is not useful, I was able to get the EDATA to store more than 512 bytes per session but unfortunately, it could not store exactly 512 bytes and the size of data is not always the same. I did not look into the reason why the size of data is not always the same.
Now, I would have to explain a bit on the HTTP process and the writing process. Both process are while loops which made the integration of both process tricky to me. The HTTP process always loops, but particularly the upload process, the HTTP process will fetch a portion of data and write a portion of data until all the data is fetched. The size of data per fetching is, sadly, not exactly 512 bytes. For the writing process, the loop is similar as well, but instead of fetching and writing, the process is writing one block of data, prepare the next sector for writing and then write the other block of data until the end. The desired integrated loop would be that the HTTP fetches the data,check if the block space is enough, writes into part of the block, prepare the next sector block (if necessary), write the remaining data into the next block (if necessary) and repeat. The loop gets more complex when the HTTP would have to first send the multiple block write command before it starts writing and also pad the last block of data with 0x00 until it writes the whole block then only sends stop token.
First, the writing process needs to be break down into three different sections: start, write and end. The function that is being broken down is originally AsyncWriteTask(). By separating the switch cases, calling each cases them independently, it can prevent the looping of the AsyncWriteTask() until it completes the write. The three particular cases that interested are ASYNC_WRITE_QUEUED which starts the writing, ASYNC_WRITE_TRANSMIT_PACKET which writes the data and ASYNC_WRITE_MEDIA_BUSY which detects the state of the SD card and stop the writing process if the process is completed. I try to do this by creating three functions which will call into different cases in the switch structure by modifying from MDD_SDSPI_SectorWrite() function.
Next, these three functions have to be inserted in the correct place in the HTTP process. The particular function that deals with the upload process is the HTTPMPFSUpload() function. Fortunately, the function uses a similar switch structure, thus, I inserted three of the modified functions respectively in cases named HTTP_MPFS_UP which suppose to prepare for the uploading process and HTTP_MPFS_OK which writes the data and if the data processing is complete, it will do the necessary process to stop the transfer.
The end result? The multiple block writing command definitely worked since multiple sectors of the SD is written with different and continuous data with garbage data chunks in between actual data chunks. The writing process is partially working because the some data are written correctly into the SD card but some data which is not meant to written into the SD card was also written into it. These data appears to be some of the HTTP protocol data which shows the content type, the host, the origin of the data and other stuffs. I saw these data before when I was trying to write more EDATA than the actual data, for that time, it is the previous data stored in the EDATA which is not written due to the small 15 bytes file I used to upload. But, it could mean something different now and I have to look into the function I created for writing the EDATA.