/*********************************************************************//** * @brief SPI Read write data function * @param[in] SPIx Pointer to SPI peripheral, should be SPI * @param[in] dataCfg Pointer to a SPI_DATA_SETUP_Type structure that * contains specified information about transmit * data configuration. * @param[in] xfType Transfer type, should be: * - SPI_TRANSFER_POLLING: Polling mode * - SPI_TRANSFER_INTERRUPT: Interrupt mode * @return Actual Data length has been transferred in polling mode. * In interrupt mode, always return (0) * Return (-1) if error. * Note: This function can be used in both master and slave mode. ***********************************************************************/ int32_t SPI_ReadWrite (LPC_SPI_TypeDef *SPIx, SPI_DATA_SETUP_Type *dataCfg, \ SPI_TRANSFER_Type xfType) { uint8_t *rdata8; uint8_t *wdata8; uint16_t *rdata16; uint16_t *wdata16; uint32_t stat; uint32_t temp; //read for empty buffer temp = SPIx->SPDR; //dummy to clear status temp = SPIx->SPSR; dataCfg->counter = 0; dataCfg->status = 0; if (xfType == SPI_TRANSFER_POLLING){ if (spidat.dataword == 0){ rdata8 = (uint8_t *)dataCfg->rx_data; wdata8 = (uint8_t *)dataCfg->tx_data; } else { rdata16 = (uint16_t *)dataCfg->rx_data; wdata16 = (uint16_t *)dataCfg->tx_data; } while(dataCfg->counter < dataCfg->length) { // Write data to buffer if(dataCfg->tx_data == NULL){ if (spidat.dataword == 0){ SPI_SendData(SPIx, 0xFF); } else { SPI_SendData(SPIx, 0xFFFF); } } else { if (spidat.dataword == 0){ SPI_SendData(SPIx, *wdata8); wdata8++; } else { SPI_SendData(SPIx, *wdata16); wdata16++; } } // Wait for transfer complete while (!((stat = SPIx->SPSR) & SPI_SPSR_SPIF)); // Check for error if (stat & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){ // save status dataCfg->status = stat | SPI_STAT_ERROR; return (dataCfg->counter); } // Read data from SPI dat temp = (uint32_t) SPI_ReceiveData(SPIx); // Store data to destination if (dataCfg->rx_data != NULL) { if (spidat.dataword == 0){ *(rdata8) = (uint8_t) temp; rdata8++; } else { *(rdata16) = (uint16_t) temp; rdata16++; } } // Increase counter if (spidat.dataword == 0){ dataCfg->counter++; } else { dataCfg->counter += 2; } } // Return length of actual data transferred // save status dataCfg->status = stat | SPI_STAT_DONE; return (dataCfg->counter); } // Interrupt mode else { spidat.txrx_setup = (uint32_t)dataCfg; spidat.inthandler = SPI_IntHandler; // Check if interrupt flag is already set if(SPIx->SPINT & SPI_SPINT_INTFLAG){ SPIx->SPINT = SPI_SPINT_INTFLAG; } if (dataCfg->counter < dataCfg->length){ // Write data to buffer if(dataCfg->tx_data == NULL){ if (spidat.dataword == 0){ SPI_SendData(SPIx, 0xFF); } else { SPI_SendData(SPIx, 0xFFFF); } } else { if (spidat.dataword == 0){ SPI_SendData(SPIx, (*(uint8_t *)dataCfg->tx_data)); } else { SPI_SendData(SPIx, (*(uint16_t *)dataCfg->tx_data)); } } SPI_IntCmd(SPIx, ENABLE); } else { // Save status dataCfg->status = SPI_STAT_DONE; } return (0); } }
/*********************************************************************//** * @brief Standard Private SPI Interrupt handler * @param[in] None * @return None ***********************************************************************/ void SPI_IntHandler(void) { SPI_DATA_SETUP_Type *xf_setup; uint16_t tmp; xf_setup = (SPI_DATA_SETUP_Type *)spidat.txrx_setup; CS_Force(1); /* Dummy read to clear SPI interrupt flag */ if (LPC_SPI->SPINT & SPI_SPINT_INTFLAG){ LPC_SPI->SPINT = SPI_SPINT_INTFLAG; } // save status tmp = LPC_SPI->SPSR; xf_setup->status = tmp; // Check for error if (tmp & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){ xf_setup->status |= SPI_STAT_ERROR; // Disable Interrupt and call call-back SPI_IntCmd(LPC_SPI, DISABLE); if (xf_setup->callback != NULL){ xf_setup->callback(); } return; } /* Check SPI complete flag */ if (tmp & SPI_SPSR_SPIF){ // Read data from SPI data tmp = SPI_ReceiveData(LPC_SPI); if (xf_setup->rx_data != NULL) { // if (spidat.dataword == 0){ // *(uint8_t *)(xf_setup->rx_data + xf_setup->counter) = (uint8_t) tmp; // } else { // *(uint16_t *)(xf_setup->rx_data + xf_setup->counter) = (uint8_t) tmp; // } if (spidat.dataword == 0){ *(uint8_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp; } else { *(uint16_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp; } } if (xf_setup->rd_length) { xf_setup->rd_length--; } if(xf_setup->rd_length==0) { xf_setup->rx_data = NULL; } /* if (!(GPIO_ReadValue(0) & (1<<3))||(xf_setup->tx_data != NULL)) { if (spidat.dataword == 0){ xf_setup->counter++; } else { xf_setup->counter += 2; } }*/ if ((xf_setup->rd_length == 0) && (xf_setup->wr_length == 0)) { xf_setup->counter = xf_setup->length; } else { // Increase counter if (spidat.dataword == 0){ xf_setup->counter++; } else { xf_setup->counter += 2; } } } if (xf_setup->counter < xf_setup->length) { if (xf_setup->wr_length) { xf_setup->wr_length--; } if(xf_setup->wr_length==0) { xf_setup->tx_data = NULL; } // Write data to buffer if(xf_setup->tx_data == NULL){ if (spidat.dataword == 0){ SPI_SendData(LPC_SPI, 0xFF); } else { SPI_SendData(LPC_SPI, 0xFFFF); } } else { // if (spidat.dataword == 0){ // SPI_SendData(SPI, (*(uint8_t *)(xf_setup->tx_data + xf_setup->counter))); // } else { // SPI_SendData(SPI, (*(uint16_t *)(xf_setup->tx_data + xf_setup->counter))); // } if (spidat.dataword == 0){ SPI_SendData(LPC_SPI, (*(uint8_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter))); } else { SPI_SendData(LPC_SPI, (*(uint16_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter))); } } } // No more data to send else { xf_setup->status |= SPI_STAT_DONE; // Disable Interrupt and call call-back SPI_IntCmd(LPC_SPI, DISABLE); if (xf_setup->callback != NULL){ xf_setup->callback(); } } }
/*********************************************************************//** * @brief SPI Interrupt used for reading and writing handler * @param None * @return None ***********************************************************************/ void SPI_IRQHandler(void) { SPI_DATA_SETUP_Type *xf_setup; uint16_t tmp; uint8_t dataword; xf_setup = &xferConfig; if(SPI_GetDataSize(LPC_SPI) == 8) dataword = 0; else dataword = 1; /* Dummy read to clear SPI interrupt flag */ SPI_ClearIntPending(LPC_SPI); // save status tmp = SPI_GetStatus(LPC_SPI); xf_setup->status = tmp; // Check for error if (tmp & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){ xf_setup->status |= SPI_STAT_ERROR; // Disable Interrupt and call call-back SPI_IntCmd(LPC_SPI, DISABLE); // Set Complete Flag complete = SET; return; } /* Check SPI complete flag */ if (tmp & SPI_SPSR_SPIF){ // Read data from SPI data tmp = SPI_ReceiveData(LPC_SPI); if (xf_setup->rx_data != NULL) { if (dataword == 0){ *(uint8_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp; } else { *(uint16_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp; } } // Increase counter if (dataword == 0){ xf_setup->counter++; } else { xf_setup->counter += 2; } } if (xf_setup->counter < xf_setup->length){ // Write data to buffer if(xf_setup->tx_data == NULL){ if (dataword == 0){ SPI_SendData(LPC_SPI, 0xFF); } else { SPI_SendData(LPC_SPI, 0xFFFF); } } else { if (dataword == 0){ SPI_SendData(LPC_SPI, (*(uint8_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter))); } else { SPI_SendData(LPC_SPI, (*(uint16_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter))); } } } // No more data to send else { xf_setup->status |= SPI_STAT_DONE; // Disable Interrupt and call call-back SPI_IntCmd(LPC_SPI, DISABLE); // Set Complete Flag complete = SET; } }