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. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue