/*********************************************************************//** * @brief SSP Read write data function * @param[in] SSPx Pointer to SSP peripheral, should be * - LPC_SSP0: SSP0 peripheral * - LPC_SSP1: SSP1 peripheral * @param[in] dataCfg Pointer to a SSP_DATA_SETUP_Type structure that * contains specified information about transmit * data configuration. * @param[in] xfType Transfer type, should be: * - SSP_TRANSFER_POLLING: Polling mode * - SSP_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 SSP_ReadWrite (LPC_SSP_TypeDef *SSPx, SSP_DATA_SETUP_Type *dataCfg, \ SSP_TRANSFER_Type xfType) { uint8_t *rdata8 = 0; uint8_t *wdata8 = 0; uint16_t *rdata16 = 0; uint16_t *wdata16 = 0; uint32_t stat; uint32_t tmp; int32_t dataword; dataCfg->rx_cnt = 0; dataCfg->tx_cnt = 0; dataCfg->status = 0; /* Clear all remaining data in RX FIFO */ while (SSPx->SR & SSP_SR_RNE){ tmp = (uint32_t) SSP_ReceiveData(SSPx); } // Clear status SSPx->ICR = SSP_ICR_BITMASK; if(SSP_GetDataSize(SSPx)>8) dataword = 1; else dataword = 0; // Polling mode ---------------------------------------------------------------------- if (xfType == SSP_TRANSFER_POLLING){ if (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->tx_cnt != dataCfg->length) || (dataCfg->rx_cnt != dataCfg->length)){ if ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){ // Write data to buffer if(dataCfg->tx_data == NULL){ if (dataword == 0){ SSP_SendData(SSPx, 0xFF); dataCfg->tx_cnt++; } else { SSP_SendData(SSPx, 0xFFFF); dataCfg->tx_cnt += 2; } } else { if (dataword == 0){ SSP_SendData(SSPx, *wdata8); wdata8++; dataCfg->tx_cnt++; } else { SSP_SendData(SSPx, *wdata16); wdata16++; dataCfg->tx_cnt += 2; } } } // Check overrun error if ((stat = SSPx->RIS) & SSP_RIS_ROR){ // save status and return dataCfg->status = stat | SSP_STAT_ERROR; return (-1); } // Check for any data available in RX FIFO while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){ // Read data from SSP data tmp = SSP_ReceiveData(SSPx); // Store data to destination if (dataCfg->rx_data != NULL) { if (dataword == 0){ *(rdata8) = (uint8_t) tmp; rdata8++; } else { *(rdata16) = (uint16_t) tmp; rdata16++; } } // Increase counter if (dataword == 0){ dataCfg->rx_cnt++; } else { dataCfg->rx_cnt += 2; } } } // save status dataCfg->status = SSP_STAT_DONE; if (dataCfg->tx_data != NULL){ return dataCfg->tx_cnt; } else if (dataCfg->rx_data != NULL){ return dataCfg->rx_cnt; } else { return (0); } } // Interrupt mode ---------------------------------------------------------------------- else if (xfType == SSP_TRANSFER_INTERRUPT){ while ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){ // Write data to buffer if(dataCfg->tx_data == NULL){ if (dataword == 0){ SSP_SendData(SSPx, 0xFF); dataCfg->tx_cnt++; } else { SSP_SendData(SSPx, 0xFFFF); dataCfg->tx_cnt += 2; } } else { if (dataword == 0){ SSP_SendData(SSPx, (*(uint8_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt))); dataCfg->tx_cnt++; } else { SSP_SendData(SSPx, (*(uint16_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt))); dataCfg->tx_cnt += 2; } } // Check error if ((stat = SSPx->RIS) & SSP_RIS_ROR){ // save status and return dataCfg->status = stat | SSP_STAT_ERROR; return (-1); } // Check for any data available in RX FIFO while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){ // Read data from SSP data tmp = SSP_ReceiveData(SSPx); // Store data to destination if (dataCfg->rx_data != NULL) { if (dataword == 0){ *(uint8_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint8_t) tmp; } else { *(uint16_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint16_t) tmp; } } // Increase counter if (dataword == 0){ dataCfg->rx_cnt++; } else { dataCfg->rx_cnt += 2; } } } // If there more data to sent or receive if ((dataCfg->rx_cnt != dataCfg->length) || (dataCfg->tx_cnt != dataCfg->length)){ // Enable all interrupt SSPx->IMSC = SSP_IMSC_BITMASK; } else { // Save status dataCfg->status = SSP_STAT_DONE; } return (0); } return (-1); }
/*********************************************************************//** * @brief SSP0 Interrupt used for reading and writing handler * @param None * @return None ***********************************************************************/ void SSP0_IRQHandler(void) { SSP_DATA_SETUP_Type *xf_setup; uint16_t tmp; uint8_t dataword; // Disable all SSP interrupts SSP_IntConfig(LPC_SSP0, SSP_INTCFG_ROR|SSP_INTCFG_RT|SSP_INTCFG_RX|SSP_INTCFG_TX, DISABLE); if(SSP_GetDataSize(LPC_SSP0)>8) dataword = 1; else dataword = 0; xf_setup = &xferConfig; // save status tmp = SSP_GetRawIntStatusReg(LPC_SSP0); xf_setup->status = tmp; // Check overrun error if (tmp & SSP_RIS_ROR){ // Clear interrupt SSP_ClearIntPending(LPC_SSP0, SSP_INTCLR_ROR); // update status xf_setup->status |= SSP_STAT_ERROR; // Set Complete Flag complete = SET; return; } if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)){ /* check if RX FIFO contains data */ while ((SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY)) && (xf_setup->rx_cnt != xf_setup->length)){ // Read data from SSP data tmp = SSP_ReceiveData(LPC_SSP0); // Store data to destination if (xf_setup->rx_data != NULL) { if (dataword == 0){ *(uint8_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint8_t) tmp; } else { *(uint16_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint16_t) tmp; } } // Increase counter if (dataword == 0){ xf_setup->rx_cnt++; } else { xf_setup->rx_cnt += 2; } } while ((SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL)) && (xf_setup->tx_cnt != xf_setup->length)){ // Write data to buffer if(xf_setup->tx_data == NULL){ if (dataword == 0){ SSP_SendData(LPC_SSP0, 0xFF); xf_setup->tx_cnt++; } else { SSP_SendData(LPC_SSP0, 0xFFFF); xf_setup->tx_cnt += 2; } } else { if (dataword == 0){ SSP_SendData(LPC_SSP0, (*(uint8_t *)((uint32_t)xf_setup->tx_data + xf_setup->tx_cnt))); xf_setup->tx_cnt++; } else { SSP_SendData(LPC_SSP0, (*(uint16_t *)((uint32_t)xf_setup->tx_data + xf_setup->tx_cnt))); xf_setup->tx_cnt += 2; } } // Check overrun error if (SSP_GetRawIntStatus(LPC_SSP0, SSP_INTSTAT_RAW_ROR)){ // update status xf_setup->status |= SSP_STAT_ERROR; // Set Complete Flag complete = SET; return; } // Check for any data available in RX FIFO while ((SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY)) && (xf_setup->rx_cnt != xf_setup->length)){ // Read data from SSP data tmp = SSP_ReceiveData(LPC_SSP0); // Store data to destination if (xf_setup->rx_data != NULL) { if (dataword == 0){ *(uint8_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint8_t) tmp; } else { *(uint16_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint16_t) tmp; } } // Increase counter if (dataword == 0){ xf_setup->rx_cnt++; } else { xf_setup->rx_cnt += 2; } } } } // If there more data to sent or receive if ((xf_setup->rx_cnt != xf_setup->length) || (xf_setup->tx_cnt != xf_setup->length)){ // Enable all interrupt SSP_IntConfig(LPC_SSP0, SSP_INTCFG_ROR|SSP_INTCFG_RT|SSP_INTCFG_RX|SSP_INTCFG_TX, ENABLE); } else { // Save status xf_setup->status = SSP_STAT_DONE; // Set Complete Flag complete = SET; } }