/** @ingroup spi_function @brief Send an array of bytes to to the SPI bus. @note Can only be used if SPI_USE_BUFFER are enabled in spi_iha_defs.h @see spi_iha_defs.h for SPI_USE_BUFFER setup. @return SPI_OK: OK byte send to SPI bus or put in tx_buffer.\n SPI_NO_ROOM_IN_TX_BUFFER: Buffer full no data send\n SPI_ILLEGAL_INSTANCE: instance is null. @param spi to send to. @param *buf pointer to buffer to be send. @param len no of bytes to send. */ uint8_t spi_send_bytes(spi_p spi, uint8_t buf[], uint8_t len) { uint8_t result = SPI_OK; uint32_t value; uint8_t tmp = 0; if (spi == NULL) { return SPI_ILLEGAL_INSTANCE; } // Select correct instance if (_this != spi ) { _select_instance(spi); } // Critical section { // disable interrupt spi_disable_interrupt(_spi_base, SPI_IDR_TDRE | SPI_IDR_RDRF); // Check if buffer is free if (len > fifo_get_free_size(spi->_spi_tx_fifo_desc)) { result = SPI_NO_ROOM_IN_TX_BUFFER; } else { // If SPI in idle send the first byte if (!_spi_active) { _spi_active = 1; // Send first byte value = SPI_TDR_TD(buf[0]) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin)); if (len == 1) { // It was last byte value |= SPI_TDR_LASTXFER; } // Send byte _spi_base->SPI_TDR = value; //spi_enable_interrupt(_spi_base, SPI_IER_TDRE); tmp = 1; } // Put in the tx buffer for (uint8_t i = tmp; i < len; i++) { value = SPI_TDR_TD(buf[i]) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin)); if (i == len-1) { // It was last byte value |= SPI_TDR_LASTXFER; } if ( fifo_push_uint32(spi->_spi_tx_fifo_desc, value) == FIFO_ERROR_OVERFLOW ) { result = SPI_NO_ROOM_IN_TX_BUFFER; } } } // restore interrupt state spi_enable_interrupt(_spi_base, SPI_IER_TDRE | SPI_IER_RDRF); } return result; }
void spi_transmission_begin(spi_t dev, char reset_val) { switch (dev) { #if SPI_0_EN case SPI_0: SPI_0_DEV->SPI_TDR = SPI_TDR_TD(reset_val); break; #endif /* SPI_0_EN */ } }
static inline void irq_handler_transfer(Spi *spi, spi_t dev) { if (spi->SPI_SR & SPI_SR_RDRF) { char data; data = spi->SPI_RDR & SPI_RDR_RD_Msk; data = spi_config[dev].cb(data); spi->SPI_TDR = SPI_TDR_TD(data); } /* See if a thread with higher priority wants to run now */ if (sched_context_switch_request) { thread_yield(); } }
uint8_t spi_send_byte(spi_p spi, uint8_t byte, uint8_t last_byte) { uint8_t result = SPI_OK; uint32_t value; if (spi == NULL) { return SPI_ILLEGAL_INSTANCE; } // Select correct instance if (_this != spi ) { _select_instance(spi); } // Critical section { // disable interrupt spi_disable_interrupt(_spi_base, SPI_IDR_TDRE | SPI_IDR_RDRF); value = SPI_TDR_TD(byte) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin)); if (last_byte) { value |= SPI_TDR_LASTXFER; } // If SPI in idle send the byte if (!_spi_active) { _spi_active = 1; // Send byte _spi_base->SPI_TDR = value; } else { // Put in the TX buffer if ( fifo_push_uint32(spi->_spi_tx_fifo_desc, value) == FIFO_ERROR_UNDERFLOW ) result = SPI_NO_ROOM_IN_TX_BUFFER; } // Enable interrupt spi_enable_interrupt(_spi_base, SPI_IER_TDRE | SPI_IER_RDRF); } return result; }
int spi_transfer_byte(spi_t dev, char out, char *in) { Spi *spi_port; switch (dev) { #if SPI_0_EN case SPI_0: spi_port = SPI_0_DEV; break; #endif /* SPI_0_EN */ default: return -1; } while (!(spi_port->SPI_SR & SPI_SR_TDRE)); spi_port->SPI_TDR = SPI_TDR_TD(out); while (!(spi_port->SPI_SR & SPI_SR_RDRF)); *in = spi_port->SPI_RDR & SPI_RDR_RD_Msk; return 1; }