/*****************************************************************************/ /** * @file systembus.c * @author FanHao (hao_fan_bit_ee@163.com) * @brief System bus protocol implementation file. * @version 0.1 * @date 2023-05-06 * * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n * Lab of Communication and Network * ******************************************************************************/ /** * @addtogroup SystemBus * @{ */ /***************************** Include Files *********************************/ #include #include #include #include #include "systembus_uart.h" #include "systembus.h" #include "util.h" #include "common.h" #include "error.h" #include "circ_queue.h" #include "../system_monitor.h" /** * @addtogroup SystemBus_Protocol_Routine * @{ */ /************************** Constant Definitions *****************************/ /** * @name SystemBus_MSG_Constants * @{ */ // Common Field // -- Command word #define WD_CMD 0x00 // -- Production type #define WD_PRD 0x01 #define PRD_DL_K 0xDD #define PRD_DL_S 0xEE #define PRD_ALL 0xFF // Self-Test #define CMD_SELF_TEST 0xE1 // -- Request // -- -- -- // -- Response // -- -- Self-Test Result #define ST_RSP_LEN 16 #define WD_ST_RET 0x02 #define ST_RET_OK 0xAA #define ST_RET_ERROR 0x55 #define ST_RET_INFO_LEN 13 // -- -- Signal processor PS voltage #define WD_SP_FPGA_VOLT 0x03 // -- -- Signal processor PS AUX voltage #define WD_SP_CLK_STATE 0x04 // -- -- Signal processor DDR voltage #define WD_SP_AD_LOCK_STATE 0x05 // -- -- Signal processor PL voltage #define WD_SP_AD_TEMP_0 0x06 // -- -- Signal processor PL AUX voltage #define WD_SP_AD_TEMP_1 0x07 // -- -- Signal processor Bram voltage #define WD_SP_FPGA_TEMP 0x08 // -- -- Signal processor antenna voltage status #define WD_ANT_VOLT 0x09 // -- -- Signal processor antenna RF temperature #define WD_ANT_RF_TEMP 0x0A // -- -- Signal processor antenna PLL lock status #define WD_ANT_RF_PLL 0x0B // -- -- Signal processor antenna MGC #define WD_ANT_MGC_0 0x0C #define WD_ANT_MGC_1 0x0D // -- -- Reserved #define WD_ANT_RESERVE 0x0E // Data Send Test Command #define CMD_DATA_TEST_A 0xE2 // -- Request #define DATA_TEST_REQ_A_LEN 68 // -- -- 68 byte payload // -- Response #define DATA_TEST_RSP_A_LEN 68 // -- -- 68 byte payload // Data Send Test Command #define CMD_DATA_TEST_B 0xF2 // -- Request #define DATA_TEST_REQ_B_LEN 170 // -- -- 170 byte payload // -- Response #define DATA_TEST_RSP_B_LEN 170 // -- -- 170 byte payload // Config load #define CMD_CONFIG 0xE3 // -- Request #define WD_EN_CMD 0x02 #define EN_CMD_ON_HIGH_POWER 0x66 #define EN_CMD_ON_LOW_POWER 0x77 #define EN_CMD_SILENT 0x88 #define WD_MODE_CMD 0x03 #define MODE_CMD_HEAD 0x11 #define MODE_CMD_MEMBER 0x00 // -- Response // -- -- none response // System info update #define CMD_SYS_INFO 0x33 #define SYS_INFO_OFFSET 2 // -- Request // -- -- 54 byte system info // -- Response // -- -- none response // Data Send Test Command #define CMD_FLJ_SEND 0xE4 #define FLJ_DATA_OFFSET 2 // -- Request // -- -- 78 byte payload // -- Response // -- -- none response // Data Send Test Command #define CMD_LJ_SEND 0xF4 #define LJ_DATA_OFFSET 2 // -- Request // -- -- 156 byte payload // -- Response // -- -- none response // FLJ Poll #define CMD_FLJ_POLL 0xE5 // -- Request #define WD_FLJ_POLL 0x02 #define FLJ_POLL_CODE 0x77 // -- Response #define FLJ_POLL_RESP_LEN 170 // -- -- received 170 byte payload // LJ Poll #define CMD_LJ_POLL 0xF5 // -- Request #define WD_LJ_POLL 0x02 #define LJ_POLL_CODE 0x77 // -- Response #define LJ_POLL_RESP_LEN 68 // -- -- received 68 byte payload // Remote Test FLJ #define CMD_FLJ_RM_TEST 0xE6 // -- Request #define WD_FLJ_RM_TEST 0x02 #define FLJ_RM_TEST_CODE 0x99 // -- Response #define WD_FLJ_TIME_STAMP 0x02 #define WD_FLJ_TIME_STAMP_LEN 8 #define WD_FLJ_SYSBUS_LOG 0x0A #define WD_FLJ_SYSBUS_LOG_LEN 14 #define WD_FLJ_LINK_LOG 0x18 #define WD_FLJ_LINK_LOG_LEN 64 #define WD_FLJ_PHY_LOG 0x58 #define WD_FLJ_PHY_LOG_LEN 57 #define WD_FLJ_HARDWARE_ST 0x91 #define WD_FLJ_HARDWARE_ST_LEN 13 #define FLJ_RM_TEST_RESP_LEN 158 // Remote Test LJ #define CMD_LJ_RM_TEST 0xF6 // -- Request #define WD_LJ_RM_TEST 0x02 #define LJ_RM_TEST_CODE 0x99 // -- Response #define WD_LJ_TIME_STAMP 0x02 #define WD_LJ_TIME_STAMP_LEN 8 #define WD_LJ_SYSBUS_LOG 0x0A #define WD_LJ_SYSBUS_LOG_LEN 14 #define WD_LJ_LINK_LOG 0x18 #define WD_LJ_LINK_LOG_LEN 64 #define WD_LJ_PHY_LOG 0x58 #define WD_LJ_PHY_LOG_LEN 57 #define WD_LJ_HARDWARE_ST 0x91 #define WD_LJ_HARDWARE_ST_LEN 13 #define LJ_RM_TEST_RESP_LEN 158 // My Production Type #define MY_PRD_ID PRD_DL_K /** @} SystemBus_MSG_Constants*/ /************************** Function Prototypes ******************************/ static int32_t SystemBus_GenSelfTestRsp(SYSBUS *instPtr); static int32_t SystemBus_SystemConfig(SYSBUS *instPtr, uint8_t *msg); static int32_t SystemBus_Echo(SYSBUS *instPtr, SYSBUS_UART_FRAME *frame); static int32_t SystemBus_GenPollRsp(SYSBUS *instPtr, uint8_t *msg); static int32_t SystemBus_GenRemoteTestRsp(SYSBUS *instPtr, uint8_t *msg); /**************************** Type Definitions *******************************/ /************************** Variable Definitions *****************************/ // TODO: better approach? #include "../networking/link_layer/link_layer.h" #include "../networking/phy_layer/phy_layer.h" extern L2_INST *linkInstPtr; extern L2_CONFIG linkConfig; inline bool SystemBus_IsReqPending(SYSBUS *instPtr) { ASSERT(instPtr != NULL); return (!isCircQueueEmpty(instPtr->rxQueue)); } inline bool SystemBus_IsRsqPending(SYSBUS *instPtr) { ASSERT(instPtr != NULL); return (!isCircQueueEmpty(instPtr->txQueue)); } inline bool SystemBus_IsTxBusy(SYSBUS *instPtr) { ASSERT(instPtr != NULL); return (!instPtr->isTxDone); } inline bool SystemBus_IsRxBusy(SYSBUS *instPtr) { ASSERT(instPtr != NULL); return SysbusUart_IsRxBusy(instPtr->uartInst); } /** * @brief Generate System Bus SelfTest response. */ static int32_t SystemBus_GenSelfTestRsp(SYSBUS *instPtr) { ASSERT(instPtr != NULL); SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); if (sysbusRsp == NULL) { DBG_ERROR("Failed to allocate memory for SELF TEST Response!\n"); return ENOMEM; } HWSTATE *hwStatsPtr = &(instPtr->hwState); sysbusRsp->len = ST_RSP_LEN; memset(sysbusRsp->data, 0x00, ST_RSP_LEN); sysbusRsp->data[WD_CMD] = CMD_SELF_TEST; sysbusRsp->data[WD_PRD] = MY_PRD_ID; SysMonitor_GetHardwareStatus(hwStatsPtr); if (L2_isStarted(linkInstPtr)) { sysbusRsp->data[WD_ST_RET] = (hwStatsPtr->isSpOk && hwStatsPtr->isAntOk) ? ST_RET_OK : ST_RET_ERROR; } else { sysbusRsp->data[WD_ST_RET] = (hwStatsPtr->isSpOk) ? ST_RET_OK : ST_RET_ERROR; } // apply status and omit 2 bytes of overhead. memcpy(sysbusRsp->data + WD_SP_FPGA_VOLT, &(hwStatsPtr->spFpgaVolt), ST_RET_INFO_LEN); if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) { free(sysbusRsp); DBG_ERROR("SystemBus::TX Queue overflowed!\n"); return EQUEUE; } return SUCCESS; } /** * @brief Apply system configuration */ static int32_t SystemBus_SystemConfig(SYSBUS *instPtr, uint8_t *msg) { ASSERT(instPtr != NULL); ASSERT(msg != NULL); PHY_INST *phyRef = linkInstPtr->config.phyInstPtr; TMC_INST *tmcRef = linkInstPtr->config.tmcInstPtr; bool reconfig = false; if (msg[WD_MODE_CMD] == MODE_CMD_HEAD) { // head node config reconfig = (L2_NODE_HEAD != L2_GetNodeType(linkInstPtr)); linkConfig.myType = L2_NODE_HEAD; linkConfig.myId = 1; } else if (msg[WD_MODE_CMD] == MODE_CMD_MEMBER) { // member node config reconfig = (L2_NODE_MEMBER != L2_GetNodeType(linkInstPtr)); linkConfig.myType = L2_NODE_MEMBER; linkConfig.myId = 2; } else { // Ignore current command DBG_ERROR("Unexpected config command 0x%02X:0x%02X", WD_MODE_CMD, msg[WD_MODE_CMD]); return EPARAM; } if (msg[WD_EN_CMD] == EN_CMD_ON_HIGH_POWER) { // full power config Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_FULL); if (reconfig || !L2_isStarted(linkInstPtr)) { Linklayer_Reconfig(linkInstPtr, &linkConfig); } Linklayer_Start(linkInstPtr); } else if (msg[WD_EN_CMD] == EN_CMD_ON_LOW_POWER) { // low power config Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_LOW); if (reconfig || !L2_isStarted(linkInstPtr)) { Linklayer_Reconfig(linkInstPtr, &linkConfig); } Linklayer_Start(linkInstPtr); } else if (msg[WD_EN_CMD] == EN_CMD_SILENT) { // silence config // TODO: better approach? Linklayer_Halt(linkInstPtr); Phy_AntConfigMode(phyRef, PHY_ANT_MODE_STANDBY); TIME_WORD pullTime = {0, 0}; pullTime.int_part = TimeCtrl_GetIntCnt(tmcRef) + 1; if (Phy_SetTimeWord(phyRef, &pullTime, PHY_TIME_WORD_POLL) != SUCCESS) { DBG_ERROR("Physical set pull time failed.\n"); } Phy_SetupNextSlot(phyRef, PHY_TOR_RX, L1_10KBPS_10MS_FRAME, NULL); } else { // Ignore current command DBG_ERROR("Unexpected config command 0x%02X:0x%02X", WD_EN_CMD, msg[WD_EN_CMD]); return EIGNORE; } instPtr->sysbusLog.lastConfig[0] = msg[WD_MODE_CMD]; instPtr->sysbusLog.lastConfig[1] = msg[WD_EN_CMD]; return SUCCESS; } /** * @brief Echo System Bus frame */ static int32_t SystemBus_Echo(SYSBUS *instPtr, SYSBUS_UART_FRAME *frame) { ASSERT(instPtr != NULL); ASSERT(frame != NULL); SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); if (sysbusRsp == NULL) { DBG_ERROR("Failed to allocate memory for DATA TEST A Response!\n"); return ENOMEM; } sysbusRsp->len = frame->len; memcpy(sysbusRsp->data, frame->data, sysbusRsp->len); if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) { free(sysbusRsp); DBG_ERROR("SystemBus::TX Queue overflowed!\n"); return EQUEUE; } return SUCCESS; } /** * @brief Generate System Bus poll call command response */ static int32_t SystemBus_GenPollRsp(SYSBUS *instPtr, uint8_t *msg) { ASSERT(instPtr != NULL); ASSERT(msg != NULL); size_t dataLen; uint8_t *payload; SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); if (sysbusRsp == NULL) { DBG_ERROR("Failed to allocate memory for FLJ POLL Response!\n"); return ENOMEM; } if (msg[WD_CMD] == CMD_FLJ_POLL) { sysbusRsp->len = FLJ_POLL_RESP_LEN; sysbusRsp->data[WD_CMD] = CMD_FLJ_POLL; sysbusRsp->data[WD_PRD] = MY_PRD_ID; dataLen = PAYLOAD_LEN_FLJ_RX; payload = sysbusRsp->data + FLJ_DATA_OFFSET; } else if (msg[WD_CMD] == CMD_LJ_POLL) { sysbusRsp->len = LJ_POLL_RESP_LEN; sysbusRsp->data[WD_CMD] = CMD_LJ_POLL; sysbusRsp->data[WD_PRD] = MY_PRD_ID; dataLen = PAYLOAD_LEN_LJ_RX; payload = sysbusRsp->data + LJ_DATA_OFFSET; } else { DBG_ERROR("Unexpected command 0x%02X.\n", msg[WD_CMD]); free(sysbusRsp); return EUNEXP; } uint32_t dataId; SysMonitor_GetRecvPayload(payload, &dataId, dataLen); // omit control info if (dataId == DATA_ID_NONE) { free(sysbusRsp); DBG_WARNING("SystemBus::no RX data!\n"); return SUCCESS; } if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) { free(sysbusRsp); DBG_WARNING("SystemBus::TX Queue overflowed!\n"); return EQUEUE; } instPtr->sysbusLog.pollCnt++; return SUCCESS; } /** * @brief Generate System Bus remote test command response */ static int32_t SystemBus_GenRemoteTestRsp(SYSBUS *instPtr, uint8_t *msg) { ASSERT(instPtr != NULL); ASSERT(msg != NULL); SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); if (sysbusRsp == NULL) { DBG_ERROR("Failed to allocate memory for LJ REMOTE TEST Response!\n"); return ENOMEM; } TIME_WORD tmWord; uint64_t time; TimeCtrl_GetCurrentTime(linkInstPtr->config.tmcInstPtr, &tmWord); time = (uint64_t)tmWord.int_part * TIME_FRAC_MAX + tmWord.frac_part; if (msg[WD_CMD] == CMD_FLJ_RM_TEST) { sysbusRsp->len = FLJ_RM_TEST_RESP_LEN; memset(sysbusRsp->data, 0x00, FLJ_RM_TEST_RESP_LEN); sysbusRsp->data[WD_CMD] = CMD_FLJ_RM_TEST; sysbusRsp->data[WD_PRD] = MY_PRD_ID; memcpy(sysbusRsp->data + WD_FLJ_TIME_STAMP, &time, WD_FLJ_TIME_STAMP_LEN); SysMonitor_GetLinklayerLog(&(instPtr->linkLog)); SysMonitor_GetPhysicalLayerLog(&(instPtr->phyLog)); SysMonitor_GetHardwareStatus(&(instPtr->hwState)); memcpy(sysbusRsp->data + WD_FLJ_SYSBUS_LOG, &(instPtr->sysbusLog), WD_FLJ_SYSBUS_LOG_LEN); memcpy(sysbusRsp->data + WD_FLJ_LINK_LOG, &(instPtr->linkLog), WD_FLJ_LINK_LOG_LEN); memcpy(sysbusRsp->data + WD_FLJ_PHY_LOG, &(instPtr->phyLog), WD_FLJ_PHY_LOG_LEN); memcpy(sysbusRsp->data + WD_FLJ_HARDWARE_ST, &(instPtr->hwState.spFpgaVolt), WD_FLJ_HARDWARE_ST_LEN); } else if (msg[WD_CMD] == CMD_LJ_RM_TEST) { sysbusRsp->len = LJ_RM_TEST_RESP_LEN; sysbusRsp->data[WD_CMD] = CMD_LJ_RM_TEST; sysbusRsp->data[WD_PRD] = MY_PRD_ID; memcpy(sysbusRsp->data + WD_LJ_TIME_STAMP, &time, WD_LJ_TIME_STAMP_LEN); SysMonitor_GetLinklayerLog(&(instPtr->linkLog)); SysMonitor_GetPhysicalLayerLog(&(instPtr->phyLog)); SysMonitor_GetHardwareStatus(&(instPtr->hwState)); memcpy(sysbusRsp->data + WD_LJ_SYSBUS_LOG, &(instPtr->sysbusLog), WD_LJ_SYSBUS_LOG_LEN); memcpy(sysbusRsp->data + WD_LJ_LINK_LOG, &(instPtr->linkLog), WD_LJ_LINK_LOG_LEN); memcpy(sysbusRsp->data + WD_LJ_PHY_LOG, &(instPtr->phyLog), WD_LJ_PHY_LOG_LEN); memcpy(sysbusRsp->data + WD_LJ_HARDWARE_ST, &(instPtr->hwState.spFpgaVolt), WD_LJ_HARDWARE_ST_LEN); } else { DBG_ERROR("Unexpected command 0x%02X.\n", msg[WD_CMD]); free(sysbusRsp); return EUNEXP; } if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) { free(sysbusRsp); DBG_WARNING("SystemBus::TX Queue overflowed!\n"); return EQUEUE; } instPtr->sysbusLog.remoteCnt++; return SUCCESS; } /*****************************************************************************/ /** * @brief A handler function. This handler evaluate the message from system * bus receive queue, and make appropriate response. * * @param instPtr A pointer to System Bus instance. * * @return None * ******************************************************************************/ int32_t SystemBus_HandleCmd(SYSBUS *instPtr) { ASSERT(instPtr != NULL); int32_t Status; SYSBUS_UART_FRAME *sysbusReq; uint8_t *msg; if (CircQueuePop(instPtr->rxQueue, (void **)(&sysbusReq)) == false) { DBG_WARNING("SystemBus::Nothing to be handled.\n"); return EIGNORE; } msg = sysbusReq->data; if (msg[WD_PRD] != MY_PRD_ID && msg[WD_PRD] != PRD_ALL) { DBG_WARNING("SystemBus::Production code mismatch!\n"); return EIGNORE; } switch (msg[WD_CMD]) { case CMD_SELF_TEST: { Status = SystemBus_GenSelfTestRsp(instPtr); break; } case CMD_DATA_TEST_A: case CMD_DATA_TEST_B: { Status = SystemBus_Echo(instPtr, sysbusReq); break; } case CMD_CONFIG: { Status = SystemBus_SystemConfig(instPtr, msg); break; } case CMD_SYS_INFO: { SysMonitor_UpdateSysinfo((SYSINFO *)(msg + SYS_INFO_OFFSET)); Status = SUCCESS; break; } case CMD_FLJ_SEND: { SysMonitor_UpdateSendPayload(msg + FLJ_DATA_OFFSET, PAYLOAD_LEN_FLJ_TX); // omit control info instPtr->sysbusLog.svcCnt++; Status = SUCCESS; break; } case CMD_LJ_SEND: { SysMonitor_UpdateSendPayload(msg + LJ_DATA_OFFSET, PAYLOAD_LEN_LJ_TX); // omit control info instPtr->sysbusLog.svcCnt++; Status = SUCCESS; break; } case CMD_FLJ_POLL: { if (msg[WD_FLJ_POLL] != FLJ_POLL_CODE) { DBG_ERROR("SystemBus::Invalid roll call code!\n"); Status = EIGNORE; break; } Status = SystemBus_GenPollRsp(instPtr, msg); break; } case CMD_LJ_POLL: { if (msg[WD_LJ_POLL] != LJ_POLL_CODE) { DBG_WARNING("SystemBus::Invalid roll call code!\n"); Status = EIGNORE; break; } Status = SystemBus_GenPollRsp(instPtr, msg); break; } case CMD_FLJ_RM_TEST: { if (msg[WD_FLJ_RM_TEST] != FLJ_RM_TEST_CODE) { DBG_WARNING("SystemBus::Invalid remote test code!\n"); Status = EIGNORE; break; } Status = SystemBus_GenRemoteTestRsp(instPtr, msg); break; } case CMD_LJ_RM_TEST: { if (msg[WD_LJ_RM_TEST] != LJ_RM_TEST_CODE) { DBG_WARNING("SystemBus::Invalid remote test code!\n"); Status = EIGNORE; break; } Status = SystemBus_GenRemoteTestRsp(instPtr, msg); break; } default: { DBG_ERROR("SystemBus::Unknown command code!\n"); Status = FAILURE; break; } } free(sysbusReq); return Status; } /*****************************************************************************/ /** * @brief This function send a repose frame from system bus tx queue. * * @param instPtr A pointer to System Bus instance. * * @return None * ******************************************************************************/ int32_t SystemBus_MakeResp(SYSBUS *instPtr) { ASSERT(instPtr != NULL); int32_t Status; SYSBUS_UART_FRAME *sysbusRsp; if (CircQueuePop(instPtr->txQueue, (void **)(&sysbusRsp)) == false) { DBG_WARNING("SystemBus::Nothing to be sent.\n"); return EIGNORE; } instPtr->isTxDone = false; // A transmission procedure is started. Status = SysbusUart_Send(instPtr->uartInst, sysbusRsp); free(sysbusRsp); return Status; } /** @} */ /*****************************************************************************/ /** * @brief Initialize System Bus instance. * * @param InstPtr A double pointer to System Bus instance. * @param config A pointer to System Bus configurations. * * @return None. * ******************************************************************************/ int32_t SystemBus_Init(SYSBUS **instPtr, SYSBUS_CONFIG *config) { ASSERT(instPtr != NULL); ASSERT(config != NULL); SYSBUS_UART_CONFIG uartConfig; int32_t Status; (*instPtr) = malloc(sizeof(SYSBUS)); if ((*instPtr) == NULL) { return FAILURE; } (*instPtr)->rxQueue = NULL; (*instPtr)->txQueue = NULL; (*instPtr)->uartInst = NULL; memcpy(&((*instPtr)->config), config, sizeof(SYSBUS_CONFIG)); memset(&((*instPtr)->sysbusLog), 0x00, sizeof(SYSBUSLOG)); memset(&((*instPtr)->linkLog), 0x00, sizeof(LINKLOG)); memset(&((*instPtr)->phyLog), 0x00, sizeof(PHYLOG)); memset(&((*instPtr)->hwState), 0x00, sizeof(HWSTATE)); uartConfig.baseAddr = config->baseAddr; Status = SysbusUart_Init(&((*instPtr)->uartInst), &uartConfig); if (Status != SUCCESS) { Status = ENOMEM; goto sysbus_init_error; } if (CircQueueCreate(&((*instPtr)->txQueue), (*instPtr)->config.txQueueMax) == false) { Status = ENOMEM; goto sysbus_init_error; } if (CircQueueCreate(&((*instPtr)->rxQueue), (*instPtr)->config.rxQueueMax) == false) { Status = ENOMEM; goto sysbus_init_error; } (*instPtr)->isRxDone = false; // nothing received. (*instPtr)->isTxDone = true; // nothing to be sent. return SUCCESS; sysbus_init_error: free((*instPtr)->uartInst); free((*instPtr)->txQueue); free((*instPtr)->rxQueue); free(*instPtr); return Status; } /*****************************************************************************/ /** * @brief This function handles the systembus tx irq events. * * @param instPtr A pointer to System Bus instance. * * @return None * ******************************************************************************/ int32_t SystemBus_TxIntrHandler(SYSBUS *instPtr) { ASSERT(instPtr != NULL); // nothing special... instPtr->isTxDone = true; // A transmission procedure finished. return SUCCESS; } /*****************************************************************************/ /** * @brief This function handles the systembus rx irq events. * * @param instPtr A pointer to System Bus instance. * * @return None * ******************************************************************************/ int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr) { ASSERT(instPtr != NULL); instPtr->isRxDone = true; // whether reception successes or not, receiving procedure ended. int32_t Status; SYSBUS_UART_FRAME *sysbusReq = malloc(sizeof(SYSBUS_UART_FRAME)); if (sysbusReq == NULL) { return ENOMEM; } Status = SysbusUart_Recv(instPtr->uartInst, sysbusReq); if (Status != SUCCESS) { goto recv_error; } if (CircQueuePush(instPtr->rxQueue, (void *)sysbusReq) == false) { DBG_ERROR("SystemBus::RX Queue overflowed!\n"); Status = EQUEUE; goto recv_error; } instPtr->isRxDone = false; // another reception is undergoing. return SUCCESS; recv_error: free(sysbusReq); return Status; } /** @} SystemBus*/