aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorFabio Utzig <utzig@utzig.org>2016-12-31 21:46:34 +0000
committerFabio Utzig <utzig@utzig.org>2016-12-31 21:46:34 +0000
commit97d615ea05989c3e85d2baf7438b7ede9723dbcd (patch)
treeb7314ebd112c3e9ae4ae27bfcc1bd91d44bb6d99 /os/hal
parent91aed554b8d5c181162472d5faf0c8fa9496c62e (diff)
downloadChibiOS-97d615ea05989c3e85d2baf7438b7ede9723dbcd.tar.gz
ChibiOS-97d615ea05989c3e85d2baf7438b7ede9723dbcd.tar.bz2
ChibiOS-97d615ea05989c3e85d2baf7438b7ede9723dbcd.zip
Fix AVR SPI bugs
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10002 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/ports/AVR/hal_spi_lld.c109
-rw-r--r--os/hal/ports/AVR/hal_spi_lld.h68
2 files changed, 66 insertions, 111 deletions
diff --git a/os/hal/ports/AVR/hal_spi_lld.c b/os/hal/ports/AVR/hal_spi_lld.c
index 638f778b1..d0adcc379 100644
--- a/os/hal/ports/AVR/hal_spi_lld.c
+++ b/os/hal/ports/AVR/hal_spi_lld.c
@@ -30,6 +30,8 @@
/* Driver local definitions. */
/*===========================================================================*/
+#define DUMMY_SPI_SEND_VALUE 0xFF
+
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@@ -64,31 +66,19 @@ OSAL_IRQ_HANDLER(SPI_STC_vect) {
SPIDriver *spip = &SPID1;
- /* spi_lld_exchange or spi_lld_receive */
- if (spip->rxbuf && spip->rxidx < spip->rxbytes) {
- spip->rxbuf[spip->rxidx++] = SPDR; // receive
- }
+ /* a new value has arrived, store it if we are interested in it */
+ if (spip->rxbuf) spip->rxbuf[spip->exidx] = SPDR;
- /* rx done and tx done */
- if (spip->rxidx >= spip->rxbytes && spip->txidx >= spip->txbytes) {
+ /* check if we are done */
+ if (++(spip->exidx) >= spip->exbytes) {
_spi_isr_code(spip);
- }
- else {
- /* spi_lld_exchange, spi_lld_send or spi_lld_ignore */
- if (spip->txidx < spip->txbytes) {
- if (spip->txbuf) {
- SPDR = spip->txbuf[spip->txidx++]; // send
- } else {
- SPDR = 0; spip->txidx++; // dummy send
- }
- }
-
- /* spi_lld_receive */
- else if (spip->rxidx < spip->rxbytes) { /* rx not done */
- SPDR = 0; // dummy send to keep the clock going
+ } else { /* if not done send the next byte */
+ if (spip->txbuf) { /* if there is a buffer with values to be send then use it*/
+ SPDR = spip->txbuf[spip->exidx];
+ } else { /* if there isn't a buffer with values to be send then send a the dummy value*/
+ SPDR = DUMMY_SPI_SEND_VALUE;
}
}
-
OSAL_IRQ_EPILOGUE();
}
#endif /* AVR_SPI_USE_SPI1 */
@@ -265,25 +255,6 @@ void spi_lld_unselect(SPIDriver *spip) {
}
-/**
- * @brief Ignores data on the SPI bus.
- * @details This asynchronous function starts the transmission of a series of
- * idle words on the SPI bus and ignores the received data.
- * @post At the end of the operation the configured callback is invoked.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] n number of words to be ignored
- *
- * @notapi
- */
-void spi_lld_ignore(SPIDriver *spip, size_t n) {
-
- spip->rxbuf = spip->txbuf = NULL;
- spip->txbytes = n;
- spip->txidx = 0;
-
- SPDR = 0;
-}
/**
* @brief Exchanges data on the SPI bus.
@@ -300,64 +271,16 @@ void spi_lld_ignore(SPIDriver *spip, size_t n) {
*
* @notapi
*/
-void spi_lld_exchange(SPIDriver *spip, size_t n,
- const void *txbuf, void *rxbuf) {
+void spi_lld_exchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) {
- spip->rxbuf = rxbuf;
spip->txbuf = txbuf;
- spip->txbytes = spip->rxbytes = n;
- spip->txidx = spip->rxidx = 0;
-
- SPDR = spip->txbuf[spip->txidx++];
-}
-
-/**
- * @brief Sends data over the SPI bus.
- * @details This asynchronous function starts a transmit operation.
- * @post At the end of the operation the configured callback is invoked.
- * @note The buffers are organized as uint8_t arrays for data sizes below or
- * equal to 8 bits else it is organized as uint16_t arrays.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] n number of words to send
- * @param[in] txbuf the pointer to the transmit buffer
- *
- * @notapi
- */
-void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
-
- spip->rxbuf = NULL;
- spip->txbuf = txbuf;
- spip->txbytes = n;
- spip->txidx = 0;
-
- SPDR = spip->txbuf[spip->txidx++];
-}
-
-/**
- * @brief Receives data from the SPI bus.
- * @details This asynchronous function starts a receive operation.
- * @post At the end of the operation the configured callback is invoked.
- * @note The buffers are organized as uint8_t arrays for data sizes below or
- * equal to 8 bits else it is organized as uint16_t arrays.
- *
- * @param[in] spip pointer to the @p SPIDriver object
- * @param[in] n number of words to receive
- * @param[out] rxbuf the pointer to the receive buffer
- *
- * @notapi
- */
-void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
-
- spip->txbuf = NULL;
spip->rxbuf = rxbuf;
- spip->rxbytes = n;
- spip->rxidx = 0;
-
- /* Write dummy byte to start communication */
- SPDR = 0;
+ spip->exidx = 0;
+ spip->exbytes = n;
+ SPDR = (spip->txbuf ? spip->txbuf[0] : DUMMY_SPI_SEND_VALUE);
}
+
/**
* @brief Exchanges one frame using a polled wait.
* @details This synchronous function exchanges one frame using a polled
diff --git a/os/hal/ports/AVR/hal_spi_lld.h b/os/hal/ports/AVR/hal_spi_lld.h
index b685087ee..f7d0ad03e 100644
--- a/os/hal/ports/AVR/hal_spi_lld.h
+++ b/os/hal/ports/AVR/hal_spi_lld.h
@@ -139,7 +139,7 @@ struct SPIDriver {
/**
* @brief Current configuration data.
*/
- SPIConfig *config;
+ const SPIConfig *config;
#if SPI_USE_WAIT || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
@@ -159,33 +159,68 @@ struct SPIDriver {
/**
* @brief Pointer to the buffer with data to send.
*/
- uint8_t *txbuf;
+ const uint8_t *txbuf;
/**
- * @brief Number of bytes of data to send.
- */
- size_t txbytes;
- /**
- * @brief Current index in buffer when sending data.
- */
- size_t txidx;
- /**
- * @brief Pointer to the buffer to put received data.
+ * @brief Pointer to the buffer to store received data.
*/
uint8_t *rxbuf;
/**
- * @brief Number of bytes of data to receive.
+ * @brief Number of bytes of data to exchange.
*/
- size_t rxbytes;
+ size_t exbytes;
/**
- * @brief Current index in buffer when receiving data.
+ * @brief Current index in buffer when exchanging data.
*/
- size_t rxidx;
+ size_t exidx;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This asynchronous function starts the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @notapi
+ */
+#define spi_lld_ignore(spip, n) spi_lld_exchange(spip, n, NULL, NULL)
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+#define spi_lld_send(spip, n, txbuf) spi_lld_exchange(spip, n, txbuf, NULL)
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+#define spi_lld_receive(spip, n, rxbuf) spi_lld_exchange(spip, n, NULL, rxbuf)
+
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@@ -202,11 +237,8 @@ extern "C" {
void spi_lld_stop(SPIDriver *spip);
void spi_lld_select(SPIDriver *spip);
void spi_lld_unselect(SPIDriver *spip);
- void spi_lld_ignore(SPIDriver *spip, size_t n);
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf);
- void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
- void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
#if AVR_SPI_USE_16BIT_POLLED_EXCHANGE
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);