// ----------------------------------------------------------------------------- //! \brief This callback is invoked on Write completion //! //! \param[in] handle - handle to the UART port //! \param[in] ptr - pointer to data to be transmitted //! \param[in] size - size of the data //! //! \return void // ----------------------------------------------------------------------------- static void NPITLUART_writeCallBack(UART_Handle handle, void *ptr, size_t size) { ICall_CSState key; key = ICall_enterCriticalSection(); #ifdef POWER_SAVING if ( !RxActive ) { UART_readCancel(uartHandle); if ( npiTransmitCB ) { npiTransmitCB(TransportRxLen,TransportTxLen); } } TxActive = FALSE; #else if ( npiTransmitCB ) { npiTransmitCB(0,TransportTxLen); } #endif //POWER_SAVING ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine writes copies buffer addr to the transport layer. //! //! \param[in] len - Number of bytes to write. //! //! \return uint8 - number of bytes written to transport // ----------------------------------------------------------------------------- uint16 NPITLUART_writeTransport(uint16 len) { ICall_CSState key; key = ICall_enterCriticalSection(); TransportTxLen = len; #ifdef POWER_SAVING TxActive = TRUE; // Start reading prior to impending write transaction // We can only call UART_write() once MRDY has been signaled from Master // device NPITLUART_readTransport(); #else // Check to see if transport is successful. If not, reset TxLen to allow // another write to be processed if(UART_write(uartHandle, TransportTxBuf, TransportTxLen) == UART_ERROR ) { TransportTxLen = 0; } #endif //POWER_SAVING ICall_leaveCriticalSection(key); return TransportTxLen; }
// ----------------------------------------------------------------------------- //! \brief This callback is invoked on Write completion //! //! \param[in] handle - handle to the UART port //! \param[in] ptr - pointer to data to be transmitted //! \param[in] size - size of the data //! //! \return void // ----------------------------------------------------------------------------- static void SDITLUART_writeCallBack(UART_Handle handle, void *ptr, size_t size) { ICall_CSState key; key = ICall_enterCriticalSection(); uint8 errStatus = 0; if (errStatus = ((UARTCC26XX_Handle)handle->object)->status) { //report UART error status to application if(incomingRXErrorStatusAppCBFunc != NULL) incomingRXErrorStatusAppCBFunc(UART_ERROR_EVT, &errStatus, sizeof(errStatus)); } #ifdef POWER_SAVING if ( !RxActive ) { UART_readCancel(uartHandle); if ( sdiTransmitCB ) { sdiTransmitCB(TransportRxLen,TransportTxLen); } } TxActive = FALSE; #else if ( sdiTransmitCB ) { sdiTransmitCB(0,TransportTxLen); } #endif //POWER_SAVING ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine initializes the transport layer and opens the port //! of the device. Note that based on project defines, either the //! UART, or SPI driver can be used. //! //! \param[in] npiCBTx - Call back function for TX complete event //! \param[in] npiCBRx - Call back function for RX event //! \param[in] npiCBMrdy - Call back function for MRDY event //! //! \return void // ----------------------------------------------------------------------------- void NPITL_initTL(npiRtosCB_t npiCBTx, npiRtosCB_t npiCBRx, npiRtosCB_t npiCBMrdy) { ICall_CSState key; key = ICall_enterCriticalSection(); taskTxCB = npiCBTx; taskRxCB = npiCBRx; #if (NPI_FLOW_CTRL == 1) taskMrdyCB = npiCBMrdy; #endif // NPI_FLOW_CTRL = 1 transportInit(npiRxBuf,npiTxBuf, NPITL_transmissionCallBack); #if (NPI_FLOW_CTRL == 1) SRDY_DISABLE(); // Initialize SRDY/MRDY. Enable int after callback registered hNpiHandshakePins = PIN_open(&npiHandshakePins, npiHandshakePinsCfg); PIN_registerIntCb(hNpiHandshakePins, NPITL_MRDYPinHwiFxn); PIN_setConfig(hNpiHandshakePins, PIN_BM_IRQ, MRDY_PIN | PIN_IRQ_BOTHEDGES); // Enable wakeup PIN_setConfig(hNpiHandshakePins, PINCC26XX_BM_WAKEUP, MRDY_PIN | PINCC26XX_WAKEUP_NEGEDGE); mrdy_state = PIN_getInputValue(MRDY_PIN); #endif // NPI_FLOW_CTRL = 1 ICall_leaveCriticalSection(key); return; }
uint8 SDITLUART_configureUARTParams(UART_Params *initParams) { uint8 status = SUCCESS; ICall_CSState key; SDITLUART_closeUART(); key = ICall_enterCriticalSection(); // Open / power on the UART. uartHandle = UART_open(Board_UART, ¶msUART); if(uartHandle != NULL) { //DEBUG("UART_open successful"); }else{ //DEBUG("ERROR in UART_open"); status = FAILURE; } //Enable Partial Reads on all subsequent UART_read() status = UART_control(uartHandle, UARTCC26XX_RETURN_PARTIAL_ENABLE, NULL); ICall_leaveCriticalSection(key); #ifndef POWER_SAVING //Initiate first read to start polling UART SDITLUART_readTransport(); #endif //POWER_SAVING return status; }
// ----------------------------------------------------------------------------- //! \brief This callback is invoked on Read completion of readSize/receive //! timeout //! //! \param[in] handle - handle to the UART port //! \param[in] ptr - pointer to buffer to read data into //! \param[in] size - size of the data //! //! \return void // ----------------------------------------------------------------------------- static void SDITLUART_readCallBack(UART_Handle handle, void *ptr, size_t size) { ICall_CSState key; key = ICall_enterCriticalSection(); uint8 errStatus = 0; if (errStatus = ((UARTCC26XX_Handle)handle->object)->status) { //report UART error status to application if(incomingRXErrorStatusAppCBFunc != NULL) incomingRXErrorStatusAppCBFunc(UART_ERROR_EVT, &errStatus, sizeof(errStatus)); } if (size) { if (size != SDITLUART_readIsrBuf(size)) { // Buffer overflow imminent. Cancel read and pass to higher layers // for handling #ifdef POWER_SAVING RxActive = FALSE; #endif //POWER_SAVING if ( sdiTransmitCB ) { sdiTransmitCB(SDI_TL_BUF_SIZE,TransportTxLen); } } } #ifdef POWER_SAVING // Read has been cancelled by transport layer, or bus timeout and no bytes in FIFO // - do not invoke another read if ( !UARTCharsAvail(((UARTCC26XX_HWAttrs const *)(uartHandle->hwAttrs))->baseAddr) && mrdy_flag ) { RxActive = FALSE; // If TX has also completed then we are safe to issue call back if ( !TxActive && sdiTransmitCB ) { sdiTransmitCB(TransportRxLen,TransportTxLen); } } else { UART_read(uartHandle, &isrRxBuf[0], UART_ISR_BUF_SIZE); } #else if ( sdiTransmitCB ) { sdiTransmitCB(size,0); } TransportRxLen = 0; UART_read(uartHandle, &isrRxBuf[0], UART_ISR_BUF_SIZE); #endif //POWER_SAVING ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine writes data from the buffer to the transport layer. //! //! \param[in] buf - Pointer to buffer to write data from. //! \param[in] len - Number of bytes to write. //! //! \return uint16 - the number of bytes written to transport // ----------------------------------------------------------------------------- uint16 NPITL_writeTL(uint8 *buf, uint16 len) { ICall_CSState key; key = ICall_enterCriticalSection(); // Writes are atomic at transport layer if ( NPITL_checkNpiBusy() ) { ICall_leaveCriticalSection(key); return 0; } // If len of message is greater than fragment size // then message must be sent over the span of multiple // fragments if ( len > NPI_MAX_FRAG_SIZE ) { msgFrag = buf + NPI_MAX_FRAG_SIZE; msgFragLen = len - NPI_MAX_FRAG_SIZE; len = NPI_MAX_FRAG_SIZE; } else { msgFrag = NULL; msgFragLen = 0; } memcpy(npiTxBuf, buf, len); npiTxBufLen = len; npiTxActive = TRUE; txPktCount++; len = transportWrite(npiTxBufLen); #if (NPI_FLOW_CTRL == 1) SRDY_ENABLE(); #endif // NPI_FLOW_CTRL = 1 ICall_leaveCriticalSection(key); return len; }
// ----------------------------------------------------------------------------- //! \brief This routine reads data from the UART //! //! \return void // ----------------------------------------------------------------------------- void NPITLUART_readTransport(void) { ICall_CSState key; key = ICall_enterCriticalSection(); #ifdef POWER_SAVING RxActive = TRUE; #endif //POWER_SAVING TransportRxLen = 0; UART_read(uartHandle, &isrRxBuf[0], UART_ISR_BUF_SIZE); ICall_leaveCriticalSection(key); }
void SDITLUART_closeUART(void) { ICall_CSState key; key = ICall_enterCriticalSection(); // Cancel any pending reads UART_readCancel(uartHandle); // Close / power off the UART. UART_close(uartHandle); ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine reads data from the UART //! //! \return void // ----------------------------------------------------------------------------- void NPITLUART_readTransport(void) { ICall_CSState key; key = ICall_enterCriticalSection(); #if (NPI_FLOW_CTRL == 1) RxActive = TRUE; #endif // NPI_FLOW_CTRL = 1 TransportRxLen = 0; UART_read(uartHandle, &isrRxBuf[0], UART_ISR_BUF_SIZE); ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This callback is invoked on Read completion of readSize/receive //! timeout //! //! \param[in] handle - handle to the UART port //! \param[in] ptr - pointer to buffer to read data into //! \param[in] size - size of the data //! //! \return void // ----------------------------------------------------------------------------- static void NPITLUART_readCallBack(UART_Handle handle, void *ptr, size_t size) { ICall_CSState key; key = ICall_enterCriticalSection(); if (size) { if (size != NPITLUART_readIsrBuf(size)) { // Buffer overflow imminent. Cancel read and pass to higher layers // for handling #ifdef POWER_SAVING RxActive = FALSE; #endif //POWER_SAVING if ( npiTransmitCB ) { npiTransmitCB(NPI_TL_BUF_SIZE,TransportTxLen); } } } #ifdef POWER_SAVING // Read has been cancelled by transport layer, or bus timeout and no bytes in FIFO // - do not invoke another read if ( !UARTCharsAvail(((UARTCC26XX_HWAttrs const *)(uartHandle->hwAttrs))->baseAddr) && mrdy_flag ) { RxActive = FALSE; // If TX has also completed then we are safe to issue call back if ( !TxActive && npiTransmitCB ) { npiTransmitCB(TransportRxLen,TransportTxLen); } } else { UART_read(uartHandle, &isrRxBuf[0], UART_ISR_BUF_SIZE); } #else if ( npiTransmitCB ) { npiTransmitCB(size,0); } TransportRxLen = 0; UART_read(uartHandle, &isrRxBuf[0], UART_ISR_BUF_SIZE); #endif //POWER_SAVING ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine is used to handle an MRDY transition from a task //! context. Certain operations such as UART_read() cannot be //! performed from a HWI context //! //! \return void // ----------------------------------------------------------------------------- void NPITL_handleMrdyEvent(void) { ICall_CSState key; key = ICall_enterCriticalSection(); // Check to make sure this event is not occurring during the next packet // transmission if ( PIN_getInputValue(MRDY_PIN) == 0 || (npiTxActive && mrdyPktStamp == txPktCount ) ) { transportMrdyEvent(); SRDY_ENABLE(); } ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine is called from the application context when REM RDY //! is de-asserted //! //! \return void // ----------------------------------------------------------------------------- void NPITLSPI_handleRemRdyEvent(void) { ICall_CSState key; key = ICall_enterCriticalSection(); // If write has not be set up then a read must occur during this // transaction. There is a possibility that after bidirectional // transaction there is an extra MRDY event. This event // could cause a double read (which would clear the RX Buffer) so this // check ignores the MRDY event if Rx is already in progress if (!tlWriteLen && !RxActive) { NPITLSPI_readTransport(); } ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine initializes and begins a SPI transaction //! //! \param[in] len - Number of bytes to write. //! //! \return uint8 - number of bytes written to transport // ----------------------------------------------------------------------------- uint16 NPITLSPI_writeTransport(uint16 len) { int16 i = 0; ICall_CSState key; key = ICall_enterCriticalSection(); TransportTxBufLen = len + SPI_TX_FIELD_LEN; // Shift TX message two bytes to give room for SPI header for( i = ( TransportTxBufLen - 1 ) ; i >= 0 ; i-- ) { TransportTxBuf[i + SPI_TX_HDR_LEN] = TransportTxBuf[i]; } // Add header (including a zero padding byte required by the SPI driver) TransportTxBuf[SPI_TX_ZERO_PAD_INDEX] = 0x00; TransportTxBuf[SPI_TX_SOF_INDEX] = SPI_SOF; TransportTxBuf[SPI_TX_LEN_INDEX] = len; // Calculate and append FCS at end of Frame TransportTxBuf[TransportTxBufLen - 1] = NPITLSPI_calcFCS(&TransportTxBuf[SPI_TX_LEN_INDEX],len + 1); // Clear DMA Rx buffer and clear extra Tx buffer bytes to ensure clean buffer // for next RX/TX memset(TransportRxBuf, 0, NPI_TL_BUF_SIZE); memset(&TransportTxBuf[TransportTxBufLen], 0, NPI_TL_BUF_SIZE - TransportTxBufLen); // set up the SPI Transaction spiTransaction.count = NPI_TL_BUF_SIZE; spiTransaction.txBuf = TransportTxBuf; spiTransaction.rxBuf = TransportRxBuf; // Check to see if transport is successful. If not, reset TxBufLen to allow // another write to be processed if( ! SPI_transfer(spiHandle, &spiTransaction) ) { TransportTxBufLen = 0; } ICall_leaveCriticalSection(key); return TransportTxBufLen; }
// ----------------------------------------------------------------------------- //! \brief This routine is called from the application context when MRDY is //! de-asserted //! //! \return void // ----------------------------------------------------------------------------- void NPITLSPI_handleMrdyEvent() { ICall_CSState key; key = ICall_enterCriticalSection(); // If we have not already set up a write then we must be reading // during this transaction. There is a possibility that after // bidirectional transaction there is an extra MRDY event. This event // could cause a double read (which would clear the RX Buffer) so this // check ignores the MRDY event if Rx is already in progress if (!TransportTxBufLen && !RxActive) { NPITLSPI_readTransport(); } ICall_leaveCriticalSection(key); return; }
// ----------------------------------------------------------------------------- //! \brief This routine initializes and begins a SPI transaction //! //! \param[in] len - Number of bytes to write. //! //! \return uint16_t - number of bytes written to transport // ----------------------------------------------------------------------------- uint16_t NPITLSPI_writeTransport(uint16_t len) { int16 i = 0; ICall_CSState key; key = ICall_enterCriticalSection(); // Shift all bytes in TX Buffer up ZERO_PAD indexes. SPI Driver clips off // first byte // NPI TL already shifts bytes up 1 index for SOF before calling write() for (i = len + 1; i > 0; i--) { npiTxBuf[i + ZERO_PAD] = npiTxBuf[i]; } // Clear zero pad bytes memset(npiTxBuf, 0, ZERO_PAD); npiTxBuf[NPI_SPI_MSG_SOF_IDX + ZERO_PAD] = NPI_SPI_MSG_SOF; npiTxBuf[len + ZERO_PAD + 1] = NPITLSPI_calcFCS((uint8_t *)&npiTxBuf[2],len); tlWriteLen = len + ZERO_PAD + 2; // 2 = SOF + FCS // Clear DMA Rx buffer and clear extra Tx buffer bytes to ensure clean buffer // for next RX/TX memset(npiRxBuf, 0, npiBufSize); memset(&npiTxBuf[tlWriteLen], 0, npiBufSize - tlWriteLen); // set up the SPI Transaction spiTransaction.count = npiBufSize; spiTransaction.txBuf = npiTxBuf; spiTransaction.rxBuf = npiRxBuf; // Check to see if transport is successful. If not, reset TxBufLen to allow // another write to be processed if (!SPI_transfer(spiHandle, &spiTransaction)) { tlWriteLen = 0; } ICall_leaveCriticalSection(key); return len; }
// ----------------------------------------------------------------------------- //! \brief This routine stops any pending reads //! //! \return void // ----------------------------------------------------------------------------- void NPITLUART_stopTransfer(void) { ICall_CSState key; key = ICall_enterCriticalSection(); mrdy_flag = 1; // If we have no bytes in FIFO yet we must assume there was nothing to read // or that the FIFO has already been read for this UART_read() // In either case UART_readCancel will call the read CB function and it will // invoke npiTransmitCB with the appropriate number of bytes read if (!UARTCharsAvail(((UARTCC26XX_HWAttrs const *)(uartHandle->hwAttrs))->baseAddr)) { RxActive = FALSE; UART_readCancel(uartHandle); } ICall_leaveCriticalSection(key); return; }
// ----------------------------------------------------------------------------- //! \brief This routine reads data from the transport layer //! and places it into the buffer. //! //! \return void // ----------------------------------------------------------------------------- void NPITLSPI_readTransport(void) { ICall_CSState key; key = ICall_enterCriticalSection(); tlWriteLen = 0; RxActive = TRUE; // Clear DMA Rx buffer and clear extra Tx buffer bytes to ensure clean buffer // for next RX/TX memset(npiRxBuf, 0, npiBufSize); memset(&npiTxBuf[tlWriteLen], 0, npiBufSize - tlWriteLen); // set up the SPI Transaction spiTransaction.txBuf = npiTxBuf; spiTransaction.rxBuf = npiRxBuf; spiTransaction.count = npiBufSize; SPI_transfer(spiHandle, &spiTransaction); ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine reads data from the transport layer //! and places it into the buffer. //! //! \return void // ----------------------------------------------------------------------------- void NPITLSPI_readTransport() { ICall_CSState key; key = ICall_enterCriticalSection(); RxActive = TRUE; TransportTxBufLen = 0; // Clear DMA Rx buffer and clear extra Tx buffer bytes to ensure clean buffer // for next RX/TX memset(TransportRxBuf, 0, NPI_TL_BUF_SIZE); memset(&TransportTxBuf[TransportTxBufLen], 0, NPI_TL_BUF_SIZE - TransportTxBufLen); // set up the SPI Transaction spiTransaction.txBuf = TransportTxBuf; spiTransaction.rxBuf = TransportRxBuf; spiTransaction.count = NPI_TL_BUF_SIZE; SPI_transfer(spiHandle, &spiTransaction); ICall_leaveCriticalSection(key); }
// ----------------------------------------------------------------------------- //! \brief This routine is called from the application context when MRDY is //! de-asserted //! //! \return void // ----------------------------------------------------------------------------- void NPITLUART_handleMrdyEvent(void) { ICall_CSState key; key = ICall_enterCriticalSection(); mrdy_flag = 0; // If we haven't already begun reading, now is the time before Master // potentially starts to send data // The !TxActive condition is because we will call UART_npiRead() prior to setting // TxActive true. There is the possibility that MRDY gets set high which // clears RxActive prior to us getting to this event. This will cause us to // read twice per transaction which will cause the transaction to never // complete if ( !RxActive && !TxActive ) { NPITLUART_readTransport(); } // If we have something to write, then the Master has signalled it is ready // to receive. Time to write. if ( TxActive ) { // Check to see if transport is successful. If not, reset TxLen to allow // another write to be processed if ( UART_write(uartHandle, TransportTxBuf, TransportTxLen) == UART_ERROR ) { TxActive = FALSE; TransportTxLen = 0; } } ICall_leaveCriticalSection(key); return; }