/** * @brief Common IRQ handler. * * @param[in] spip pointer to the @p SPIDriver object */ static void serve_interrupt(SPIDriver *spip) { SSP *ssp = spip->spd_ssp; if ((ssp->SSP_MIS & MIS_ROR) != 0) { /* The overflow condition should never happen because priority is given to receive but a hook macro is provided anyway...*/ LPC214x_SPI_SSP_ERROR_HOOK(); } ssp->SSP_ICR = ICR_RT | ICR_ROR; while ((ssp->SSP_SR & SR_RNE) != 0) { if (spip->spd_rxptr != NULL) { if ((ssp->SSP_CR0 & CR0_DSSMASK) > CR0_DSS8BIT) *(uint16_t *)spip->spd_rxptr++ = ssp->SSP_DR; else *(uint8_t *)spip->spd_rxptr++ = ssp->SSP_DR; } else (void)ssp->SSP_DR; if (--spip->spd_rxcnt == 0) { chDbgAssert(spip->spd_txcnt == 0, "spi_serve_interrupt(), #1", "counter out of synch"); /* Stops the IRQ sources.*/ ssp->SSP_IMSC = 0; /* Portable SPI ISR code defined in the high level driver, note, it is a macro.*/ _spi_isr_code(spip); return; } } ssp_fifo_preload(spip); if (spip->spd_txcnt == 0) ssp->SSP_IMSC = IMSC_ROR | IMSC_RT | IMSC_RX; }
/** * @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->rxptr = rxbuf; spip->txptr = NULL; spip->rxcnt = spip->txcnt = n; ssp_fifo_preload(spip); spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX; }
/** * @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->rxptr = NULL; spip->txptr = txbuf; spip->rxcnt = spip->txcnt = n; ssp_fifo_preload(spip); spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX; }
/** * @brief Ignores data on the SPI bus. * @details This function transmits a series of idle words on the SPI bus and * ignores the received data. This function can be invoked even * when a slave select signal has not been yet asserted. * * @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->rxptr = NULL; spip->txptr = NULL; spip->rxcnt = spip->txcnt = n; ssp_fifo_preload(spip); spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX; }
/** * @brief Exchanges data on the SPI bus. * @details This asynchronous function starts a simultaneous transmit/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 be exchanged * @param[in] txbuf the pointer to the transmit buffer * @param[out] rxbuf the pointer to the receive buffer * * @notapi */ void spi_lld_exchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { spip->spd_rxptr = rxbuf; spip->spd_txptr = txbuf; spip->spd_rxcnt = spip->spd_txcnt = n; ssp_fifo_preload(spip); spip->spd_ssp->SSP_IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX; }