/************************************************************************************************** Filename: znp_spi.c Revised: $Date: 2010-07-28 18:42:54 -0700 (Wed, 28 Jul 2010) $ Revision: $Revision: 23203 $ Description: This file contains the interface to the H/W-specific ZNP SPI driver. Copyright 2009-2010 Texas Instruments Incorporated. All rights reserved. IMPORTANT: Your use of this Software is limited to those specific rights granted under the terms of a software license agreement between the user who downloaded the software, his/her employer (which must be your employer) and Texas Instruments Incorporated (the "License"). You may not use this Software unless you agree to abide by the terms of the License. The License limits your use, and you acknowledge, that the Software may not be modified, copied or distributed unless embedded on a Texas Instruments microcontroller or used solely and exclusively in conjunction with a Texas Instruments radio frequency transceiver, which is integrated into your product. Other than for the foregoing purpose, you may not use, reproduce, copy, prepare derivative works of, modify, distribute, perform, display or sell this Software and/or its documentation for any purpose. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. Should you have any questions regarding your right to use this Software, contact Texas Instruments Incorporated at www.TI.com. **************************************************************************************************/ /* ------------------------------------------------------------------------------------------------ * Includes * ------------------------------------------------------------------------------------------------ */ #include "comdef.h" #include "hal_assert.h" #include "hal_dma.h" #include "MT_RPC.h" #include "OnBoard.h" #include "osal.h" #if defined POWER_SAVING #include "OSAL_PwrMgr.h" #endif #include "ZDApp.h" #include "znp_app.h" #include "znp_spi.h" /* ------------------------------------------------------------------------------------------------ * Macros * ------------------------------------------------------------------------------------------------ */ /* * The MAC_ASSERT macro is for use during debugging. * The given expression must evaluate as "true" or else fatal error occurs. * At that point, the call stack feature of the debugger can pinpoint where the problem occurred. * * To disable this feature and save code size, the project should define NP_SPI_NODEBUG to TRUE. */ #if !defined ( NP_SPI_NODEBUG ) #define NP_SPI_NODEBUG TRUE #endif #if ( NP_SPI_NODEBUG ) #define NP_SPI_ASSERT( expr ) #else #define NP_SPI_ASSERT( expr) HAL_ASSERT( expr ) #endif #if defined CC2530_MK #define DMATRIG_RX HAL_DMA_TRIG_URX0 #define DMATRIG_TX HAL_DMA_TRIG_UTX0 #define DMA_UDBUF NP_SPI_U0DBUF #else #define DMATRIG_RX HAL_DMA_TRIG_URX1 #define DMATRIG_TX HAL_DMA_TRIG_UTX1 #define DMA_UDBUF NP_SPI_U1DBUF #endif #define DMA_RX() \ st( \ volatile uint8 clearRx = *((uint8 *)DMA_UDBUF); \ \ HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX); \ \ HAL_DMA_ARM_CH(HAL_DMA_CH_RX); \ ) #define DMA_TX( buf ) \ st( \ halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX); \ \ HAL_DMA_SET_SOURCE(ch, (buf)); \ \ HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX); \ \ HAL_DMA_ARM_CH(HAL_DMA_CH_TX); \ \ HAL_DMA_START_CH(HAL_DMA_CH_TX); \ ) #define HAL_DMA_GET_SOURCE( pDesc, src ) \ st( \ src = (uint16)(pDesc->srcAddrH) << 8; \ src += pDesc->srcAddrL; \ ) /* ------------------------------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------------------------------ */ #define NP_SPI_U0DBUF 0x70C1 #define NP_SPI_U1DBUF 0x70F9 /* UxCSR - USART Control and Status Register. */ #define CSR_MODE 0x80 #define CSR_RE 0x40 #define CSR_SLAVE 0x20 #define CSR_FE 0x10 #define CSR_ERR 0x08 #define CSR_RX_BYTE 0x04 #define CSR_TX_BYTE 0x02 #define CSR_ACTIVE 0x01 /* UxUCR - USART UART Control Register. */ #define UCR_FLUSH 0x80 #define UCR_FLOW 0x40 #define UCR_D9 0x20 #define UCR_BIT9 0x10 #define UCR_PARITY 0x08 #define UCR_SPB 0x04 #define UCR_STOP 0x02 #define UCR_START 0x01 #define UTX0IE 0x04 #define UTX1IE 0x08 #define NP_SPI_RX_SREQ_EVENT ZNP_SPI_RX_SREQ_EVENT #define NP_SPI_RX_AREQ_EVENT ZNP_SPI_RX_AREQ_EVENT /* Reference data sheet section 8.2.4: When using variable-length transfers, then LEN * should be set to the largest allowed transfer length plus one. */ #define NP_SPI_BUF_LEN (MT_RPC_DATA_MAX + MT_RPC_FRAME_HDR_SZ + 1) #if defined CC2530_MK #define NP_RDYIn_BIT BV(0) #define NP_RDYIn P2_0 #define NP_RDYOut P1_0 #define NP_RDYOut_BIT BV(0) #elif !defined CC2530ZNP_MK #define NP_RDYIn_BIT BV(3) #define NP_RDYIn P0_3 #define NP_RDYOut P0_4 #define NP_RDYOut_BIT BV(4) #endif #define NP_CSR_MODE BV(5) // CSR_SLAVE /* ------------------------------------------------------------------------------------------------ * TypeDefs * ------------------------------------------------------------------------------------------------ */ typedef enum { NP_SPI_IDLE, /* Idle, no transaction in progress. */ NP_SPI_MRDY, /* Idle, but got MRDY ISR, so waiting to enable the RX DMA. */ NP_SPI_WAIT_RX, /* Waiting for RX to complete. */ NP_SPI_WAIT_TX, /* Waiting for TX to complete. */ NP_SPI_WAIT_AREQ, /* Waiting for asynchronous request to finish processing. */ NP_SPI_WAIT_SREQ /* Waiting for a synchronous request to finish processing. */ } spiState_t; /* ------------------------------------------------------------------------------------------------ * Local Variables * ------------------------------------------------------------------------------------------------ */ static uint8 npSpiBuf[NP_SPI_BUF_LEN]; static volatile spiState_t npSpiState; /* ------------------------------------------------------------------------------------------------ * Local Functions * ------------------------------------------------------------------------------------------------ */ static void dmaInit(void); /************************************************************************************************** * @fn dmaInit * * @brief This function initializes the DMA for the SPI driver. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void dmaInit(void) { halDMADesc_t *ch; /* Setup Tx by DMA. */ ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX); /* The start address of the source and destination. */ HAL_DMA_SET_SOURCE(ch, npSpiBuf); HAL_DMA_SET_DEST(ch, DMA_UDBUF); /* Transfer the first byte + the number of bytes indicated by the first byte + 2 more bytes. */ HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_1_P_VALOFFIRST_P_2); HAL_DMA_SET_LEN(ch, NP_SPI_BUF_LEN); /* One byte is transferred each time. */ HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE); /* The bytes are transferred 1-by-1 on Tx Complete trigger. */ HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE); HAL_DMA_SET_TRIG_SRC(ch, DMATRIG_TX); /* The source address is decremented by 1 byte after each transfer. */ HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_1); /* The destination address is constant - the Tx Data Buffer. */ HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0); /* The DMA shall issue an IRQ upon completion. */ HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_ENABLE); /* Xfer all 8 bits of a byte xfer. */ HAL_DMA_SET_M8(ch, HAL_DMA_M8_USE_8_BITS); /* DMA has highest priority for memory access. */ HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH); /* Setup Rx by DMA. */ ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_RX); /* The start address of the source and destination. */ HAL_DMA_SET_SOURCE(ch, DMA_UDBUF); HAL_DMA_SET_DEST(ch, npSpiBuf); /* Transfer the first byte + the number of bytes indicated by the first byte + 2 more bytes. */ HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_1_P_VALOFFIRST_P_2); HAL_DMA_SET_LEN(ch, NP_SPI_BUF_LEN); HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE); /* The bytes are transferred 1-by-1 on Rx Complete trigger. */ HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE); HAL_DMA_SET_TRIG_SRC(ch, DMATRIG_RX); /* The source address is constant - the Rx Data Buffer. */ HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_0); /* The destination address is incremented by 1 byte after each transfer. */ HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_1); /* The DMA shall issue an IRQ upon completion. */ HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_ENABLE); /* Xfer all 8 bits of a byte xfer. */ HAL_DMA_SET_M8(ch, HAL_DMA_M8_USE_8_BITS); /* DMA has highest priority for memory access. */ HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH); } /************************************************************************************************** * @fn npSpiInit * * @brief This function is called to set up the SPI interface. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ #if defined CC2530_MK void npSpiInit(void) // TODO - hard-coded for USART0 alt1 SPI for now. { if (ZNP_CFG1_UART == znpCfg1) { return; } /* Set bit order to MSB */ U0GCR |= BV(5); /* Set UART0 I/O to alternate 1 location on P1 pins. */ //PERCFG |= 0x02; /* U1CFG */ /* Mode select UART1 SPI Mode as slave. */ U0CSR = NP_CSR_MODE; /* Select peripheral function on I/O pins. */ P0SEL |= 0x3C; /* SELP0_[5:2] */ /* Give UART1 priority over Timer3. */ //P2SEL &= ~0x20; /* PRI2P1 */ /* Set RDY to inactive high. */ NP_RDYOut = 1; /* Select general purpose on I/O pins. */ P1SEL &= ~(NP_RDYOut_BIT); /* P1.0 SRDY - GPIO */ P2SEL &= ~(NP_RDYIn_BIT); /* P2.0 MRDY - GPIO */ /* Select GPIO direction */ P1DIR |= NP_RDYOut_BIT; /* P1.0 SRDY - OUT */ P2DIR &= ~NP_RDYIn_BIT; /* P2.0 MRDY - IN */ /* Falling edge on P2 pins triggers interrupt. */ PICTL |= BV(3); /* P2ICON */ /* Trigger an interrupt on MRDY input. */ P2IFG &= ~NP_RDYIn_BIT; P2IEN |= NP_RDYIn_BIT; IEN2 |= 0x02; dmaInit(); U0CSR |= CSR_RE; } #else void npSpiInit(void) { if (ZNP_CFG1_UART == znpCfg1) { return; } /* Set bit order to MSB */ U1GCR |= BV(5); /* Set UART1 I/O to alternate 2 location on P1 pins. */ PERCFG |= 0x02; /* U1CFG */ /* Mode select UART1 SPI Mode as slave. */ U1CSR = NP_CSR_MODE; /* Select peripheral function on I/O pins. */ P1SEL |= 0xF0; /* SELP1_[7:4] */ /* Give UART1 priority over Timer3. */ P2SEL &= ~0x20; /* PRI2P1 */ /* Set RDY to inactive high. */ NP_RDYOut = 1; /* Select general purpose on I/O pins. */ P0SEL &= ~(NP_RDYIn_BIT); /* P0.3 MRDY - GPIO */ P0SEL &= ~(NP_RDYOut_BIT); /* P0.4 SRDY - GPIO */ /* Select GPIO direction */ P0DIR &= ~NP_RDYIn_BIT; /* P0.3 MRDY - IN */ P0DIR |= NP_RDYOut_BIT; /* P0.4 SRDY - OUT */ P0INP &= ~NP_RDYIn_BIT; /* Pullup/down enable of MRDY input. */ P2INP &= ~BV(5); /* Pullup all P0 inputs. */ /* Falling edge on P0 pins triggers interrupt. */ PICTL |= BV(0); /* P0ICON */ /* Trigger an interrupt on MRDY input. */ P0IFG &= ~NP_RDYIn_BIT; P0IEN |= NP_RDYIn_BIT; P0IE = 1; dmaInit(); U1CSR |= CSR_RE; } #endif /************************************************************************************************** * @fn npSpiMonitor * * @brief This function monitors the SPI signals for error conditions and for the end of a * transaction. If an error is detected it attempts to recover. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiMonitor(void) { if (ZNP_CFG1_UART == znpCfg1) { return; } #if ZNP_RUN_WDOG if ((devState != DEV_HOLD) && (npSpiState == NP_SPI_IDLE)) { // Enable the watchdog for 1 second period and pet it. WatchDogEnable( WDTIMX ); } #endif switch (npSpiState) { case NP_SPI_IDLE: NP_SPI_ASSERT((P1IFG & NP_RDYIn_BIT) == 0); break; #if defined POWER_SAVING case NP_SPI_MRDY: npSpiState = NP_SPI_WAIT_RX; DMA_RX(); NP_RDYOut = 0; break; #endif case NP_SPI_WAIT_RX: NP_SPI_ASSERT((HAL_DMA_CHECK_IRQ(HAL_DMA_CH_RX)) == 0); break; case NP_SPI_WAIT_TX: NP_SPI_ASSERT((HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX)) == 0); break; case NP_SPI_WAIT_AREQ: break; default: NP_SPI_ASSERT(0); break; } if (npSpiState == NP_SPI_IDLE) { *((uint8 *)DMA_UDBUF) = 0; // Clear the SPI Tx buffer to zero. /* Poll for MRDY in case it was set before slave had setup the ISR. * Also, async responses may get queued, so flush them out here. */ if ((NP_RDYIn == 0) || (npSpiReadyCallback())) { npSpiAReqReady(); } } else { halIntState_t his; HAL_ENTER_CRITICAL_SECTION(his); if (((npSpiState == NP_SPI_WAIT_RX) && (!HAL_DMA_CH_ARMED(HAL_DMA_CH_RX) && !HAL_DMA_CHECK_IRQ(HAL_DMA_CH_RX))) || ((npSpiState == NP_SPI_WAIT_TX) && (!HAL_DMA_CH_ARMED(HAL_DMA_CH_TX) && !HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX)))) { HAL_EXIT_CRITICAL_SECTION(his); if (npSpiState == NP_SPI_WAIT_RX) { npSpiRxIsr(); } else // if (npSpiState == NP_SPI_WAIT_TX) { npSpiTxIsr(); } } else { HAL_EXIT_CRITICAL_SECTION(his); } } #if defined POWER_SAVING /* A simple ZAP application sending a unicast at 2-Hz was seen to bog down to < 1-Hz OTA unicast * when the ZNP was configured to be a ZED (i.e. POWER_SAVING was enabled). So adding this delay * of only 10 msecs before re-enabling CONSERVE showed that the problem was fixed while still * allowing the ZNP to enter sleep. */ static uint8 znpSpiActiveShdw; if (ZG_DEVICE_ENDDEVICE_TYPE && (npSpiState == NP_SPI_IDLE)) { if (znpSpiActiveShdw) { uint8 rxOnIdle; (void)ZMacGetReq(ZMacRxOnIdle, &rxOnIdle); if (!rxOnIdle) { znpSpiActiveShdw = FALSE; if (ZSuccess != osal_start_timerEx(znpTaskId, ZNP_PWRMGR_CONSERVE_EVENT, ZNP_PWRMGR_CONSERVE_DELAY)) { (void)osal_set_event(znpTaskId, ZNP_PWRMGR_CONSERVE_EVENT); } } } } else if (!znpSpiActiveShdw) { znpSpiActiveShdw = TRUE; (void)osal_stop_timerEx(znpTaskId, ZNP_PWRMGR_CONSERVE_EVENT); (void)osal_clear_event(znpTaskId, ZNP_PWRMGR_CONSERVE_EVENT); (void)osal_pwrmgr_task_state(znpTaskId, PWRMGR_HOLD); } #endif } /************************************************************************************************** * @fn npSpiSRspAlloc * * @brief This function is called by MT to allocate a buffer in which to build an SRSP frame. * MT must only call this function after processing a received SREQ frame. * * input parameters * * @param len - Length of the buffer required. * * output parameters * * None. * * @return NULL for failure; a pointer to the npSpiBuf on success. Success is determined by * the correct npSpiState and H/W signals as well as a valid length request. ************************************************************************************************** */ uint8 *npSpiSRspAlloc(uint8 len) { if (npSpiState == NP_SPI_WAIT_SREQ) { return npSpiBuf; } else { return NULL; } } /************************************************************************************************** * @fn npSpiAReqAlloc * * @brief This function is called by MT to allocate a buffer in which to buld an AREQ frame. * * input parameters * * @param len - Length of the buffer required. * * output parameters * * None. * * @return NULL for failure; otherwise a pointer to the data of an osal message. ************************************************************************************************** */ uint8 *npSpiAReqAlloc(uint8 len) { return osal_msg_allocate(len + MT_RPC_FRAME_HDR_SZ); } /************************************************************************************************** * @fn npSpiSRspReady * * @brief This function is called by MT to notify SPI driver that an SRSP is ready to Tx. * * input parameters * * @param pBuf - Pointer to the buffer to transmit on the SPI. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiSRspReady(uint8 *pBuf) { if ((npSpiState == NP_SPI_WAIT_SREQ) && (NP_RDYOut == 0)) { npSpiState = NP_SPI_WAIT_TX; DMA_TX( pBuf ); NP_RDYOut = 1; } } /************************************************************************************************** * @fn npSpiAReqReady * * @brief This function is called by MT to notify the SPI driver that an AREQ frame is ready * to be transmitted. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiAReqReady(void) { halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); if (npSpiState == NP_SPI_IDLE) { npSpiState = NP_SPI_WAIT_RX; DMA_RX(); NP_RDYOut = 0; } HAL_EXIT_CRITICAL_SECTION(intState); } /************************************************************************************************** * @fn npSpiAReqComplete * * @brief This function is called by MT to notify the SPI driver that the processing of a * received AREQ is complete. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiAReqComplete(void) { if (npSpiState == NP_SPI_WAIT_AREQ) { npSpiState = NP_SPI_IDLE; } } /************************************************************************************************** * @fn npSpiGetReqBuf * * @brief This function is called by the application to get the buffer containing the * currently received AREQ or SREQ. * * input parameters * * None. * * output parameters * * None. * * @return Pointer to the buffer containing the currently received AREQ or SREQ. ************************************************************************************************** */ uint8 *npSpiGetReqBuf(void) { if (npSpiState != NP_SPI_IDLE) { return npSpiBuf; } else { return NULL; } } /************************************************************************************************** * @fn npSpiMrdyIsr * * @brief This function is called when a GPIO falling-edge interrupt occurs on the MRDY. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiMrdyIsr(void) { if (npSpiState == NP_SPI_IDLE) { #if defined POWER_SAVING if (ZG_DEVICE_ENDDEVICE_TYPE) { npSpiState = NP_SPI_MRDY; } else #endif { npSpiState = NP_SPI_WAIT_RX; DMA_RX(); NP_RDYOut = 0; } } } /************************************************************************************************** * @fn npSpiRxIsr * * @brief This function handles the DMA Rx complete interrupt. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiRxIsr(void) { mtRpcCmdType_t type = (mtRpcCmdType_t)(npSpiBuf[1] & MT_RPC_CMD_TYPE_MASK); uint8 *pBuf, rdy = 1; NP_SPI_ASSERT(npSpiState == NP_SPI_WAIT_RX); switch (type) { case MT_RPC_CMD_POLL: if ( (pBuf = npSpiPollCallback()) == NULL ) { pBuf = npSpiBuf; npSpiBuf[0] = 0; npSpiBuf[1] = 0; npSpiBuf[2] = 0; } npSpiState = NP_SPI_WAIT_TX; DMA_TX(pBuf); break; case MT_RPC_CMD_SREQ: npSpiState = NP_SPI_WAIT_SREQ; osal_set_event(znpTaskId, ZNP_SPI_RX_SREQ_EVENT); rdy = 0; break; case MT_RPC_CMD_AREQ: npSpiState = NP_SPI_WAIT_AREQ; osal_set_event(znpTaskId, ZNP_SPI_RX_AREQ_EVENT); break; default: npSpiState = NP_SPI_IDLE; break; } NP_RDYOut = rdy; } /************************************************************************************************** * @fn npSpiTxIsr * * @brief This function handles the DMA Tx complete interrupt. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiTxIsr(void) { halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX); uint16 src; NP_SPI_ASSERT(npSpiState == NP_SPI_WAIT_TX); HAL_DMA_GET_SOURCE( ch, src ); if ((uint8 *)src != npSpiBuf) { osal_msg_deallocate((uint8 *)src); } npSpiState = NP_SPI_IDLE; } /************************************************************************************************** * @fn npSpiIdle * * @brief This function returns true if SPI is idle and there is no queued data. * * input parameters * * None. * * output parameters * * None. * * @return True if SPI is idle with no quequed data. ************************************************************************************************** */ bool npSpiIdle(void) { return (npSpiState == NP_SPI_IDLE && !npSpiReadyCallback()); } /************************************************************************************************** * @fn portN-Isr * * @brief This function handles the PORT-N interrupt. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ #if defined CC2530_MK HAL_ISR_FUNCTION(port2Isr, P2INT_VECTOR) { P2IFG = 0; P2IF = 0; #else HAL_ISR_FUNCTION(port0Isr, P0INT_VECTOR) { P0IFG = 0; P0IF = 0; #endif // Knowing which pin requires a #define from _hal_uart_dma.c //if (P0IFG & NP_RDYIn_BIT) { if (ZNP_CFG1_UART == znpCfg1) { osal_set_event(znpTaskId, ZNP_UART_TX_READY_EVENT); } else { npSpiMrdyIsr(); } } } /************************************************************************************************** */