Spi::Spi(SerialCallback callback) : m_rq(SPI_RECEIVEBUF_SIZE), m_tq(SPI_TRANSMITBUF_SIZE, callback) { uint32_t i; volatile uint32_t d; SSP_CFG_Type configStruct; configStruct.CPHA = SSP_CPHA_FIRST; configStruct.CPOL = SSP_CPOL_HI; configStruct.ClockRate = 204000000; configStruct.Databit = SSP_DATABIT_16; configStruct.Mode = SSP_SLAVE_MODE; configStruct.FrameFormat = SSP_FRAME_SPI; // Initialize SSP peripheral with parameter given in structure above SSP_Init(LPC_SSP1, &configStruct); // clear receive fifo for (i=0; i<8; i++) d = LPC_SSP1->DR; // Enable SSP peripheral SSP_Cmd(LPC_SSP1, ENABLE); SSP_ClearIntPending(LPC_SSP1, SSP_INTCFG_RX); SSP_IntConfig(LPC_SSP1, SSP_INTCFG_RX, ENABLE); NVIC_SetPriority(SSP1_IRQn, 0); // high priority interrupt m_sync = false; m_recvCounter = 0; m_lastRecvCounter = 0; m_syncCounter = 0; setAutoSlaveSelect(false); }
void spi_init() { uint32_t i; volatile uint32_t d; SSP_CFG_Type configStruct; g_receive.m_buf = new uint16_t[SPI_RECEIVEBUF_SIZE]; g_receive.m_read = 0; g_receive.m_write = 0; g_receive.m_produced = 0; g_receive.m_consumed = 0; g_transmit.m_buf = new uint16_t[SPI_TRANSMITBUF_SIZE]; g_transmit.m_read = 0; g_transmit.m_len = 0; g_transmit.m_callback = (TransmitCallback)NULL; configStruct.CPHA = SSP_CPHA_FIRST; configStruct.CPOL = SSP_CPOL_HI; configStruct.ClockRate = 204000000; configStruct.Databit = SSP_DATABIT_16; configStruct.Mode = SSP_SLAVE_MODE; configStruct.FrameFormat = SSP_FRAME_SPI; // Initialize SSP peripheral with parameter given in structure above SSP_Init(LPC_SSP1, &configStruct); // clear receive fifo for (i=0; i<8; i++) d = LPC_SSP1->DR; // Enable SSP peripheral SSP_Cmd(LPC_SSP1, ENABLE); SSP_ClearIntPending(LPC_SSP1, SSP_INTCFG_RT); SSP_IntConfig(LPC_SSP1, SSP_INTCFG_RT, ENABLE); // sync spi_sync(); // enable interrupt NVIC_SetPriority(SSP1_IRQn, 0); // high priority interrupt NVIC_EnableIRQ(SSP1_IRQn); }
/*********************************************************************//** * @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; } }
/*********************************************************************//** * @brief SSP Slave Interrupt sub-routine used for reading * and writing handler * @param None * @return None ***********************************************************************/ void ssp_Slave_IntHandler(void) { uint16_t tmp; /* Clear all interrupt */ SSP_ClearIntPending(SSPDEV_S, SSP_INTCLR_ROR); SSP_ClearIntPending(SSPDEV_S, SSP_INTCLR_RT); /* check if RX FIFO contains data */ while (SSP_GetStatus(SSPDEV_S, SSP_STAT_RXFIFO_NOTEMPTY) == SET) { tmp = SSP_ReceiveData(SSPDEV_S); if ((pRdBuf_S!= NULL) && (RdIdx_S < DatLen_S)) { *(pRdBuf_S + RdIdx_S) = (uint8_t) tmp; } RdIdx_S++; } /* Check if TX FIFO is not full */ while ((SSP_GetStatus(SSPDEV_S, SSP_STAT_TXFIFO_NOTFULL) == SET) && (WrIdx_S < DatLen_S)) { /* check if RX FIFO contains data */ while (SSP_GetStatus(SSPDEV_S, SSP_STAT_RXFIFO_NOTEMPTY) == SET) { tmp = SSP_ReceiveData(SSPDEV_S); if ((pRdBuf_S!= NULL) && (RdIdx_S < DatLen_S)) { *(pRdBuf_S + RdIdx_S) = (uint8_t) tmp; } RdIdx_S++; } if (pWrBuf_S != NULL) { SSP_SendData(SSPDEV_S, (uint16_t)(*(pWrBuf_S + WrIdx_S))); } else { SSP_SendData(SSPDEV_S, IDLE_CHAR); } WrIdx_S++; } /* There're more data to send */ if (WrIdx_S < DatLen_S) { SSP_IntConfig(SSPDEV_S, SSP_INTCFG_TX, ENABLE); } /* Otherwise */ else { SSP_IntConfig(SSPDEV_S, SSP_INTCFG_TX, DISABLE); } /* There're more data to receive */ if (RdIdx_S < DatLen_S) { SSP_IntConfig(SSPDEV_S, SSP_INTCFG_ROR, ENABLE); SSP_IntConfig(SSPDEV_S, SSP_INTCFG_RT, ENABLE); SSP_IntConfig(SSPDEV_S, SSP_INTCFG_RX, ENABLE); } /* Otherwise */ else { SSP_IntConfig(SSPDEV_S, SSP_INTCFG_ROR, DISABLE); SSP_IntConfig(SSPDEV_S, SSP_INTCFG_RT, DISABLE); SSP_IntConfig(SSPDEV_S, SSP_INTCFG_RX, DISABLE); } /* Set Flag if both Read and Write completed */ if ((WrIdx_S == DatLen_S) && (RdIdx_S == DatLen_S)) { complete_S = TRUE; } }