You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mynewt.apache.org by will sanfilippo <wi...@runtime.io> on 2016/08/26 00:27:44 UTC

SPI HAL

Hello:

Since we are on the subject of HALs and blocking/non-blocking interfaces…

1) Looking at the SPI HAL for the slave I am thinking that the API is a bit off. Here are the changes I am considering:

a) The per-byte interface is not really practical and can be implemented using the txrx API anyway. I feel that this should be removed. This means removal of hal_spi_start_rx() and removal of the per-value callback (hal_spi_rx_val). There will only be one callback that will be executed when the transfer is done (see more below).

b) A slave may not be able to know how many bytes it will receive from the master for a given transaction. If the master de-asserts the chip select to the slave, the slave should get notified. This would necessitate a change to the callback API to pass the length. Given that there will be only one callback I will change the name as well:
typedef void (*hal_spi_txrx_cb)(void *arg, int len). Just to re-iterate: this will be called when either the number of values in the hal_spi_txrx() call were received or the master de-asserts chip select.

c) The API to set the character to send to the master (hal_spi_tx_val) should not be dual-purposed. The HAL needs to provide a way to set the “default” character that the slave will clock to the master. This could be done in the configuration but I prefer a separate API for two reasons: I think it is cleaner when having a system that is only a master, and it also allows using this API without having to specify the rest of the configuration. This api would be called: hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val);

2) Regarding the blocking master transmit API hal_spi_tx_val. I certainly think there should be a blocking SPI API for the master. Furthermore, and this is sort of a key point, you should not have to “re-initialize” the SPI interface when you want to do blocking transfers and non-blocking transfers; there are times when you might want to send some values and get immediate responses and other times when you just want to hand something to the spi interface and get called back when it is done.

The issue that I am running into which bothers me is having just a “per-value" master blocking API. Given that the SPI interface could be set up for a txrx callback during configuration (for future hal_spi_txrx calls), the API has to disable interrupts or disable the callback feature in some way. This makes the per-value API somewhat ineffecient. Not a huge deal, but things like this bother me. Given that there is no separate SPI API to disable SPI interrupts, I think we should consider the following:

a) Just leave it the way it is and hal_spi_tx_val() will make sure no interrupts occur or the callback is called.
b) Use the API to set the callback to tell the HAL that it is in blocking or non-blocking mode. In other words (and using the new terminology stated above), if the txrx callback is NULL, the device is in blocking mode and thus there is no need to disable interrupts during every call to hal_spi_tx_val. And btw, this does not mean we are replacing disabling interrupts with a check of a function pointer for NULL. The HAL assumes that the user has called hal_spi_set_txrx_cb with NULL as the function pointer or that the SPI was configured without a callback.
c) Add an API to enable/disable HAL SPI interrupts. It would be up to the user to make sure interrupts are disabled prior to calling hal_spi_tx_val().

NOTE: I prefer b) as this would also allow the hal_spi_txrx api to be used in blocking fashion to send an entire buffer.

Thanks everyone! Sorry for the long email...