diff options
Diffstat (limited to 'src/master.c')
| -rw-r--r-- | src/master.c | 272 |
1 files changed, 184 insertions, 88 deletions
diff --git a/src/master.c b/src/master.c index 09b6b66..4cad251 100644 --- a/src/master.c +++ b/src/master.c @@ -48,12 +48,16 @@ uint32_t allocated[4]={0}; uint8_t dev_sts[BUS_DEVICE_LIMIT] = {OFFLINE}; uint8_t data_idx; -_datapoint routing_buffer[ROUTING_BUFSIZE]; -/* Index information for each datapoint */ -uint8_t routing_idx_buffer[ROUTING_BUFSIZE]; -/* Pointer to tail of both data and idx buffers */ -uint32_t routing_ptr = 0; +_datapoint routing_buffer[ROUTING_BUFSIZE]; /*< Buffer to store data to be routed */ +uint8_t *cmd_routing_buf[ROUTING_BUFSIZE]; /*< Buffer to store commands to be routed */ +uint8_t routing_idx_buffer[ROUTING_BUFSIZE]; /*< Index information for data source */ +uint8_t cmd_src_idx_rbuf[ROUTING_BUFSIZE]; /*< Index information for command source */ +uint8_t cmd_dst_idx_rbuf[ROUTING_BUFSIZE]; /*< Index information for command dest */ + +uint32_t routing_ptr = 0; /*< Pointer to tail of both data and data index buffers */ +uint32_t cmd_routing_ptr = 0; /*< Pointer to tail of cmd and cmd index buffers */ + /* Function prototypes */ void SystemClock_Config(void); static void MX_GPIO_Init(void); @@ -63,6 +67,8 @@ static void MX_USART1_UART_Init(void); hs_status_t handshake(uint32_t i2c_addr); dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t routing_buf_idx); bool routing(void); +bool cmd_routing(void); +uint8_t get_CTS(uint8_t i2c_addr); bool todo_hs_or_not_todo_hs(uint8_t i2c_addr); state_t get_state_from_hs_status(uint16_t device_addr, hs_status_t hs_status); bool decode_subscriptions_callback(pb_istream_t *istream, const pb_field_t *field, void **args); @@ -100,16 +106,15 @@ int main(void) #endif /* MASTER */ #endif /* TESTING_ENABLE */ - uint8_t priority_counter = 0, debug_buf[128]; + uint8_t priority_counter = 0, debug_buf[128] = {0}; /* Handshake */ while (1) { if (priority_counter == 0) { hs_status_t hs_status; - /* for (uint8_t curr_addr=5; curr_addr == 5; curr_addr++) { */ - for (uint8_t curr_addr=0x1; curr_addr <= BUS_DEVICE_LIMIT; curr_addr++) { - if (todo_hs_or_not_todo_hs(curr_addr)) { - hs_status = handshake(curr_addr); - dev_sts[GET_IDX_FROM_ADDR(curr_addr)] = get_state_from_hs_status(curr_addr, hs_status); + for (int dev_idx = 0; dev_idx < BUS_DEVICE_LIMIT-1; dev_idx++) { + if (todo_hs_or_not_todo_hs(GET_ADDR_FROM_IDX(dev_idx))) { + hs_status = handshake(GET_ADDR_FROM_IDX(dev_idx)); + dev_sts[dev_idx] = get_state_from_hs_status(GET_ADDR_FROM_IDX(dev_idx), hs_status); } } } @@ -124,12 +129,9 @@ int main(void) } } routing(); + cmd_routing(); } priority_counter = ((priority_counter+1)%10); - - sprintf((char*)debug_buf, "Routing pointer: %ld\r\n", routing_ptr); - HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); - memset(debug_buf, 0, 128); } } @@ -147,7 +149,7 @@ hs_status_t handshake(uint32_t i2c_addr) s2m_MDR_response MDR_res_message = s2m_MDR_response_init_default; #if defined(TESTING_ENABLE) || defined(DEBUG_ENABLE) - uint8_t debug_buf[128]; + uint8_t debug_buf[128] = {0}; #endif #ifdef TESTING_ENABLE uint8_t term[] = "\r\n"; @@ -305,7 +307,7 @@ __TESTING_BLOCK_END: { goto __DEBUG_BLOCK_END; __HS_MDR_REQ_I2C_ERROR: - sprintf((char*)debug_buf, "Unable to send MDR request to %lx. I2C error: %ld\r\n", i2c_addr, HAL_I2C_GetError(&hi2c1)); + sprintf((char*)debug_buf, "Unable to send MDR request to %lx. I2C error: %ld\r\n", i2c_addr>>1, HAL_I2C_GetError(&hi2c1)); HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); memset(debug_buf, 0, 128); goto __HS_MDR_REQ_I2C_ERROR_END; @@ -337,13 +339,16 @@ __TESTING_BLOCK_END: return hs_sts; } -dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t rbuf_data_idx) +dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t rbuf_idx) { uint8_t dev_idx = GET_IDX_FROM_ADDR(i2c_addr); dataflow_status_t df_status = DF_IDLE; - + uint8_t CTS_buf[2] = {0x2, 0xFF}; + uint8_t DOC_buf[4]; uint8_t *data_buf; + uint8_t cmd_dest; + uint32_t AF_error_counter = 0; uint32_t data_len = 0; _datapoint datapoints[16]; @@ -351,10 +356,7 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r /* TODO Add default values to the CTS message in proto */ s2m_data data_message = s2m_data_init_zero; #if defined(TESTING_ENABLE) || defined(DEBUG_ENABLE) - uint8_t debug_buf[128]; -#endif -#ifdef TESTING_ENABLE - uint8_t term[] = "\r\n"; + uint8_t debug_buf[128]={0}; #endif while (df_status != DF_SUCCESS && df_status != DF_FAIL) { @@ -376,11 +378,10 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r df_status = DF_RX_DOC; } else if (SOR_code == SLAVE_RX_DATAPOINT) { - /* TODO */ - df_status = DF_LEN_TX; + df_status = DF_TX_DATA; } else if (SOR_code == SLAVE_RX_COMMAND) { - /* TODO */ + df_status = DF_TX_CMD; } } break; @@ -392,7 +393,7 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r HAL_Delay(MASTER_I2C_BUS_INTERVAL); AF_error_counter = 0; while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)i2c_addr, - (uint8_t*)DOC_buf, 4, 10000) != HAL_OK) { + (uint8_t*)DOC_buf, 4, 0xffff) != HAL_OK) { if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { df_status = DF_FAIL; #ifdef DEBUG_ENABLE @@ -413,7 +414,9 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r data_len = DOC_buf[3]; } else if (DOC_buf[1] == CMD_UNICAST) { - /* TODO */ + df_status = DF_CTS; + cmd_dest = DOC_buf[0]; + data_len = DOC_buf[3]; } else if (DOC_buf[1] == CMD_MULTICAST) { /* TODO */ @@ -430,7 +433,6 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r case (DF_CTS): { HAL_Delay(MASTER_I2C_BUS_INTERVAL); - uint8_t CTS_buf[2] = {0x2, 0xFF}; if (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, CTS_buf, 2, 10000) != HAL_OK) { df_status = DF_FAIL; #ifdef DEBUG_ENABLE @@ -444,7 +446,9 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r df_status = DF_RX_DATA; } else { - /* TODO RX CMD stuff */ + if (DOC_buf[1] == CMD_UNICAST) { + df_status = DF_RX_CMD; + } } } break; @@ -498,61 +502,75 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r } break; } - case (DF_LEN_TX): + case (DF_TX_DATA): { HAL_Delay(MASTER_I2C_BUS_INTERVAL); /* TODO error checking */ /* Will need to package datapoint and MDR to know their lengths Once cached, will not need to do this */ - /* Do this after handshake to cache ================================================== */ + /* Do this after handshake to cache ==================================== */ uint8_t MDR_buf[128], data_buf[128], CTS_buf[2]; - uint8_t src_device_idx = routing_idx_buffer[rbuf_data_idx]; + uint8_t src_device_idx = routing_idx_buffer[rbuf_idx]; s2m_MDR_response data_src_MDR = device_info[src_device_idx]->MDR; pb_ostream_t MDR_ostream = pb_ostream_from_buffer(MDR_buf, sizeof(MDR_buf)); data_src_MDR.subscriptions.funcs.encode=master_encode_MDR_callback; pb_encode(&MDR_ostream, s2m_MDR_response_fields, &data_src_MDR); uint8_t MDR_len = MDR_ostream.bytes_written; - /* =================================================================================== */ + /* ==================================================================== */ - _datapoint data = routing_buffer[rbuf_data_idx]; + _datapoint data = routing_buffer[rbuf_idx]; pb_ostream_t data_ostream = pb_ostream_from_buffer(data_buf, sizeof(data_buf)); pb_encode(&data_ostream, _datapoint_fields, &data); uint8_t data_len = data_ostream.bytes_written; uint8_t data_MDR_len_buf[4] = {0, MDR_len, 0, data_len}; - AF_error_counter = 0; - while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)i2c_addr, CTS_buf, 2, 10000) != HAL_OK) { - if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { - df_status = DF_FAIL; - } - if (++AF_error_counter > 3000) { - df_status = DF_FAIL; - } - if (df_status == DF_FAIL) { - sprintf((char*)debug_buf, "Failed to get LEN CTS\r\n"); - HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); - memset(debug_buf, 0, 128); - break; - } - } - + uint8_t status = get_CTS(i2c_addr); HAL_Delay(MASTER_I2C_BUS_INTERVAL); - if (df_status != DF_FAIL && - HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, data_MDR_len_buf, 4, 10000) == HAL_OK) { + if (status != 0 && + HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, + data_MDR_len_buf, 4, 10000) == HAL_OK) { +#ifdef DEBUG_ENABLE sprintf((char*)debug_buf, "MDR len: %d data len: %d SENT\r\n", MDR_len, data_len); HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); memset(debug_buf, 0, 128); +#endif } else { +#ifdef DEBUG_ENABLE sprintf((char*)debug_buf, "Failed to send lengths\r\n"); HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); memset(debug_buf, 0, 128); +#endif + } + + status = get_CTS(i2c_addr); + if (status != 0 && + HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, MDR_buf, + MDR_len, 10000) == HAL_OK && + HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, data_buf, + data_len, 10000) == HAL_OK) { +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Data and MDR sent\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + df_status = DF_SUCCESS; } + else { + df_status = DF_FAIL; + } + break; + } + case (DF_RX_CMD): + { + uint8_t *cmd_buf; + HAL_Delay(MASTER_I2C_BUS_INTERVAL); + cmd_buf = (uint8_t*)malloc(data_len); AF_error_counter = 0; - while (df_status != DF_FAIL && - HAL_I2C_Master_Receive(&hi2c1, (uint16_t)i2c_addr, CTS_buf, 2, 10000) != HAL_OK) { + while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)i2c_addr, cmd_buf, + data_len, 10000) != HAL_OK) { if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { df_status = DF_FAIL; } @@ -560,49 +578,78 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r df_status = DF_FAIL; } if (df_status == DF_FAIL) { - sprintf((char*)debug_buf, "Failed to get TX CTS\r\n"); + free(cmd_buf); +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Failed to get command, expected len: %ld\r\n", data_len); HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); memset(debug_buf, 0, 128); +#endif break; } } + if (df_status != DF_FAIL) { + cmd_routing_buf[cmd_routing_ptr] = malloc(sizeof(uint8_t)*data_len); + memcpy(cmd_routing_buf[cmd_routing_ptr], cmd_buf, data_len); + free(cmd_buf); + + cmd_src_idx_rbuf[cmd_routing_ptr] = dev_idx; + cmd_dst_idx_rbuf[cmd_routing_ptr] = cmd_dest; + cmd_routing_ptr++; - -#ifdef TESTING_ENABLE - uint8_t buf_title[64]; - sprintf((char*)buf_title, "MDR buffer: "); - HAL_UART_Transmit(&huart1, buf_title, sizeof(buf_title), 100); - memset(buf_title, 0, 64); - for(int x=0; x<MDR_len; x++) - sprintf((char*)debug_buf+x, "%x", MDR_buf[x]); - HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); - HAL_UART_Transmit(&huart1, term, 2, 100); - memset(debug_buf, 0, 128); - - sprintf((char*)buf_title, "Data buffer: "); - HAL_UART_Transmit(&huart1, buf_title, sizeof(buf_title), 100); - memset(buf_title, 0, 64); - for(int x=0; x<data_len; x++) - sprintf((char*)debug_buf+x, "%x", data_buf[x]); - HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); - HAL_UART_Transmit(&huart1, term, 2, 100); - memset(debug_buf, 0, 128); +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Got command\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); #endif + df_status = DF_SUCCESS; + } + break; + } + case (DF_TX_CMD): + { + HAL_Delay(MASTER_I2C_BUS_INTERVAL); + uint8_t data_len = sizeof(cmd_routing_buf[rbuf_idx]); + uint8_t len_buf[] = {0x0, data_len, 0x0, 0x0}; - if (df_status != DF_FAIL && - HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, MDR_buf, MDR_len, 10000) == HAL_OK && - HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, data_buf, data_len, 10000) == HAL_OK) { - sprintf((char*)debug_buf, "Data and MDR SENT\r\n"); + uint8_t status = get_CTS(i2c_addr); + if (status != 0 && + HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, len_buf, + 4, 10000) != HAL_OK) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Failed to send cmd len buf to %ld\r\n", i2c_addr>>1); HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); memset(debug_buf, 0, 128); - - df_status = DF_SUCCESS; +#endif + } + + if (df_status != DF_FAIL) { + uint8_t status = get_CTS(i2c_addr); + if (status != 0 && + HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, + cmd_routing_buf[rbuf_idx], + 4, 10000) == HAL_OK) { + df_status = DF_SUCCESS; +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Routed cmd to %ld\r\n", i2c_addr>>1); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + } + else { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Failed to send cmd to %ld\r\n", i2c_addr>>1); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + } } break; } case DF_SUCCESS: case DF_FAIL: - break; + break; } } @@ -619,7 +666,7 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r goto __DF_DEBUG_BLOCK_END; __DF_SOR_I2C_ERROR: sprintf((char*)debug_buf, "Unable to send SOR request to %d. I2C error: %ld\r\n", - i2c_addr, HAL_I2C_GetError(&hi2c1)); + i2c_addr>>1, HAL_I2C_GetError(&hi2c1)); HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); memset(debug_buf, 0, 128); goto __DF_SOR_I2C_ERROR_END; @@ -651,6 +698,32 @@ dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t r return df_status; } +uint8_t get_CTS(uint8_t i2c_addr) +{ + uint8_t CTS_buf[2], AF_error_counter = 0, debug_buf[20] = {0}; + uint8_t status = 1; + while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)i2c_addr, CTS_buf, 2, 10000) != HAL_OK) { + if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { + status = 0; + } + if (++AF_error_counter > 1000) { + status = 0; + } + if (status == 0) { +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Failed to get CTS\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); +#endif + break; + } + } + return status; +} + +/** + * @brief Dataflow routing + * + */ bool routing(void) { /* This table holds information on where to send each datapoint in the routing buffer */ @@ -660,12 +733,14 @@ bool routing(void) for (uint8_t rbuf_data_idx = 0; rbuf_data_idx < routing_ptr; rbuf_data_idx++) { uint8_t src_module_idx = routing_idx_buffer[rbuf_data_idx]; for (uint8_t dev_idx = 0; dev_idx < BUS_DEVICE_LIMIT; dev_idx++) { - if (!(GET_BIT_FROM_IDX(allocated, dev_idx)&&1)) { // No module at this index + if (!(GET_BIT_FROM_IDX(allocated, dev_idx) && 1)) { // No module at this index continue; } bool alloc = false; - for (uint8_t dev_sub_idx = 0; dev_sub_idx < subs_info[dev_idx]->mod_idx && !alloc; dev_sub_idx++) { - if (subs_info[dev_idx]->module_ids[dev_sub_idx] == device_info[src_module_idx]->MDR.module_id) { + for (uint8_t dev_sub_idx = 0; + dev_sub_idx < subs_info[dev_idx]->mod_idx && !alloc; dev_sub_idx++) { + if (subs_info[dev_idx]->module_ids[dev_sub_idx] == + device_info[src_module_idx]->MDR.module_id) { SET_BIT_FROM_IDX(routing_table[rbuf_data_idx], dev_idx); alloc = true; } @@ -688,6 +763,27 @@ bool routing(void) return true; } +/** + * @brief Routing specific to commands. Currently only supports Unicast commands, multicast and + * broadcast support to be added in a later version if deemed necessary. + * + */ +bool cmd_routing(void) +{ + /* uint32_t routing_table[4]; */ + for (uint8_t rbuf_cmd_idx = 0; rbuf_cmd_idx < cmd_routing_ptr; rbuf_cmd_idx++) { + uint8_t dst_module_idx = cmd_dst_idx_rbuf[rbuf_cmd_idx]; + for (int dev_idx = 0; dev_idx < BUS_DEVICE_LIMIT; dev_idx++) { + if (GET_BIT_FROM_IDX(allocated, dev_idx) && + device_info[dev_idx]->MDR.module_id == dst_module_idx) { + device_dataflow(GET_ADDR_FROM_IDX(dev_idx), SLAVE_RX_COMMAND, rbuf_cmd_idx); + } + } + } + cmd_routing_ptr = 0; + return true; +} + bool decode_subscriptions_callback(pb_istream_t *istream, const pb_field_t *field, void **args) { _subscriptions subs; @@ -889,7 +985,7 @@ void SystemClock_Config(void) static void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; - hi2c1.Init.ClockSpeed = 400000; + hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; |
