Following the completion of the Ping-Pong Upload mechanism, its time to step forward to system optimization for the PIC firmware. This includes many separate portions looked into during the week to try to enhance the system performance and deliverable. The tasks include: i)optimization of the read/write functions ii) clearing up flash memory for future firmware updates. Apart from that, it was also required to find possible flaws in the current code which may result in the stack to not function properly. Apart from that, the function to read the bitstream from the SD card was also modified to first check and obtain the length of the bitstream so as to acertain how much to exactly read when reading out from the SD card to the UART.
Optimization of the Read Function
The function created to read out of the SD card and write straight to the UART needed to be optimized as the current performance was not satisfactory. Testing the read speeds, it was found that the current algorithm takes about 3.67 seconds in average to read the total length of the bitstream (340kB). This was deemed to be too slow as this was much slower than the reading speeds found my colleague earlier (https://blog.aeste.my/archives/2578). Looking back at the differences in the code, it was found that there is a optimized function for reading data packets from the SD card which greatly speeds up the read speed. But it was tricky to find a way to use this optimized function from Microchip. Utilizing the temporary buffer where the data read from the SD card was stored, the same pointer to that buffer memory on the PIC’s flash was used to point to the data actually being read from the SD card. Correspondingly, using this pointer as the argument for reading out the bytes to the UART, a faster and more optimized method was developed.
After using the optimized function, for a file of size 340kB, the read speed (without transmitted to UART) was found to be around 0.7 seconds which is a great improvement on the previous read speeds. Using the UART however, makes the overall read process much slower and this is down to the baud rate being used. Initially, a baud rate of 9600 bits/s was used in the read function and some simple mathematics can be applied to observe that the expected time to read a file that is approximately 350kB (2800000 bits) would be 291s or about 5 minutes. This does not take into account the start/end bit that the UART send with every byte causing the overall time to be about 20% more, i.e. 350s or 5.83 minutes. And the actual read time of the full sized bitstream through the UART was about 6 minutes (5:48s). Using the highest baud rate available(115200 bits/s) at asynchronous mode, the time taken to read the file fully was about 28 seconds.
Code Cleanup to free up Flash memory space on the PIC
The flash memory available on the PIC is 131064 bytes. It is required for the ability for future firmware updates, that only 64kB be used for the firmware. At the start of the week, this value was found to be 107kB, so a lot of code cleanup was needed to trim the code down to the required 64kB. Following the supervisor’s advice to survey the current firmware and throw away and and all functions not needed for the stack to operate, a few unused scripts were removed. This included, the Pingdemo and SPIEEPROM. It was also found that a few functions in the Helpers functions source code was also not being used and could be removed. However the greatest cleanup was done in the File System (FSIO) source code.
The file system is for use of the SD card to store the data as files. Considering the fact that the bitstream is being stored only into the raw sectors, all the functions using the file system can be considered expendable. This of course excludes the important functions that are being used such as the FSInit, which initializes the SD card; FSFormat, which formats the SD card to the current usable format; LoadMBR and LoadBootSector functions that are subsidarily being used in the functions mentioned. There were also a few new functions created that were kept (such as the AesteEditMBR, MBRCheck etc). After removing all the other file system related functions, it was found that the flash memory was free up by 25%. Following a few more careful removal of unnecessary functions, by the end of the week, the current flash memory in use is about 72kB which is an improvement of 27% from the beginning of the week. Further space can be freed up by simplifying some of the custom functions written for the SD card raw read/write operations and will be executed in the coming weeks.
Obtaining the Bitstream length
The bitstream length is stored in the bitstream header file (https://blog.aeste.my/archives/2892). This information can be used to great advantage as it can help notify the PIC of exactly how much to read from the SD card when programming the FPGA. From the work done by my colleague, as the bitstream comes into the SD card, the first 4 bytes are to represent the 32-bit long value of the bitstream length. So a function was developed to pick out these values and use them to read out that amount of bytes from the raw sectors of the SD card. The function created was called FileSizeCheck and it takes in the SectorAddress of the starting sector where the bitstream is stored on the SD card. This information is obtained after the MBRCheck is done to find the location of the current version of the bitstream. After extracting the data, the FileSize is fed into the AesteSectorRead function as an argument. A couple of logic problems with this approach were observed.
The first was the fact that the bistream length would not be an exact multiple of 512 bytes. But the read function decrements the number of bytes to read by 512 bytes as each block is being read, causing the function to loop infinitely. This was rectified by subtracting the number of bytes to read counter by 1 byte every time a byte of data is read. This solved the problem of the infinite read loop. But the Multi-Block Read operation cannot terminate while still in the middle of a block, i.e. even is a Stop Transmission token is sent before the block is completely read, the block in read progress will be ignored and only the block before will be read. So a new method was devised to allow the SD card to read the final block, by first setting a Sector Count of the number of sectors to be read using the File Size. This solved the problem and the whole bitstream was able to be read.
A few good steps were taken during the week but it felt like the progress was slow compared to previous weeks. It is hoped that the optimization can be sped up in the coming week and further advancements towards the completion of the project can be made smoothly. The next daunting task is to try and optimize the write operations further to speed up the writing speed for the SD card.