diff --git a/cube/User/Inc/mbusComm.h b/cube/User/Inc/mbusComm.h index 59c1118..72dec52 100644 --- a/cube/User/Inc/mbusComm.h +++ b/cube/User/Inc/mbusComm.h @@ -4,6 +4,38 @@ #include #include + +typedef struct { + uint8_t start1; + uint8_t length1; + uint8_t length2; + uint8_t start2; + uint8_t l; + uint8_t c; + uint8_t a; + uint8_t ci; + uint8_t *userdata; + uint8_t chksum; + uint8_t stop; +} t_longframe; + +typedef enum { + MBCR_SUCCESS = 0, + MBCR_ERROR_TIMEOUT, + MBCR_ERROR_LOOP_FAILURE, + MBCR_ERROR_TX_REG_UNACCESSIBLE, + MBCR_ERROR_OUT_OF_MEMORY__FRAME, + MBCR_ERROR_OUT_OF_MEMORY__USERDATA, + MBCR_ERROR_STATE_ENGINE__START1, + MBCR_ERROR_STATE_ENGINE__LENGTH1, + MBCR_ERROR_STATE_ENGINE__LENGTH2, + MBCR_ERROR_STATE_ENGINE__START2, + MBCR_ERROR_STATE_ENGINE__INVALID_CHKSUM, + MBCR_ERROR_STATE_ENGINE__STOP, + MBCR_ERROR_STATE_ENGINE__ILLEGAL_STATE, + MBCR_ERROR_STATE_ENGINE__UNKNOWN +} t_mbusCommResult; + void mbusCommRequest(uint8_t cmd, uint8_t addr); void mbusCommTxCpltCallback(UART_HandleTypeDef *huart); void mbusCommRxCpltCallback(UART_HandleTypeDef *huart); diff --git a/cube/User/Src/mbusComm.c b/cube/User/Src/mbusComm.c index 5903dfd..35e8f63 100644 --- a/cube/User/Src/mbusComm.c +++ b/cube/User/Src/mbusComm.c @@ -14,13 +14,24 @@ typedef enum { - IDLE, - SEND, - SEND_CONT, - SENDING_DONE, - ENABLE_FRONTEND, - RECEIVING, - DISABLE_FRONTEND + MBCS_IDLE, + MBCS_SEND, + MBCS_SEND_CONT, + MBCS_SENDING_DONE, + MBCS_ENABLE_FRONTEND, + MBCS_START1, + MBCS_LENGTH1, + MBCS_LENGTH2, + MBCS_START2, + MBCS_C_FIELD, + MBCS_A_FIELD, + MBCS_CI_FIELD, + MBCS_USERDATA, + MBCS_CHKSUM, + MBCS_STOP, + MBCS_DONE, + MBCS_DISABLE_FRONTEND, + MBCS_ERROR } e_mbusCommState; typedef struct { @@ -32,16 +43,18 @@ typedef struct { uint8_t receiveCnt; uint8_t receivedOctet; bool receiving; + t_mbusCommResult result; + t_longframe frame; } t_mbusCommHandle; -static t_mbusCommHandle mbusCommHandle = { .state = IDLE, .retryCnt = 0, .cmd = 0, .addr = 0, .receiveCnt = 0, .receivedOctet = 0, .receiving = false }; +static t_mbusCommHandle mbusCommHandle = { .state = MBCS_IDLE, .retryCnt = 0, .cmd = 0, .addr = 0, .receiveCnt = 0, .receivedOctet = 0, .receiving = false }; static void handleRequestEngine(void *handle); static void timeoutHandler(void *handle) { logMsg("mbc timeout"); t_mbusCommHandle *localMbusCommHandle = (t_mbusCommHandle*) handle; - localMbusCommHandle->state = DISABLE_FRONTEND; + localMbusCommHandle->state = MBCS_DISABLE_FRONTEND; localMbusCommHandle->receiving = false; handleRequestEngine(handle); } @@ -54,22 +67,25 @@ static void receiveNext(t_mbusCommHandle *localMbusCommHandle) { static void handleRequestEngine(void *handle) { t_mbusCommHandle *localMbusCommHandle = (t_mbusCommHandle*) handle; + static uint8_t userdataIdx = 0; + static uint8_t calculatedChksum = 0; + switch (localMbusCommHandle->state) { - case IDLE: + case MBCS_IDLE: logMsg("hre state IDLE"); break; - case SEND: + case MBCS_SEND: logMsg("hre state SEND"); localMbusCommHandle->sendBuf[0] = 0x10; localMbusCommHandle->sendBuf[1] = localMbusCommHandle->cmd; localMbusCommHandle->sendBuf[2] = localMbusCommHandle->addr; localMbusCommHandle->sendBuf[3] = localMbusCommHandle->cmd + localMbusCommHandle->addr; // checksum localMbusCommHandle->sendBuf[4] = 0x16; - localMbusCommHandle->state = SEND_CONT; + localMbusCommHandle->state = MBCS_SEND_CONT; // no break !! - case SEND_CONT: + case MBCS_SEND_CONT: logMsg("hre state SEND_CONT"); signal(LED_RED, OFF); if (! loopActive) { @@ -82,59 +98,177 @@ static void handleRequestEngine(void *handle) { HAL_UART_Transmit_IT(&mbusUart, localMbusCommHandle->sendBuf, 5); // transition from here to SENDING_DONE is initiate by mbusCommTxCpltCallback // interrupt callback - localMbusCommHandle->state = SENDING_DONE; + localMbusCommHandle->state = MBCS_SENDING_DONE; } break; - case SENDING_DONE: + case MBCS_SENDING_DONE: logMsg("hre state SENDING_DONE"); - localMbusCommHandle->state = ENABLE_FRONTEND; + localMbusCommHandle->state = MBCS_ENABLE_FRONTEND; schAdd(handleRequestEngine, handle, 3, 0); break; - case ENABLE_FRONTEND: + case MBCS_ENABLE_FRONTEND: logMsg("hre state ENABLE_FRONTEND"); frontendEnable(); schAdd(timeoutHandler, handle, 2500, 0); - localMbusCommHandle->state = RECEIVING; - localMbusCommHandle->receiveCnt = 0; + calculatedChksum = 0; + userdataIdx = 0; + localMbusCommHandle->state = MBCS_START1; receiveNext(localMbusCommHandle); break; - case RECEIVING: - // logMsg("hre state RECEIVING"); - logMsg("hre received octet: 0x%02x: 0x%02x", localMbusCommHandle->receiveCnt, localMbusCommHandle->receivedOctet); - localMbusCommHandle->receiveCnt += 1; + case MBCS_START1: + logMsg("hre state START1"); + if (localMbusCommHandle->receivedOctet == 0x68) { + localMbusCommHandle->frame.start1 = localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_LENGTH1; + } else { + logMsg("hre err: invalid start1 symbol %02x", localMbusCommHandle->receivedOctet); + localMbusCommHandle->result = MBCR_ERROR_STATE_ENGINE__START1; + localMbusCommHandle->state = MBCS_ERROR; + } receiveNext(localMbusCommHandle); break; - case DISABLE_FRONTEND: + case MBCS_LENGTH1: + logMsg("hre state LENGTH1"); + if (localMbusCommHandle->receivedOctet <= 3) { + logMsg("hre err: length to small %02x", localMbusCommHandle->receivedOctet); + localMbusCommHandle->result = MBCR_ERROR_STATE_ENGINE__LENGTH1; + localMbusCommHandle->state = MBCS_ERROR; + } else { + localMbusCommHandle->frame.length1 = localMbusCommHandle->receivedOctet; + localMbusCommHandle->frame.userdata = (uint8_t*) malloc(localMbusCommHandle->frame.length1 - 3); + if (! localMbusCommHandle->frame.userdata) { + logMsg("hre err: unable to allocate memory for userdata"); + localMbusCommHandle->result = MBCR_ERROR_OUT_OF_MEMORY__USERDATA; + localMbusCommHandle->state = MBCS_ERROR; + } else { + localMbusCommHandle->state = MBCS_LENGTH2; + } + } + receiveNext(localMbusCommHandle); + break; + + case MBCS_LENGTH2: + logMsg("hre state LENGTH2"); + if (localMbusCommHandle->frame.length1 != localMbusCommHandle->receivedOctet) { + logMsg("hre err: invalid length2 %02x vs. %02x", localMbusCommHandle->frame.length1, localMbusCommHandle->receivedOctet); + localMbusCommHandle->result = MBCR_ERROR_STATE_ENGINE__LENGTH2; + localMbusCommHandle->state = MBCS_ERROR; + } else { + localMbusCommHandle->frame.length2 = localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_START2; + } + receiveNext(localMbusCommHandle); + break; + + case MBCS_START2: + logMsg("hre state START2"); + if (localMbusCommHandle->receivedOctet == 0x68) { + localMbusCommHandle->frame.start2 = localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_C_FIELD; + } else { + logMsg("hre err: invalid start2 symbol %02x", localMbusCommHandle->receivedOctet); + localMbusCommHandle->result = MBCR_ERROR_STATE_ENGINE__START2; + localMbusCommHandle->state = MBCS_ERROR; + } + receiveNext(localMbusCommHandle); + break; + + case MBCS_C_FIELD: + logMsg("hre state C_FIELD"); + localMbusCommHandle->frame.c = localMbusCommHandle->receivedOctet; + calculatedChksum += localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_A_FIELD; + receiveNext(localMbusCommHandle); + break; + + case MBCS_A_FIELD: + logMsg("hre state A_FIELD"); + localMbusCommHandle->frame.a = localMbusCommHandle->receivedOctet; + calculatedChksum += localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_CI_FIELD; + receiveNext(localMbusCommHandle); + break; + + case MBCS_CI_FIELD: + logMsg("hre state CI_FIELD"); + localMbusCommHandle->frame.ci = localMbusCommHandle->receivedOctet; + calculatedChksum += localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_USERDATA; + receiveNext(localMbusCommHandle); + break; + + case MBCS_USERDATA: + logMsg("hre state USERDATA"); + localMbusCommHandle->frame.userdata[userdataIdx] = localMbusCommHandle->receivedOctet; + calculatedChksum += localMbusCommHandle->receivedOctet; + userdataIdx++; + if (userdataIdx == (localMbusCommHandle->frame.length1 - 3)) { + localMbusCommHandle->state = MBCS_CHKSUM; + } + receiveNext(localMbusCommHandle); + break; + + case MBCS_CHKSUM: + logMsg("hre state CHKSUM"); + if (localMbusCommHandle->receivedOctet != calculatedChksum) { + logMsg("hre err: invalid checksum %02x vs %02x", calculatedChksum, localMbusCommHandle->receivedOctet); + localMbusCommHandle->result = MBCR_ERROR_STATE_ENGINE__INVALID_CHKSUM; + localMbusCommHandle->state = MBCS_ERROR; + } else { + localMbusCommHandle->frame.chksum = localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_STOP; + } + receiveNext(localMbusCommHandle); + break; + + case MBCS_STOP: + logMsg("hre state STOP"); + if (localMbusCommHandle->receivedOctet == 0x16) { + localMbusCommHandle->frame.stop = localMbusCommHandle->receivedOctet; + localMbusCommHandle->state = MBCS_DONE; + schAdd(handleRequestEngine, handle, 0, 0); + } else { + logMsg("hre err: invalid stop symbol %02x", localMbusCommHandle->receivedOctet); + localMbusCommHandle->result = MBCR_ERROR_STATE_ENGINE__STOP; + localMbusCommHandle->state = MBCS_ERROR; + receiveNext(localMbusCommHandle); + } + break; + + case MBCS_DONE: + logMsg("hre state DONE"); + localMbusCommHandle->result = MBCR_SUCCESS; + localMbusCommHandle->state = MBCS_DISABLE_FRONTEND; + schAdd(handleRequestEngine, handle, 0, 0); + break; + + case MBCS_ERROR: + logMsg("hre state ERROR"); + signal(LED_RED, ON); + logMsg("hre err: already error, read the rest (now: %02x) until timeout", localMbusCommHandle->receivedOctet); + receiveNext(localMbusCommHandle); + break; + + + case MBCS_DISABLE_FRONTEND: logMsg("hre state DISABLE_FRONTEND"); - localMbusCommHandle->receiving = false; + localMbusCommHandle->receiving = false; HAL_UART_AbortReceive(&mbusUart); uint8_t kitchenSink[16]; memset(kitchenSink, 0, 16); HAL_StatusTypeDef r = HAL_UART_Receive(&mbusUart, kitchenSink, 16, 1000); - if (r == HAL_OK) { - logMsg("hre abort, still got some"); - // logMsg("hre abort, still got some: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - // kitchenSink[0], kitchenSink[1], kitchenSink[2], kitchenSink[3], - // kitchenSink[4], kitchenSink[5], kitchenSink[6], kitchenSink[7], - // kitchenSink[8], kitchenSink[9], kitchenSink[10], kitchenSink[11], - // kitchenSink[12], kitchenSink[13], kitchenSink[14], kitchenSink[15]); - } else if (r == HAL_TIMEOUT) { - logMsg("hre abort, run into timeout"); - } else { - logMsg("hre abort, some other result: %02x", r); - } - + logMsg("hre abort, last receive result: %02x", r); frontendDisable(); - localMbusCommHandle->state = IDLE; + localMbusCommHandle->state = MBCS_IDLE; break; default: - localMbusCommHandle->state = IDLE; + localMbusCommHandle->state = MBCS_IDLE; break; } } @@ -153,8 +287,8 @@ void mbusCommRxCpltCallback(UART_HandleTypeDef *huart) { } void mbusCommRequest(uint8_t cmd, uint8_t addr) { - if (mbusCommHandle.state == IDLE) { - mbusCommHandle.state = SEND; + if (mbusCommHandle.state == MBCS_IDLE) { + mbusCommHandle.state = MBCS_SEND; mbusCommHandle.retryCnt = 0; mbusCommHandle.cmd = cmd; mbusCommHandle.addr = addr;