Fix AVR SPI bugs
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10002 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
91aed554b8
commit
97d615ea05
|
@ -30,6 +30,8 @@
|
||||||
/* Driver local definitions. */
|
/* Driver local definitions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#define DUMMY_SPI_SEND_VALUE 0xFF
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver exported variables. */
|
/* Driver exported variables. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -64,31 +66,19 @@ OSAL_IRQ_HANDLER(SPI_STC_vect) {
|
||||||
|
|
||||||
SPIDriver *spip = &SPID1;
|
SPIDriver *spip = &SPID1;
|
||||||
|
|
||||||
/* spi_lld_exchange or spi_lld_receive */
|
/* a new value has arrived, store it if we are interested in it */
|
||||||
if (spip->rxbuf && spip->rxidx < spip->rxbytes) {
|
if (spip->rxbuf) spip->rxbuf[spip->exidx] = SPDR;
|
||||||
spip->rxbuf[spip->rxidx++] = SPDR; // receive
|
|
||||||
}
|
|
||||||
|
|
||||||
/* rx done and tx done */
|
/* check if we are done */
|
||||||
if (spip->rxidx >= spip->rxbytes && spip->txidx >= spip->txbytes) {
|
if (++(spip->exidx) >= spip->exbytes) {
|
||||||
_spi_isr_code(spip);
|
_spi_isr_code(spip);
|
||||||
}
|
} else { /* if not done send the next byte */
|
||||||
else {
|
if (spip->txbuf) { /* if there is a buffer with values to be send then use it*/
|
||||||
/* spi_lld_exchange, spi_lld_send or spi_lld_ignore */
|
SPDR = spip->txbuf[spip->exidx];
|
||||||
if (spip->txidx < spip->txbytes) {
|
} else { /* if there isn't a buffer with values to be send then send a the dummy value*/
|
||||||
if (spip->txbuf) {
|
SPDR = DUMMY_SPI_SEND_VALUE;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OSAL_IRQ_EPILOGUE();
|
OSAL_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
#endif /* AVR_SPI_USE_SPI1 */
|
#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.
|
* @brief Exchanges data on the SPI bus.
|
||||||
|
@ -300,64 +271,16 @@ void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
void spi_lld_exchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) {
|
||||||
const void *txbuf, void *rxbuf) {
|
|
||||||
|
|
||||||
spip->rxbuf = rxbuf;
|
|
||||||
spip->txbuf = txbuf;
|
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->rxbuf = rxbuf;
|
||||||
spip->rxbytes = n;
|
spip->exidx = 0;
|
||||||
spip->rxidx = 0;
|
spip->exbytes = n;
|
||||||
|
SPDR = (spip->txbuf ? spip->txbuf[0] : DUMMY_SPI_SEND_VALUE);
|
||||||
/* Write dummy byte to start communication */
|
|
||||||
SPDR = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Exchanges one frame using a polled wait.
|
* @brief Exchanges one frame using a polled wait.
|
||||||
* @details This synchronous function exchanges one frame using a polled
|
* @details This synchronous function exchanges one frame using a polled
|
||||||
|
|
|
@ -139,7 +139,7 @@ struct SPIDriver {
|
||||||
/**
|
/**
|
||||||
* @brief Current configuration data.
|
* @brief Current configuration data.
|
||||||
*/
|
*/
|
||||||
SPIConfig *config;
|
const SPIConfig *config;
|
||||||
#if SPI_USE_WAIT || defined(__DOXYGEN__)
|
#if SPI_USE_WAIT || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Waiting thread.
|
* @brief Waiting thread.
|
||||||
|
@ -159,33 +159,68 @@ struct SPIDriver {
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to the buffer with data to send.
|
* @brief Pointer to the buffer with data to send.
|
||||||
*/
|
*/
|
||||||
uint8_t *txbuf;
|
const uint8_t *txbuf;
|
||||||
/**
|
/**
|
||||||
* @brief Number of bytes of data to send.
|
* @brief Pointer to the buffer to store received data.
|
||||||
*/
|
|
||||||
size_t txbytes;
|
|
||||||
/**
|
|
||||||
* @brief Current index in buffer when sending data.
|
|
||||||
*/
|
|
||||||
size_t txidx;
|
|
||||||
/**
|
|
||||||
* @brief Pointer to the buffer to put received data.
|
|
||||||
*/
|
*/
|
||||||
uint8_t *rxbuf;
|
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. */
|
/* 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. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -202,11 +237,8 @@ extern "C" {
|
||||||
void spi_lld_stop(SPIDriver *spip);
|
void spi_lld_stop(SPIDriver *spip);
|
||||||
void spi_lld_select(SPIDriver *spip);
|
void spi_lld_select(SPIDriver *spip);
|
||||||
void spi_lld_unselect(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,
|
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||||
const void *txbuf, void *rxbuf);
|
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
|
#if AVR_SPI_USE_16BIT_POLLED_EXCHANGE
|
||||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
|
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
|
||||||
|
|
Loading…
Reference in New Issue