/***************************************************************************** * @fn HalUARTReadSPI * * @brief Execute a blocking read from master if Rx buffer is empty. Otherwise return up to 'len' * bytes of read data. * * @param buf - valid data buffer at least 'len' bytes in size * len - max length number of bytes to copy to 'buf' * * @return length of buffer that was read *****************************************************************************/ uint16 HalUARTReadSPI(uint8 *buf, uint16 len) { uint16 cnt = 0; if ((spiCfg.rxHead == 0) && (spiCfg.rxHead == spiCfg.rxTail)) { uint8 tmp; UxDBUF = 0; URXxIF = 0; // Slave signals ready for read by setting its ready flag first. SRDY_SET(); while (!MRDY_SET); do { while (!URXxIF && MRDY_SET); tmp = UxDBUF; URXxIF = 0; // Master ends slave read by clearing its ready flag first. if (!MRDY_SET) { break; } spiCfg.rxBuf[spiCfg.rxTail] = tmp; if (++spiCfg.rxTail >= HAL_UART_SPI_RX_MAX) { spiCfg.rxTail = 0; } } while(1); // Master blocks waiting for slave to clear its ready flag before continuing. SRDY_CLR(); } while ((spiCfg.rxHead != spiCfg.rxTail) && (cnt < len)) { *buf++ = spiCfg.rxBuf[spiCfg.rxHead++]; if (spiCfg.rxHead >= HAL_UART_SPI_RX_MAX) { spiCfg.rxHead = 0; } cnt++; } if (cnt == 0) { spiCfg.rxHead = spiCfg.rxTail = 0; } return cnt; }
/****************************************************************************** * @fn HalUARTWriteSPI * * @brief Write a buffer to the UART. * @brief Execute a blocking write to the master. * * @param buf - pointer to the buffer that will be written, not freed * len - length of * * @return length of the buffer that was sent *****************************************************************************/ uint16 HalUARTWriteSPI(uint8 *buf, uint16 len) { uint16 cnt; // Enforce all or none and at least one. if ((HAL_UART_SPI_TX_AVAIL() < len) || (len == 0)) { return 0; } UxDBUF = *buf++; for (cnt = 1; cnt < len; cnt++) { spiCfg.txBuf[spiCfg.txTail] = *buf++; if (spiCfg.txTail >= HAL_UART_SPI_TX_MAX-1) { spiCfg.txTail = 0; } else { spiCfg.txTail++; } } URXxIF = 0; // Master signals ready for slave write by setting its ready flag first. while (!MRDY_SET); // Master blocks waiting for slave to set its ready flag before continuing. SRDY_SET(); do { while (!URXxIF && MRDY_SET); UxDBUF = spiCfg.txBuf[spiCfg.txHead]; URXxIF = 0; if (spiCfg.txHead == spiCfg.txTail) { spiCfg.txBuf[spiCfg.txHead] = 0; } else if (++spiCfg.txHead >= HAL_UART_SPI_TX_MAX) { spiCfg.txHead = 0; } } while(MRDY_SET); // Master ends slave write by clearing its ready flag first. // Master blocks waiting for slave to set its ready flag before continuing. SRDY_CLR(); return cnt; }
/************************************************************************************************** * @fn sblInit * * @brief Initialization for SBL. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void sblInit(void) { HAL_BOARD_INIT(); vddWait(VDD_MIN_RUN); magicByte = SB_MAGIC_VALUE; /* This is in place of calling HalDmaInit() which would require init of the other 4 DMA * descriptors in addition to just Channel 0. */ HAL_DMA_SET_ADDR_DESC0(&dmaCh0); #if defined CC2530_MK znpCfg1 = ZNP_CFG1_SPI; #else znpCfg1 = P2_0; #endif if (znpCfg1 == ZNP_CFG1_SPI) { SRDY_CLR(); // 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. HalUARTInitSPI(); } else { halUARTCfg_t uartConfig; HalUARTInitISR(); uartConfig.configured = TRUE; uartConfig.baudRate = HAL_UART_BR_115200; uartConfig.flowControl = FALSE; uartConfig.flowControlThreshold = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.rx.maxBufSize = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.tx.maxBufSize = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.idleTimeout = 0; // CC2530 by #define - see hal_board_cfg.h uartConfig.intEnable = TRUE; uartConfig.callBackFunc = NULL; HalUARTOpenISR(&uartConfig); } }
/************************************************************************************************** * @fn sblWait * * @brief A timed-out wait loop that exits early upon receiving a force code/sbl byte. * * input parameters * * None. * * output parameters * * None. * * @return TRUE to run the code image, FALSE to run the SBL. ************************************************************************************************** */ static uint8 sblWait(uint16 sbl_wait_time) { uint32 dlyCnt; uint8 rtrn = FALSE; uint8 sbExec_rc; uint8 ch; if (znpCfg1 == ZNP_CFG1_SPI) { // Slave signals ready for read by setting its ready flag first. SRDY_SET(); // Flag to sbRx() to poll for 1 Rx byte instead of blocking read until MRDY_CLR. spiPoll = TRUE; dlyCnt = 0x38; // About 50 msecs. } else { URX0IE = 1; HAL_ENABLE_INTERRUPTS(); dlyCnt = (uint32)0x7332 * sbl_wait_time; //0x7332 gives about 1 second sbReportState(SB_STATE_WAITING); } while (1) { if (znpCfg1 == ZNP_CFG1_UART) { sbUartPoll(); sbExec_rc = sbExec(); if (sbExec_rc == SB_CMND_ENABLE_STATE_REPORTING) { sbReportState(SB_STATE_WAITING); } else if (sbExec_rc == SB_CMND_FORCE_RUN) { dlyCnt = 0; } else if ((sbExec_rc != SB_CMND_IDLE) && (sbExec_rc != SB_CMND_UNSUPPORTED)) { break; } } else // Note: the SPI implementation was left unchanged, since the new implementation // (as implemented for the UART) was not tested with SPI at this time. { if (sbRx(&ch, 1)) { if (ch == SB_FORCE_BOOT) { break; } else if (ch == SB_FORCE_RUN) { dlyCnt = 0; } } } if (dlyCnt-- == 0) { rtrn = TRUE; break; } } if (znpCfg1 == ZNP_CFG1_SPI) { // Master blocks waiting for slave to clear its ready flag before continuing. SRDY_CLR(); // Flag to sbRx() to now block while reading Rx bytes until MRDY_CLR. spiPoll = FALSE; } else { HAL_DISABLE_INTERRUPTS(); URX0IE = 0; } return rtrn; }