nodesign / weio

weio
http://we-io.net
128 stars 35 forks source link

weioSPI read_block_data error, when block size > 175 #267

Open ementi opened 8 years ago

ementi commented 8 years ago

I am using SPI communication (Port 0) to communicate with a sensor. I am trying to read a block of 1024 bytes with the read_block_data() function. It works perfectly for setting block sizes "SPI_FUNC_READ_BLOCK_DATA" <= 175. But if I want to read more, I get the error: (For example with 176 bytes)

read_value = spi.read_block_data(hex_addr)
File "/weio/weioLib/weioSPI.py", line 144, in read_block_data
return list(unpack(receiveFlags, result))
error: unpack requires a string argument of length 177 

(I changed the function a bit, so if I want to read n Bytes the unpack requires a string argument of length n+1, that's why the error says "177" instead of "176")

Is it possible to increment the maximum size of "SPI_FUNC_READ_BLOCK_DATA" to 1024 bytes?

Best Regards ementi

ks156 commented 8 years ago

Hello @ementi,

This is unfortunately a known bug, difficult to fix. I have spent many hours to understand what was the problem, and I figured out that the problem was located in the LPC firmware side, and is due to a lack of memory. UPER (which is the current firmware we use for the LPC) is divided in two parts : UPER itself, which handle all the peripheral functionalities (GPIO, I2C, SPI, etc), and SFP which handle the data serialization. SFP is an independent library. In addition, this firmware uses dynamic memory allocation, and these allocations are not well handled. This results by some memory problem when a big amount of data must be handled.

To fix this problem, all the firmware must be reviewed. UPER is the first LPC firmware used, and has been developed by 8devices. Even the main developer says that the code is not really nice. (ref)

The LPC firmware suffers of other problems (timings for example), and something must be done. That's why I've started to port the LPC11U34 and the WeIO board to RIOT-OS. I still need to add I2C support, and then try an USB stack (RIOT doesn't have any USB stack yet, but there's some works already done in order to add one (ref). I expect to be able to start soon to write a RIOT application for WeIO. In the same time, we plan to improve IoTPy and SFP.

As you can imagine, all of that represent a lot of work, and will require some time. But this will really improve all the system, and this kind of bug should be fixed by all of that.

As possible workaround, I don't know if it's possible on your application to use smaller blocks ?

ementi commented 8 years ago

I've got the problem, that I need a certain amount of data in a specific time. So we shouldn't lose time within the block read. So the three limiting factors of this task are: The clock speed of the SPI, the number of bytes read, and the time we need to set the chipselect pin to LOW and to HIGH again. I think the most limiting factor after the number of bytes, is the time for the chipselect. So I am using digitalWrite to set the states of the csb pin. I measured the times it takes. For reading 175 Bytes: It takes 20ms from setting the csb pin to LOW, until the block_read starts, after the block read it takes another 15ms to set it back to HIGH. With fewer bytes, it takes less time between the setting LOW and HIGH of the csb pin. For example: reading 1 byte with the read_byte_data function, it takes about 2ms from setting LOW to setting back to HIGH. Is there any way to reduce the time it takes for the read_block_data function?