From 2dbfe61eb8b0fb82d90393b664692b85e09d1436 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Thu, 17 Oct 2019 10:10:49 +0200 Subject: [PATCH 01/26] log: force stdout flush for log_print_data --- stack/framework/components/log/log.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stack/framework/components/log/log.c b/stack/framework/components/log/log.c index 615e154a5..182f3d616 100644 --- a/stack/framework/components/log/log.c +++ b/stack/framework/components/log/log.c @@ -69,9 +69,7 @@ __LINK_C void log_print_data(uint8_t* message, uint32_t length) for( uint32_t i=0 ; i Date: Mon, 23 Dec 2019 10:45:24 +0100 Subject: [PATCH 02/26] d7a: fix packet length when CRC is supported by hardware --- stack/modules/d7ap/packet.c | 8 +++++--- stack/modules/d7ap/phy.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/stack/modules/d7ap/packet.c b/stack/modules/d7ap/packet.c index f208d282a..6bbafa03f 100644 --- a/stack/modules/d7ap/packet.c +++ b/stack/modules/d7ap/packet.c @@ -75,14 +75,16 @@ void packet_assemble(packet_t* packet) data_ptr += d7anp_secure_payload(packet, nwl_payload, data_ptr - nwl_payload); #endif - packet->hw_radio_packet.length = data_ptr - packet->hw_radio_packet.data + 2; // exclude the CRC bytes + packet->hw_radio_packet.length = data_ptr - packet->hw_radio_packet.data + 2; // include the CRC bytes packet->hw_radio_packet.data[0] = packet->hw_radio_packet.length - 1; // exclude the length byte + if (has_hardware_crc) + packet->hw_radio_packet.length -= 2; // exclude the CRC bytes + // TODO network protocol footer // add CRC - SW CRC when using FEC - if (!has_hardware_crc || - packet->phy_config.tx.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9) + if (!has_hardware_crc) { uint16_t crc = __builtin_bswap16(crc_calculate(packet->hw_radio_packet.data, packet->hw_radio_packet.length - 2)); memcpy(data_ptr, &crc, 2); diff --git a/stack/modules/d7ap/phy.c b/stack/modules/d7ap/phy.c index ab7d5bcd0..64578f3d8 100644 --- a/stack/modules/d7ap/phy.c +++ b/stack/modules/d7ap/phy.c @@ -765,6 +765,7 @@ error_t phy_send_packet(hw_radio_packet_t* packet, phy_tx_config_t* config, phy_ DPRINT("start sending @ %i\n", timer_get_counter_value()); + hw_radio_set_payload_length(fg_frame.encoded_length + 2); hw_radio_send_payload(fg_frame.encoded_packet, fg_frame.encoded_length); return SUCCESS; // TODO other return codes From 68f2e45be3b9edaa4ed9ad2da3ede7ac6d14fb21 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 7 Feb 2020 15:02:20 +0100 Subject: [PATCH 03/26] fix Cortus build due to missing symbol regarding the d7ap_fs buffers The Attribute used is not sufficient to force the compiler to emit symbol for the d7ap_fs buffers. We need to modify the libraries build ordering --- stack/apps/gateway/CMakeLists.txt | 2 +- stack/apps/modem/CMakeLists.txt | 2 +- stack/apps/sensor_without_alp/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stack/apps/gateway/CMakeLists.txt b/stack/apps/gateway/CMakeLists.txt index 7fee991da..f351f576e 100644 --- a/stack/apps/gateway/CMakeLists.txt +++ b/stack/apps/gateway/CMakeLists.txt @@ -31,7 +31,7 @@ IF(${MODULE_LORAWAN}) SET(libs alp d7ap d7ap_fs lorawan framework) ELSE() - SET(libs alp d7ap d7ap_fs framework) + SET(libs alp d7ap framework d7ap_fs) ENDIF() APP_BUILD(NAME ${APP_NAME} SOURCES app.c LIBS ${libs}) diff --git a/stack/apps/modem/CMakeLists.txt b/stack/apps/modem/CMakeLists.txt index 70cae7957..5a91eecc8 100644 --- a/stack/apps/modem/CMakeLists.txt +++ b/stack/apps/modem/CMakeLists.txt @@ -32,7 +32,7 @@ IF(${MODULE_LORAWAN}) SET(libs alp d7ap d7ap_fs lorawan framework) ELSE() - SET(libs alp d7ap d7ap_fs framework) + SET(libs alp d7ap framework d7ap_fs) ENDIF() APP_BUILD(NAME ${APP_NAME} SOURCES modem.c LIBS ${libs}) diff --git a/stack/apps/sensor_without_alp/CMakeLists.txt b/stack/apps/sensor_without_alp/CMakeLists.txt index 9985e05e7..0260f62d2 100644 --- a/stack/apps/sensor_without_alp/CMakeLists.txt +++ b/stack/apps/sensor_without_alp/CMakeLists.txt @@ -32,7 +32,7 @@ IF(${MODULE_LORAWAN}) SET(libs d7ap d7ap_fs lorawan framework) ELSE() - SET(libs d7ap d7ap_fs framework) + SET(libs d7ap framework d7ap_fs) ENDIF() APP_BUILD(NAME ${APP_NAME} SOURCES sensor_without_alp.c LIBS ${libs}) From 0891b837ef26f0e869e779bd038e4c0077aab8a1 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Thu, 25 Jul 2019 19:31:27 +0200 Subject: [PATCH 04/26] d7asp: fix regression introduced by the commit f95d894 Transport layer needs to be informed that the transaction is terminated. --- stack/modules/d7ap/d7asp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index 3a8d89c76..b9dbc789b 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -616,7 +616,7 @@ void d7asp_process_received_response(packet_t* packet, bool extension) current_request_id = NO_ACTIVE_REQUEST_ID; schedule_current_session(); // continue flushing until all request handled ... // stop the current transaction - // d7atp_stop_transaction(); //TO BE CHECKED THAT COMMENTING THIS OUT HAS NO NEGATIVE EFFECT + d7atp_stop_transaction(); } // switch to the state slave when the D7ATP Dialog Extension Procedure is initiated and all request are handled else if ((extension) && (current_request_id == current_master_session.next_request_id - 1)) From db343d242a21b6c4e862181157be9e6872d30b5a Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Tue, 6 Oct 2020 12:27:25 +0200 Subject: [PATCH 05/26] fs: fix build when using default values like the PERMANENT_STORAGE_SIZE --- stack/framework/inc/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack/framework/inc/fs.h b/stack/framework/inc/fs.h index 68fea53ed..b39f012ef 100644 --- a/stack/framework/inc/fs.h +++ b/stack/framework/inc/fs.h @@ -48,7 +48,7 @@ #endif #ifndef FRAMEWORK_FS_PERMANENT_STORAGE_SIZE -#define FRAMEWORK_FS_PERMANENT_STORAGE_SIZE 1900 +#define FRAMEWORK_FS_PERMANENT_STORAGE_SIZE 2200 #endif #ifndef FRAMEWORK_FS_VOLATILE_STORAGE_SIZE From 5718b51140afdbe5cac210bfc4475533d12dd566 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Tue, 6 Oct 2020 12:27:53 +0200 Subject: [PATCH 06/26] d7ap: fix warnings --- stack/modules/d7ap/d7atp.c | 2 +- stack/modules/d7ap/dll.c | 8 ++++++++ stack/modules/d7ap/phy.c | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/stack/modules/d7ap/d7atp.c b/stack/modules/d7ap/d7atp.c index 6357710ac..f1e49f7a4 100644 --- a/stack/modules/d7ap/d7atp.c +++ b/stack/modules/d7ap/d7atp.c @@ -585,7 +585,7 @@ void d7atp_signal_transmission_failure() void d7atp_process_received_packet(packet_t* packet) { bool extension = false; - timer_tick_t Tc; + timer_tick_t Tc = 0; assert(d7atp_state == D7ATP_STATE_MASTER_TRANSACTION_RESPONSE_PERIOD || d7atp_state == D7ATP_STATE_SLAVE_TRANSACTION_RESPONSE_PERIOD diff --git a/stack/modules/d7ap/dll.c b/stack/modules/d7ap/dll.c index f810dddfd..3946cec73 100644 --- a/stack/modules/d7ap/dll.c +++ b/stack/modules/d7ap/dll.c @@ -325,6 +325,14 @@ void start_background_scan() .rssi_thr = E_CCA, }; error_t err = phy_start_background_scan(&config, &dll_signal_packet_received); + + if (err == FAIL) + { DPRINT("RSSI < minimum --> phy_start_background_scan failed"); + + //TODO + // handle the case where the RSSI is not reached + } + if(rx_nf_method == D7ADLL_MEDIAN_OF_THREE) { uint8_t position = get_position_channel(); //if current_channel in array of channels AND gotten rssi_thr smaller than pre-programmed Ecca diff --git a/stack/modules/d7ap/phy.c b/stack/modules/d7ap/phy.c index 64578f3d8..c293733d3 100644 --- a/stack/modules/d7ap/phy.c +++ b/stack/modules/d7ap/phy.c @@ -629,6 +629,8 @@ error_t phy_init(void) { error_t phy_stop() { d7ap_fs_unregister_file_modified_callback(D7A_FILE_FACTORY_SETTINGS_FILE_ID); timer_cancel_event(&continuous_tx_expiration_timer); + + return SUCCESS; } void status_write() { From b60c4592eaab12f920733f8c965a4feb0f0aff56 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 14 Oct 2020 16:40:11 +0200 Subject: [PATCH 07/26] blockdevice: fix trace --- stack/framework/hal/common/blockdevice_ram.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stack/framework/hal/common/blockdevice_ram.c b/stack/framework/hal/common/blockdevice_ram.c index 0eeddc34a..6d934363f 100644 --- a/stack/framework/hal/common/blockdevice_ram.c +++ b/stack/framework/hal/common/blockdevice_ram.c @@ -50,7 +50,8 @@ blockdevice_driver_t blockdevice_driver_ram = { static void init(blockdevice_t* bd) { blockdevice_ram_t* bd_ram = (blockdevice_ram_t*)bd; - DPRINT("init RAM block device of size %i\n", bd_ram->size); + (void)bd_ram; + DPRINT("init RAM block device of size %i\n", bd_ram->base.size); } static error_t read(blockdevice_t* bd, uint8_t* data, uint32_t addr, uint32_t size) { From 9fecf05d5b6b69bbb41ea9af112bf68e9872c72b Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 14 Oct 2020 16:59:30 +0200 Subject: [PATCH 08/26] fs: fix warnings --- stack/framework/components/fs/fs.c | 20 +++++++++++++------- stack/framework/inc/d7ap_fs.h | 2 +- stack/framework/inc/fs.h | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/stack/framework/components/fs/fs.c b/stack/framework/components/fs/fs.c index 33a833f91..1204af7e7 100644 --- a/stack/framework/components/fs/fs.c +++ b/stack/framework/components/fs/fs.c @@ -37,8 +37,10 @@ #if defined(FRAMEWORK_LOG_ENABLED) && defined(FRAMEWORK_FS_LOG_ENABLED) #define DPRINT(...) log_print_string( __VA_ARGS__) + #define DPRINT_DATA(...) log_print_data(__VA_ARGS__) #else #define DPRINT(...) + #define DPRINT_DATA(...) #endif static fs_file_t files[FRAMEWORK_FS_FILE_COUNT] = { 0 }; // TODO do not keep all file metadata in RAM but use smaller MRU cache to save RAM @@ -87,7 +89,7 @@ error_t fs_register_block_device(blockdevice_t* block_device, uint8_t bd_index) uint32_t fs_get_address(uint8_t file_id) { return files[file_id].addr; } -void fs_init() +void fs_init(void) { if (is_fs_init_completed) return /*0*/; @@ -106,7 +108,7 @@ void fs_init() DPRINT("fs_init OK"); } -int _fs_init() +int _fs_init(void) { uint8_t expected_magic_number[FS_MAGIC_NUMBER_SIZE] = FS_MAGIC_NUMBER; uint32_t number_of_files; @@ -126,6 +128,7 @@ int _fs_init() #endif assert(number_of_files < FRAMEWORK_FS_FILE_COUNT); + DPRINT("number_of_files: %ld", number_of_files); for(int file_id = 0; file_id < FRAMEWORK_FS_FILE_COUNT; file_id++) { blockdevice_read(bd[FS_BLOCKDEVICE_TYPE_METADATA], (uint8_t*)&files[file_id], @@ -146,12 +149,12 @@ int _fs_init() bd_data_offset[files[file_id].blockdevice_index] += files[file_id].length; } } - + return 0; } //TODO: CRC MAGIC -static int _fs_create_magic() +static int _fs_create_magic(void) { assert(!is_fs_init_completed); uint8_t magic[] = FS_MAGIC_NUMBER; @@ -169,6 +172,9 @@ static int _fs_verify_magic(uint8_t* expected_magic_number) uint8_t magic_number[FS_MAGIC_NUMBER_SIZE]; memset(magic_number,0,FS_MAGIC_NUMBER_SIZE); blockdevice_read(bd[FS_BLOCKDEVICE_TYPE_METADATA], magic_number, 0, FS_MAGIC_NUMBER_SIZE); + + DPRINT("READ MAGIC NUMBER:"); + DPRINT_DATA(magic_number, FS_MAGIC_NUMBER_SIZE); if(memcmp(expected_magic_number, magic_number, FS_MAGIC_NUMBER_SIZE) != 0) // if not the FS on EEPROM is not compatible with the current code return -EINVAL; @@ -191,7 +197,7 @@ int _fs_create_file(uint8_t file_id, fs_blockdevice_types_t bd_type, const uint8 if (bd_type == FS_BLOCKDEVICE_TYPE_VOLATILE) { files[file_id].addr = bd_data_offset[bd_type]; - bd_data_offset[bd_type] += length; + bd_data_offset[bd_type] += length; } else { @@ -221,7 +227,7 @@ int _fs_create_file(uint8_t file_id, fs_blockdevice_types_t bd_type, const uint8 blockdevice_program(bd[bd_type], current_data, current_address, remaining_length); remaining_length = 0; - /* else if this is the starting block, only write untill the end of the first write_block */ + /* else if this is the starting block, only write until the end of the first write_block */ } else if(current_address == files[file_id].addr) { remaining_length -= bd[bd_type]->driver->write_block_size - (current_address & (bd[bd_type]->driver->write_block_size - 1)); @@ -303,7 +309,7 @@ int fs_write_file(uint8_t file_id, uint32_t offset, const uint8_t* buffer, uint3 } while (remaining_length > 0); - DPRINT("fs write_file (file_id %d, offset %d, addr %lu, length %d)\n", + DPRINT("fs write_file (file_id %d, offset %lu, addr %lu, length %lu)", file_id, offset, files[file_id].addr, length); return 0; diff --git a/stack/framework/inc/d7ap_fs.h b/stack/framework/inc/d7ap_fs.h index ccb603078..2324b1770 100644 --- a/stack/framework/inc/d7ap_fs.h +++ b/stack/framework/inc/d7ap_fs.h @@ -118,7 +118,7 @@ bool d7ap_fs_unregister_file_modified_callback(uint8_t file_id); bool d7ap_fs_register_file_modifying_callback(uint8_t file_id, d7ap_fs_modifying_file_callback_t callback); bool d7ap_fs_unregister_file_modifying_callback(uint8_t file_id); -void d7ap_fs_init(); +void d7ap_fs_init(void); int d7ap_fs_init_file(uint8_t file_id, const d7ap_fs_file_header_t* file_header, const uint8_t* initial_data); int d7ap_fs_init_file_on_blockdevice(uint8_t file_id, uint8_t blockdevice_index, const d7ap_fs_file_header_t* file_header, const uint8_t* initial_data); diff --git a/stack/framework/inc/fs.h b/stack/framework/inc/fs.h index b39f012ef..e5df160aa 100644 --- a/stack/framework/inc/fs.h +++ b/stack/framework/inc/fs.h @@ -87,7 +87,7 @@ typedef struct __attribute__((__packed__)) uint32_t addr; } fs_file_t; -void fs_init(); +void fs_init(void); int fs_init_file(uint8_t file_id, fs_blockdevice_types_t bd_type, const uint8_t* initial_data, uint32_t initial_data_length, uint32_t length); int fs_read_file(uint8_t file_id, uint32_t offset, uint8_t* buffer, uint32_t length); int fs_write_file(uint8_t file_id, uint32_t offset, const uint8_t* buffer, uint32_t length); From 4c4cd958a9880a8ed37b028aef5144d867d33a77 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 14 Oct 2020 17:08:30 +0200 Subject: [PATCH 09/26] alp_layer: fix uninitialised variable --- stack/modules/alp/alp_layer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack/modules/alp/alp_layer.c b/stack/modules/alp/alp_layer.c index 9c34095a1..ba71b75ff 100644 --- a/stack/modules/alp/alp_layer.c +++ b/stack/modules/alp/alp_layer.c @@ -480,7 +480,7 @@ static alp_status_codes_t process_op_indirect_forward( { DPRINT("indirect fwd"); bool re_read = false; - alp_control_t ctrl; + alp_control_t ctrl = action->ctrl; if ((previous_interface_file_id != action->indirect_interface_operand.interface_file_id) || interface_file_changed) { re_read = true; From c7d6670a03037e1d5fd0c350f2dca7a97daa70a2 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 14 Oct 2020 17:09:36 +0200 Subject: [PATCH 10/26] alp_layer: free resp_command in case of unregistered interface --- stack/modules/alp/alp_layer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stack/modules/alp/alp_layer.c b/stack/modules/alp/alp_layer.c index ba71b75ff..9d76604aa 100644 --- a/stack/modules/alp/alp_layer.c +++ b/stack/modules/alp/alp_layer.c @@ -851,7 +851,8 @@ static void process_async(void* arg) if (command->use_d7aactp) { DPRINT("Using D7AActP, transmit response to the configured interface"); resp_command->forward_itf_id = command->d7aactp_interface_config.itf_id; - forward_command(resp_command, &command->d7aactp_interface_config); + if (forward_command(resp_command, &command->d7aactp_interface_config) == false) // if interface is not registered, free the resp command + free_command(resp_command); free_command(command); return; } From e909441e7ed4af0242667b7b398724e9025e1486 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 14 Oct 2020 17:10:21 +0200 Subject: [PATCH 11/26] sensor apps: add FS initialisation FS initialisation can be done by the alp_layer_init function. But this obliges to start with ALP initilisation prior to the initilisation of the stack D7A. However, D7A stack relies on the D7A FS, and not necessarily on ALP. Thus, it is more safe to invoke explicitely the FS initialisation in the bootstrap prior to the D7A init. --- stack/apps/sensor_action/sensor.c | 1 + stack/apps/sensor_without_alp/sensor_without_alp.c | 1 + 2 files changed, 2 insertions(+) diff --git a/stack/apps/sensor_action/sensor.c b/stack/apps/sensor_action/sensor.c index 5ee33daa5..0c499af58 100644 --- a/stack/apps/sensor_action/sensor.c +++ b/stack/apps/sensor_action/sensor.c @@ -149,6 +149,7 @@ void bootstrap() { log_print_string("Device booted\n"); + d7ap_fs_init(); d7ap_init(); alp_layer_init(NULL, false); diff --git a/stack/apps/sensor_without_alp/sensor_without_alp.c b/stack/apps/sensor_without_alp/sensor_without_alp.c index 65b19974c..c4a732cc8 100644 --- a/stack/apps/sensor_without_alp/sensor_without_alp.c +++ b/stack/apps/sensor_without_alp/sensor_without_alp.c @@ -117,6 +117,7 @@ void bootstrap() { log_print_string("Device booted\n"); + d7ap_fs_init(); d7ap_init(); d7_client_id = d7ap_register(&callbacks); From 36826c81a2112c268efe01c6f9b90add99a8f73f Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:20:51 +0100 Subject: [PATCH 12/26] d7asp: fix FIFO buffer size --- stack/modules/d7ap/d7asp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index b9dbc789b..5d3229a45 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -68,7 +68,7 @@ struct d7asp_master_session { uint8_t requests_indices[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; /**< Contains for every request ID the index in command_buffer the index where the request begins */ uint8_t requests_lengths[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; /**< Contains for every request ID the index in command_buffer the length of the ALP payload in that request */ uint8_t response_lengths[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; /**< Contains for every request ID the index in command_buffer the expected length of the ALP response for the specific request */ - uint8_t request_buffer[MODULE_D7AP_FIFO_COMMAND_BUFFER_SIZE]; + uint8_t request_buffer[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE]; d7ap_addressee_t preferred_addressee; }; @@ -140,7 +140,7 @@ static void init_master_session(d7asp_master_session_t* session) { memset(session->requests_indices, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); memset(session->requests_lengths, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); memset(session->response_lengths, 255, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); - memset(session->request_buffer, 0x00, MODULE_D7AP_FIFO_COMMAND_BUFFER_SIZE); + memset(session->request_buffer, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE); // TODO we don't reset preferred_addressee field for now // for now one ALP command execution mostly results one new session, which @@ -156,7 +156,7 @@ static void flush_completed() { // single flush of the FIFO without retry d7ap_stack_session_completed(current_master_session.token, current_master_session.progress_bitmap, - current_master_session.success_bitmap, current_master_session.next_request_id - 1); + current_master_session.success_bitmap, current_master_session.next_request_id - 1); init_master_session(¤t_master_session); current_master_session.state = D7ASP_MASTER_SESSION_IDLE; d7atp_signal_dialog_termination(); @@ -413,7 +413,6 @@ uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_ DPRINT("current master session state %d", current_master_session.state); - init_master_session(¤t_master_session); DPRINT("Create master session %d", current_master_session.token); @@ -496,7 +495,7 @@ uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* alp_payload_buffer, // TODO can be called in all session states? assert(session != NULL); - assert(session->request_buffer_tail_idx + alp_payload_length < MODULE_D7AP_FIFO_COMMAND_BUFFER_SIZE); + assert(session->request_buffer_tail_idx + payload_length < (MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE)); assert(session->next_request_id < MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); // TODO do not assert but let upper layer handle this assert(!(expected_alp_response_length > 0 && (session->config.qos.qos_resp_mode == SESSION_RESP_MODE_NO || session->config.qos.qos_resp_mode == SESSION_RESP_MODE_NO_RPT))); // TODO return error From 0b0b94fece3cd0fd60b6d5b9ce175e5433e9784c Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:28:19 +0100 Subject: [PATCH 13/26] d7asp: fix bitmap search size --- stack/modules/d7ap/d7asp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index 5d3229a45..90b0744b8 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -206,7 +206,7 @@ static void flush_fifos() if (current_request_id == NO_ACTIVE_REQUEST_ID) { // find first request which is not acked or dropped - int8_t found_next_req_index = bitmap_search(current_master_session.progress_bitmap, false, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); + int8_t found_next_req_index = bitmap_search(current_master_session.progress_bitmap, false, current_master_session.next_request_id); if (found_next_req_index == -1 || found_next_req_index == current_master_session.next_request_id) { // we handled all requests ... From 59cd704e7c444a75453e51baf42a3aa250d57d8a Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:36:57 +0100 Subject: [PATCH 14/26] d7asp: fix d7atp_ctrl flag in the response packet --- stack/modules/d7ap/d7asp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index 90b0744b8..209972f9d 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -707,7 +707,11 @@ bool d7asp_process_received_packet(packet_t* packet) packet->d7atp_tl = compress_data(estimated_tl, true); } else - packet->d7atp_ctrl.ctrl_is_start = 0; + { + packet->d7atp_ctrl.ctrl_is_start = false; + packet->d7atp_ctrl.ctrl_tl = false; + packet->d7atp_ctrl.ctrl_te = false; + } // execute slave transaction if (packet->d7atp_ctrl.ctrl_is_ack_requested) From 10b8729f69a8befabe3b0e0a74effeff23b0d972 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:48:42 +0100 Subject: [PATCH 15/26] d7atp: fix start and Tl flag in D7ATP ctrl header --- stack/modules/d7ap/d7atp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/stack/modules/d7ap/d7atp.c b/stack/modules/d7ap/d7atp.c index f1e49f7a4..9f1a8b0cc 100644 --- a/stack/modules/d7ap/d7atp.c +++ b/stack/modules/d7ap/d7atp.c @@ -351,14 +351,18 @@ error_t d7atp_send_request(uint8_t dialog_id, uint8_t transaction_id, bool is_la // FG scan timeout is set (and scan started) in d7atp_signal_packet_transmitted() for now, to be verified packet->d7atp_ctrl = (d7atp_ctrl_t){ - .ctrl_is_start = true, + .ctrl_is_start = (packet->type == INITIAL_REQUEST) ? true : false, .ctrl_is_ack_requested = ack_requested, .ctrl_ack_not_void = qos_settings->qos_resp_mode == SESSION_RESP_MODE_ON_ERR? true : false, .ctrl_te = false, .ctrl_agc = false, - .ctrl_ack_record = false + .ctrl_ack_record = false, + .ctrl_tl = listen_timeout ? true : false }; + if (listen_timeout) + packet->d7atp_tl = listen_timeout; + if (ack_requested) { // TODO payload length does not include headers ... + hardcoded subband @@ -594,11 +598,12 @@ void d7atp_process_received_packet(packet_t* packet) // copy addressee from NP origin current_addressee.ctrl.id_type = packet->d7anp_ctrl.origin_id_type; current_addressee.access_class = packet->origin_access_class; - DPRINT("ORI AC=0x%02x", packet->origin_access_class); + DPRINT("ORIGINE AC=0x%02x", packet->origin_access_class); memcpy(current_addressee.id, packet->origin_access_id, 8); packet->d7anp_addressee = ¤t_addressee; DPRINT("Recvd dialog %i trans id %i, curr %i - %i", packet->d7atp_dialog_id, packet->d7atp_transaction_id, current_dialog_id, current_transaction_id); + DPRINT("Transaction start flag <%d> ACK_req <%d>", packet->d7atp_ctrl.ctrl_is_start, packet->d7atp_ctrl.ctrl_is_ack_requested); if (packet->d7atp_tl) current_Tl_received = CT_DECOMPRESS(packet->d7atp_tl); From 13ebdb73d233fc3b97bd18a16c1f711b986e1383 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:51:05 +0100 Subject: [PATCH 16/26] d7asp: fix BITMAP byte count --- stack/modules/d7ap/d7asp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack/modules/d7ap/d7asp.h b/stack/modules/d7ap/d7asp.h index 347de2c2f..6dc3ba09c 100644 --- a/stack/modules/d7ap/d7asp.h +++ b/stack/modules/d7ap/d7asp.h @@ -47,7 +47,7 @@ // index [8 .. 15] --> byte 2 // index [16.. 23] --> byte 3 // so the byte count can be calculated as the integer quotient of the division + 1 byte -#define REQUESTS_BITMAP_BYTE_COUNT (MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT/8) + 1 +#define REQUESTS_BITMAP_BYTE_COUNT (MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT/8) + (MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT%8 ? 1 : 0) /** * /brief The state of a session FIFO From 1602ad637faaa52e7ebd1d8276ee7fc9ae165632 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 26 Feb 2021 11:42:14 +0100 Subject: [PATCH 17/26] d7atp: fix current_tl_received current_tl_received is renitialised when dialog is terminated. If not reinitialised, the automation scan can't be restarted after a master session is terminated. --- stack/modules/d7ap/d7atp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/stack/modules/d7ap/d7atp.c b/stack/modules/d7ap/d7atp.c index 9f1a8b0cc..49d2d8f64 100644 --- a/stack/modules/d7ap/d7atp.c +++ b/stack/modules/d7ap/d7atp.c @@ -147,6 +147,7 @@ static void terminate_dialog() switch_state(D7ATP_STATE_IDLE); current_dialog_id = 0; current_transaction_id = NO_ACTIVE_REQUEST_ID; + current_Tl_received = 0; stop_dialog_after_tx = false; // Discard eventually the Tc timer From fb4ea08c8d539ccaa18a38a575041d736a49ae7c Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 24 Apr 2020 08:51:28 +0200 Subject: [PATCH 18/26] d7a: registration is only possible when the stack is completly initialised --- stack/framework/inc/d7ap.h | 4 ++-- stack/modules/d7ap/d7ap.c | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/stack/framework/inc/d7ap.h b/stack/framework/inc/d7ap.h index 2f8ed7eaf..4e14ef36e 100644 --- a/stack/framework/inc/d7ap.h +++ b/stack/framework/inc/d7ap.h @@ -192,9 +192,9 @@ void d7ap_stop(void); * * @param[in] desc pointer to the client resource * - * @return the client Id + * @return the client Id (-1 when trying to register whereas the D7A stack is not initialised) */ -uint8_t d7ap_register(d7ap_resource_desc_t* desc); +int8_t d7ap_register(d7ap_resource_desc_t* desc); /** diff --git a/stack/modules/d7ap/d7ap.c b/stack/modules/d7ap/d7ap.c index a421f6762..fca6f886e 100644 --- a/stack/modules/d7ap/d7ap.c +++ b/stack/modules/d7ap/d7ap.c @@ -55,11 +55,11 @@ void d7ap_init() { if(inited) return; - inited = true; // Initialize the D7AP stack d7ap_stack_init(); registered_client_nb = 0; + inited = true; } void d7ap_stop() @@ -76,12 +76,16 @@ void d7ap_stop() * * @return the client Id */ -uint8_t d7ap_register(d7ap_resource_desc_t* desc) +int8_t d7ap_register(d7ap_resource_desc_t* desc) { - assert(inited); assert(registered_client_nb < MODULE_D7AP_MAX_CLIENT_COUNT); + + if (inited == false) + return -1; + registered_client[registered_client_nb] = *desc; registered_client_nb++; + DPRINT("\r\nD7A = %d", registered_client_nb-1); return (registered_client_nb-1); } From d71e3ad14dae26dbe68c3bc462cd4166d314645a Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 14 Oct 2020 16:58:35 +0200 Subject: [PATCH 19/26] d7ap: introduce Te in d7ap_session_config_t structure --- stack/framework/inc/d7ap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stack/framework/inc/d7ap.h b/stack/framework/inc/d7ap.h index 4e14ef36e..7f34fbcc2 100644 --- a/stack/framework/inc/d7ap.h +++ b/stack/framework/inc/d7ap.h @@ -148,6 +148,7 @@ typedef struct { typedef struct __attribute__((__packed__)) { d7ap_session_qos_t qos; uint8_t dormant_timeout; + uint8_t te; d7ap_addressee_t addressee; } d7ap_session_config_t; From ab832d34f2544311ab0bd866ceac7c64b764684e Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:30:51 +0100 Subject: [PATCH 20/26] d7asp: remove alp payload terminology --- stack/modules/d7ap/d7asp.c | 9 +++++---- stack/modules/d7ap/d7asp.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index 209972f9d..ead6b26ce 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -488,7 +488,7 @@ error_t d7asp_send_response(uint8_t* payload, uint8_t length) return(d7atp_send_response(current_response_packet)); } -uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* alp_payload_buffer, uint8_t alp_payload_length, uint8_t expected_alp_response_length) +uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* payload_buffer, uint8_t payload_length, uint8_t expected_alp_response_length) { DPRINT("Queuing request in the session queue"); d7asp_master_session_t *session = get_master_session_from_token(session_token); @@ -505,10 +505,11 @@ uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* alp_payload_buffer, // TODO request can contain 1 or more ALP commands, find a way to group commands in requests instead of dumping all requests in one buffer uint8_t request_id = session->next_request_id; session->requests_indices[request_id] = session->request_buffer_tail_idx; - session->requests_lengths[request_id] = alp_payload_length; + session->requests_lengths[request_id] = payload_length; session->response_lengths[request_id] = expected_alp_response_length; - memcpy(session->request_buffer + session->request_buffer_tail_idx, alp_payload_buffer, alp_payload_length); - session->request_buffer_tail_idx += alp_payload_length + 1; + memcpy(session->request_buffer + session->request_buffer_tail_idx, payload_buffer, payload_length); + session->request_buffer_tail_idx += payload_length + 1; + session->next_request_id++; if(current_master_session.state == D7ASP_MASTER_SESSION_IDLE) { diff --git a/stack/modules/d7ap/d7asp.h b/stack/modules/d7ap/d7asp.h index 6dc3ba09c..93b31bafe 100644 --- a/stack/modules/d7ap/d7asp.h +++ b/stack/modules/d7ap/d7asp.h @@ -58,7 +58,7 @@ void d7asp_init(); void d7asp_stop(); uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_config); -uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* alp_payload_buffer, uint8_t alp_payload_length, uint8_t expected_alp_response_length); +uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* payload_buffer, uint8_t payload_length, uint8_t expected_response_length); error_t d7asp_send_response(uint8_t* payload, uint8_t length); @@ -76,7 +76,7 @@ void d7asp_process_received_response(packet_t* packet, bool extension); bool d7asp_process_received_packet(packet_t* packet); /** - * @brief Called by DLL to signal the CSMA/CA process completed succesfully and packet can be ack-ed for QoS = None + * @brief Called by DLL to signal the CSMA/CA process completed successfully and packet can be ack-ed for QoS = None */ void d7asp_signal_packet_transmitted(packet_t* packet); From 01518f028ddd8916f4cad92feed8bd42cfe7866c Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:26:24 +0100 Subject: [PATCH 21/26] d7asp: introduce a retry counter per request --- stack/modules/d7ap/d7asp.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index ead6b26ce..33d1a9687 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -69,6 +69,7 @@ struct d7asp_master_session { uint8_t requests_lengths[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; /**< Contains for every request ID the index in command_buffer the length of the ALP payload in that request */ uint8_t response_lengths[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; /**< Contains for every request ID the index in command_buffer the expected length of the ALP response for the specific request */ uint8_t request_buffer[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE]; + uint8_t retry_count[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; d7ap_addressee_t preferred_addressee; }; @@ -78,9 +79,6 @@ static d7asp_master_session_t NGDEF(_current_master_session); // TODO we only us static uint8_t NGDEF(_current_request_id); // TODO move ? #define current_request_id NG(_current_request_id) -static uint8_t NGDEF(_current_request_retry_count); -#define current_request_retry_count NG(_current_request_retry_count) - static packet_t* NGDEF(_current_request_packet); #define current_request_packet NG(_current_request_packet) @@ -141,6 +139,7 @@ static void init_master_session(d7asp_master_session_t* session) { memset(session->requests_lengths, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); memset(session->response_lengths, 255, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); memset(session->request_buffer, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE); + memset(session->retry_count, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); // TODO we don't reset preferred_addressee field for now // for now one ALP command execution mostly results one new session, which @@ -216,7 +215,17 @@ static void flush_fifos() current_request_id = found_next_req_index; DPRINT("Found request Id %x", current_request_id); - current_request_retry_count = 0; + + DPRINT("Current request retry count: %i", current_master_session.retry_count[current_request_id]); + if (current_master_session.retry_count[current_request_id] == single_request_retry_limit) + { + // mark request as failed and pop + mark_current_request_done(); + DPRINT("Request reached single request retry limit (%i), skipping request", single_request_retry_limit); + current_request_id = NO_ACTIVE_REQUEST_ID; + schedule_current_session(); + return; + } current_request_packet = packet_queue_alloc_packet(); assert(current_request_packet); @@ -242,7 +251,9 @@ static void flush_fifos() } else { - if (current_request_id == 0) + if (current_master_session.retry_count[current_request_id] > 0) + current_request_packet->type = RETRY_REQUEST; + else if (current_request_id == 0) current_request_packet->type = INITIAL_REQUEST; else current_request_packet->type = SUBSEQUENT_REQUEST; @@ -254,8 +265,8 @@ static void flush_fifos() else { // retrying request ... - DPRINT("Current request retry count: %i", current_request_retry_count); - if (current_request_retry_count == single_request_retry_limit) + DPRINT("Current request retry count: %i", current_master_session.retry_count[current_request_id]); + if (current_master_session.retry_count[current_request_id] == single_request_retry_limit) { // mark request as failed and pop mark_current_request_done(); @@ -749,6 +760,9 @@ static void on_request_completed() DPRINT_DATA(current_master_session.preferred_addressee.id, 8); } + // increment the retry counter + current_master_session.retry_count[current_request_id] += 1; + if (!bitmap_get(current_master_session.progress_bitmap, current_request_id)) { if(current_master_session.config.qos.qos_resp_mode == SESSION_RESP_MODE_PREFERRED @@ -758,7 +772,7 @@ static void on_request_completed() current_responder_lowest_lb.lb = LB_MAX; memcpy(current_master_session.preferred_addressee.id, (uint8_t[8]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 8); } - current_request_retry_count++; + // the request may be retransmitted, don't free yet (this will be done in flush_fifo() when failed) } else From 77e0b5f57fd42c711a89e7c6d712503dbabc9ad0 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 15:35:17 +0100 Subject: [PATCH 22/26] d7asp: set TX duration for each request (used by TL computation) --- stack/modules/d7ap/d7asp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index 33d1a9687..7135e9a65 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -71,6 +71,8 @@ struct d7asp_master_session { uint8_t request_buffer[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE]; uint8_t retry_count[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; d7ap_addressee_t preferred_addressee; + uint16_t tx_duration[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; + dae_access_profile_t active_addressee_access_profile; }; static d7asp_master_session_t NGDEF(_current_master_session); // TODO we only use 1 fifo for now, should be multiple later (1 per on unique addressee and QoS combination) @@ -140,6 +142,7 @@ static void init_master_session(d7asp_master_session_t* session) { memset(session->response_lengths, 255, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); memset(session->request_buffer, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE); memset(session->retry_count, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); + memset(session->tx_duration, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * sizeof(uint16_t)); // TODO we don't reset preferred_addressee field for now // for now one ALP command execution mostly results one new session, which @@ -433,6 +436,8 @@ uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_ current_master_session.config.addressee.ctrl = d7asp_master_session_config->addressee.ctrl; current_master_session.config.addressee.access_class = d7asp_master_session_config->addressee.access_class; + d7ap_fs_read_access_class(current_master_session.config.addressee.access_specifier, ¤t_master_session.active_addressee_access_profile); + if(current_master_session.config.qos.qos_resp_mode != SESSION_RESP_MODE_PREFERRED) { memcpy(current_master_session.config.addressee.id, d7asp_master_session_config->addressee.id, sizeof(current_master_session.config.addressee.id)); } else { @@ -520,6 +525,9 @@ uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* payload_buffer, uint session->response_lengths[request_id] = expected_alp_response_length; memcpy(session->request_buffer + session->request_buffer_tail_idx, payload_buffer, payload_length); session->request_buffer_tail_idx += payload_length + 1; + session->tx_duration[request_id] = phy_calculate_tx_duration(session->active_addressee_access_profile.channel_header.ch_class, + session->active_addressee_access_profile.channel_header.ch_coding, + payload_length + expected_alp_response_length, false); session->next_request_id++; From 552bbfbd09b4bcc21ad4701dfa04a99d3e5d50ce Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 16:01:39 +0100 Subject: [PATCH 23/26] [New feature] introduce the fragmentation feature This feature is only applicable when sending a long request or when receiving an unsollicited request (not for response). One request is handled per fragmentation session. --- stack/framework/inc/alp.h | 2 +- stack/framework/inc/d7ap.h | 6 +- stack/modules/alp/d7ap_interface.c | 6 +- stack/modules/d7ap/d7anp.c | 2 +- stack/modules/d7ap/d7ap.c | 2 +- stack/modules/d7ap/d7ap_stack.c | 63 +++++++---- stack/modules/d7ap/d7ap_stack.h | 4 +- stack/modules/d7ap/d7asp.c | 167 +++++++++++++++++++++++++++-- stack/modules/d7ap/d7asp.h | 2 +- stack/modules/d7ap/d7atp.c | 139 ++++++++++++++++++++---- stack/modules/d7ap/d7atp.h | 15 ++- stack/modules/d7ap/packet.h | 5 +- 12 files changed, 345 insertions(+), 68 deletions(-) diff --git a/stack/framework/inc/alp.h b/stack/framework/inc/alp.h index dd34b0491..874de4648 100644 --- a/stack/framework/inc/alp.h +++ b/stack/framework/inc/alp.h @@ -301,7 +301,7 @@ typedef struct { alp_itf_id_t itf_id; uint8_t itf_cfg_len; uint8_t itf_status_len; - error_t (*send_command)(uint8_t* payload, uint8_t payload_length, uint8_t expected_response_length, uint16_t* trans_id, alp_interface_config_t* itf_cfg); + error_t (*send_command)(uint8_t* payload, uint16_t payload_length, uint8_t expected_response_length, uint16_t* trans_id, alp_interface_config_t* itf_cfg); interface_init init; interface_deinit deinit; bool unique; // TODO diff --git a/stack/framework/inc/d7ap.h b/stack/framework/inc/d7ap.h index 7f34fbcc2..c5ef0b66e 100644 --- a/stack/framework/inc/d7ap.h +++ b/stack/framework/inc/d7ap.h @@ -44,7 +44,7 @@ #define ID_TYPE_IS_BROADCAST(id_type) (id_type == ID_TYPE_NBID || id_type == ID_TYPE_NOID) -#define D7A_PAYLOAD_MAX_SIZE 255 // TODO confirm this value when FEC and security are disabled +#define D7A_PAYLOAD_MAX_SIZE 233 // TODO confirm this value when FEC and security are disabled typedef enum { @@ -158,7 +158,7 @@ typedef void (*d7ap_receive_callback)(uint16_t trans_id, uint8_t* payload, uint8 * @returns true when the unsolicited request will result in a response payload from the upper layer. If no response is expected * the upper layer should return false, so the stack can respond with an ack immediately (if requested by origin). */ -typedef bool (*d7ap_receive_unsolicited_callback)(uint8_t* payload, uint8_t len, d7ap_session_result_t result); +typedef bool (*d7ap_receive_unsolicited_callback)(uint8_t* payload, uint16_t len, d7ap_session_result_t result); typedef void (*d7ap_transmitted_callback)(uint16_t trans_id, error_t error); typedef struct{ @@ -233,7 +233,7 @@ uint8_t d7ap_get_payload_max_size(nls_method_t nls_method); * @return an error (errno.h) in case of failure */ error_t d7ap_send(uint8_t clientId, d7ap_session_config_t* config, uint8_t* payload, - uint8_t len, uint8_t expected_response_len, uint16_t* trans_id); + uint16_t len, uint8_t expected_response_len, uint16_t* trans_id); /** diff --git a/stack/modules/alp/d7ap_interface.c b/stack/modules/alp/d7ap_interface.c index d027f1ae8..8e561f445 100644 --- a/stack/modules/alp/d7ap_interface.c +++ b/stack/modules/alp/d7ap_interface.c @@ -31,7 +31,7 @@ #endif static void response_from_d7ap(uint16_t trans_id, uint8_t* payload, uint8_t len, d7ap_session_result_t result); -static bool command_from_d7ap(uint8_t* payload, uint8_t len, d7ap_session_result_t result); +static bool command_from_d7ap(uint8_t* payload, uint16_t len, d7ap_session_result_t result); static void d7ap_command_completed(uint16_t trans_id, error_t error); static alp_interface_t d7_alp_interface; @@ -108,7 +108,7 @@ static void response_from_d7ap(uint16_t trans_id, uint8_t* payload, uint8_t len, alp_layer_received_response(trans_id, payload, len, &d7_status); } -static bool command_from_d7ap(uint8_t* payload, uint8_t len, d7ap_session_result_t result) { +static bool command_from_d7ap(uint8_t* payload, uint16_t len, d7ap_session_result_t result) { DPRINT("command from d7 with len %i result linkbudget %i", len, result.link_budget); alp_interface_status_t d7_status = serialize_session_result_to_alp_interface_status(&result); alp_command_t* command = alp_layer_command_alloc(false, false); @@ -124,7 +124,7 @@ static bool command_from_d7ap(uint8_t* payload, uint8_t len, d7ap_session_result return alp_layer_process(command); } -static error_t d7ap_alp_send(uint8_t* payload, uint8_t payload_length, uint8_t expected_response_length, uint16_t* trans_id, alp_interface_config_t* itf_cfg) { +static error_t d7ap_alp_send(uint8_t* payload, uint16_t payload_length, uint8_t expected_response_length, uint16_t* trans_id, alp_interface_config_t* itf_cfg) { DPRINT("sending D7 packet"); if(itf_cfg != NULL) { diff --git a/stack/modules/d7ap/d7anp.c b/stack/modules/d7ap/d7anp.c index ebbc77e88..ff34ed4dd 100644 --- a/stack/modules/d7ap/d7anp.c +++ b/stack/modules/d7ap/d7anp.c @@ -279,7 +279,7 @@ error_t d7anp_tx_foreground_frame(packet_t* packet, bool should_include_origin_t d7anp_prev_state = d7anp_state; // No need to initialize the packet field in case of retry, except the security frame counter - if (packet->type == RETRY_REQUEST) + if ((packet->type == RETRY_REQUEST) && (!packet->d7atp_ctrl.ctrl_fragment)) goto security; if (!should_include_origin_template) diff --git a/stack/modules/d7ap/d7ap.c b/stack/modules/d7ap/d7ap.c index fca6f886e..f5c087f71 100644 --- a/stack/modules/d7ap/d7ap.c +++ b/stack/modules/d7ap/d7ap.c @@ -175,7 +175,7 @@ uint8_t d7ap_get_payload_max_size(nls_method_t nls_method) * @return an error (errno.h) in case of failure */ error_t d7ap_send(uint8_t client_id, d7ap_session_config_t* config, uint8_t* payload, - uint8_t len, uint8_t expected_response_len, uint16_t *trans_id) + uint16_t len, uint8_t expected_response_len, uint16_t *trans_id) { error_t error; diff --git a/stack/modules/d7ap/d7ap_stack.c b/stack/modules/d7ap/d7ap_stack.c index c6305e229..2e8f65977 100644 --- a/stack/modules/d7ap/d7ap_stack.c +++ b/stack/modules/d7ap/d7ap_stack.c @@ -52,6 +52,7 @@ typedef struct { uint8_t client_id; uint8_t request_nb; uint16_t trans_id[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; + bool fragmentation; } session_t; static session_t sessions[MODULE_D7AP_MAX_SESSION_COUNT]; @@ -157,6 +158,7 @@ static void free_session(session_t* session) { session->request_nb = 0; session->client_id = INVALID_CLIENT_ID; session->token = 0; + session->fragmentation = false; }; static session_t* alloc_session(uint8_t client_id) { @@ -232,8 +234,10 @@ static session_t* get_session_by_session_token(uint8_t session_token) }*/ error_t d7ap_stack_send(uint8_t client_id, d7ap_session_config_t* config, uint8_t* payload, - uint8_t len, uint8_t expected_response_length, uint16_t *trans_id) + uint16_t len, uint8_t expected_response_length, uint16_t *trans_id) { + uint8_t request_id; + bool fragmentation = (len > D7A_PAYLOAD_MAX_SIZE) ? true : false; // When an application response is expected, forward the payload directly to the current D7A session // TODO how to filter by client Id since we don't know to which client the request is addressed? @@ -245,7 +249,7 @@ error_t d7ap_stack_send(uint8_t client_id, d7ap_session_config_t* config, uint8_ } // Create or return the master session if the current one is compatible with the given session configuration. - uint8_t session_token = d7asp_master_session_create(config); + uint8_t session_token = d7asp_master_session_create(config, fragmentation); if(session_token == 0) return ERETRY; @@ -267,26 +271,42 @@ error_t d7ap_stack_send(uint8_t client_id, d7ap_session_config_t* config, uint8_ //TODO handle here the fragmentation if needed? - uint8_t request_id = d7asp_queue_request(session->token, - payload, len, - expected_response_length); + if ((len / D7A_PAYLOAD_MAX_SIZE) > MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT) + return -ESIZE; - session->trans_id[session->request_nb] = ((uint16_t)session->token << 8) | (request_id & 0x00FF); + if (len > D7A_PAYLOAD_MAX_SIZE) + session->fragmentation = true; - if (trans_id != NULL) { - *trans_id = session->trans_id[session->request_nb]; - DPRINT("[D7AP] request posted with trans_id %02X and request_nb %d", *trans_id, session->request_nb); - } else { - DPRINT("[D7AP] request posted with request_nb %d", session->request_nb); + while(len) + { + request_id = d7asp_queue_request(session->token, + payload + session->request_nb * D7A_PAYLOAD_MAX_SIZE, + len > D7A_PAYLOAD_MAX_SIZE ? D7A_PAYLOAD_MAX_SIZE : len, + expected_response_length); + + session->trans_id[session->request_nb] = ((uint16_t)session->token << 8) | (request_id & 0x00FF); + + if (trans_id != NULL) { + *trans_id = session->trans_id[session->request_nb]; + DPRINT("[D7AP] request posted with trans_id %02X and request_nb %d", *trans_id, session->request_nb); + } else { + DPRINT("[D7AP] request posted with request_nb %d", session->request_nb); + } + + DPRINT_DATA(payload + session->request_nb * D7A_PAYLOAD_MAX_SIZE, + len > D7A_PAYLOAD_MAX_SIZE ? D7A_PAYLOAD_MAX_SIZE : len); + + session->request_nb++; + if (len > D7A_PAYLOAD_MAX_SIZE) + len -= D7A_PAYLOAD_MAX_SIZE; + else + len = 0; } - - DPRINT_DATA(payload, len); - session->request_nb++; return SUCCESS; } -bool d7ap_stack_process_unsolicited_request(uint8_t *payload, uint8_t length, d7ap_session_result_t result) +bool d7ap_stack_process_unsolicited_request(uint8_t *payload, uint16_t length, d7ap_session_result_t result) { bool expect_upper_layer_resp_payload = false; @@ -340,7 +360,7 @@ void d7ap_stack_process_received_response(uint8_t *payload, uint8_t length, d7ap registered_client[session->client_id].receive_cb(trans_id, payload, length, result); } -void d7ap_stack_session_completed(uint8_t session_token, uint8_t* progress_bitmap, uint8_t* success_bitmap, uint8_t bitmap_byte_count) +void d7ap_stack_session_completed(uint8_t session_token, uint8_t* progress_bitmap, uint8_t* success_bitmap, uint8_t bitmap_size) { DPRINT("[D7AP] session is completed"); error_t error; @@ -352,6 +372,14 @@ void d7ap_stack_session_completed(uint8_t session_token, uint8_t* progress_bitma if (registered_client[session->client_id].transmitted_cb == NULL) goto free_session; + if (session->fragmentation) + { + // find if at least one fragment is not set as success + error = bitmap_search(success_bitmap, false, bitmap_size) == -1 ? SUCCESS : FAIL; + registered_client[session->client_id].transmitted_cb(session->trans_id[session->request_nb -1], error); + goto free_session; + } + for(uint8_t i = 0; i < session->request_nb; i++) { request_id = (uint8_t)(session->trans_id[i] & 0xFF); @@ -360,9 +388,8 @@ void d7ap_stack_session_completed(uint8_t session_token, uint8_t* progress_bitma registered_client[session->client_id].transmitted_cb(session->trans_id[i], error); } - switch_state(D7AP_STACK_STATE_IDLE); - free_session: + switch_state(D7AP_STACK_STATE_IDLE); free_session(session); } diff --git a/stack/modules/d7ap/d7ap_stack.h b/stack/modules/d7ap/d7ap_stack.h index 4aca1c5ad..fd844bf4b 100644 --- a/stack/modules/d7ap/d7ap_stack.h +++ b/stack/modules/d7ap/d7ap_stack.h @@ -42,9 +42,9 @@ void d7ap_stack_init(void); void d7ap_stack_stop(); error_t d7ap_stack_send(uint8_t client_id, d7ap_session_config_t* config, uint8_t* payload, - uint8_t len, uint8_t expected_response_length, uint16_t *trans_id); + uint16_t len, uint8_t expected_response_length, uint16_t *trans_id); -bool d7ap_stack_process_unsolicited_request(uint8_t* payload, uint8_t length, d7ap_session_result_t result); +bool d7ap_stack_process_unsolicited_request(uint8_t* payload, uint16_t length, d7ap_session_result_t result); void d7ap_stack_process_received_response(uint8_t* payload, uint8_t length, d7ap_session_result_t result); diff --git a/stack/modules/d7ap/d7asp.c b/stack/modules/d7ap/d7asp.c index 7135e9a65..34781c796 100644 --- a/stack/modules/d7ap/d7asp.c +++ b/stack/modules/d7ap/d7asp.c @@ -61,6 +61,7 @@ struct d7asp_master_session { d7ap_session_config_t config; d7asp_master_session_state_t state; uint8_t token; + bool fragmentation; uint8_t progress_bitmap[REQUESTS_BITMAP_BYTE_COUNT]; uint8_t success_bitmap[REQUESTS_BITMAP_BYTE_COUNT]; uint8_t next_request_id; @@ -75,6 +76,18 @@ struct d7asp_master_session { dae_access_profile_t active_addressee_access_profile; }; +typedef struct { + d7ap_session_config_t config; + //d7asp_master_session_state_t state; + uint8_t token; + uint8_t received_fragment_nb; + uint8_t total_fragments_nb; + uint8_t fragment_buffer_tail_idx; + uint8_t fragment_indices[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; /**< Contains for every fragment ID the index in fragments_buffer the index where the fragment payload begins */ + uint8_t fragment_lengths[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT]; /**< Contains for every fragment ID the index in fragments_buffer the length of the payload in that fragment */ + uint8_t fragments_buffer[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE]; +} d7asp_fragmentation_session_t; + static d7asp_master_session_t NGDEF(_current_master_session); // TODO we only use 1 fifo for now, should be multiple later (1 per on unique addressee and QoS combination) #define current_master_session NG(_current_master_session) @@ -90,6 +103,10 @@ static uint8_t NGDEF(_single_request_retry_limit); static packet_t* NGDEF(_current_response_packet); #define current_response_packet NG(_current_response_packet) +static d7asp_fragmentation_session_t NGDEF(_fragmentation_session); +#define fragmentation_session NG(_fragmentation_session) + + static timer_event current_session_timer; static timer_event dormant_session_timer; @@ -133,6 +150,7 @@ static void init_master_session(d7asp_master_session_t* session) { do { session->token = get_rnd() % 0xFF; } while(session->token == 0); + session->fragmentation = false; memset(session->progress_bitmap, 0x00, REQUESTS_BITMAP_BYTE_COUNT); memset(session->success_bitmap, 0x00, REQUESTS_BITMAP_BYTE_COUNT); session->next_request_id = 0; @@ -150,6 +168,17 @@ static void init_master_session(d7asp_master_session_t* session) { // over the session, until we decide on session lifetime etc } +static void init_fragmentation_session(d7asp_fragmentation_session_t* session) { + + //memset(session, 0x00, sizeof(d7asp_fragmentation_session_t)); + session->received_fragment_nb = 0; + session->total_fragments_nb = 0; + session->fragment_buffer_tail_idx = 0; + memset(session->fragment_indices, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); + memset(session->fragment_lengths, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); + memset(session->fragments_buffer, 0x00, MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE); +} + static void flush_completed() { DPRINT("FIFO flush completed"); @@ -286,8 +315,28 @@ static void flush_fifos() } uint8_t listen_timeout = 0; // TODO calculate timeout (and update during transaction lifetime) (based on Tc, channel, cs, payload size, # msgs, # retries) - ret = d7atp_send_request(current_master_session.token, current_request_id, (current_request_id == current_master_session.next_request_id - 1), - current_request_packet, ¤t_master_session.config.qos, listen_timeout, current_master_session.response_lengths[current_request_id]); + + if (current_master_session.fragmentation) + { + uint16_t Te = 500; //FIXME adjust the value + uint16_t Tl = 0; + for (uint8_t request_id = 0; request_id < current_master_session.next_request_id; request_id++) + { + if (!bitmap_get(current_master_session.success_bitmap, request_id)) + { + Tl += (current_master_session.tx_duration[request_id] + Te) * (single_request_retry_limit - current_master_session.retry_count[current_request_id]); + } + } + + listen_timeout = compress_data(Tl, true); + DPRINT("TL is set to %d compressed to %d", Tl, listen_timeout); + } + + ret = d7atp_send_request(current_master_session.token, current_request_id, + (current_request_id == current_master_session.next_request_id - 1), + current_request_packet, ¤t_master_session.config.qos, + listen_timeout, current_master_session.response_lengths[current_request_id], + current_master_session.fragmentation, current_master_session.next_request_id); if (ret == EPERM) { // this is probably because no further encryption is possible (frame counter reaches the maximum value) @@ -408,11 +457,17 @@ void d7asp_stop() timer_cancel_event(&dormant_session_timer); } -uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_config) { +uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_config, bool fragmentation) { // TODO for now we assume only one concurrent session, in the future we should dynamically allocate (or return from pool) a session if (current_master_session.state != D7ASP_MASTER_SESSION_IDLE) { + if (fragmentation) + { + DPRINT("current master session state %d prevents to create a fragmentation session", current_master_session.state); + return 0; + } + // Requests can be pushed in the FIFO by upper layer anytime if ((current_master_session.config.addressee.access_class == d7asp_master_session_config->addressee.access_class) && (current_master_session.config.addressee.ctrl.nls_method == d7asp_master_session_config->addressee.ctrl.nls_method) && @@ -428,8 +483,9 @@ uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_ DPRINT("current master session state %d", current_master_session.state); init_master_session(¤t_master_session); + current_master_session.fragmentation = fragmentation; - DPRINT("Create master session %d", current_master_session.token); + DPRINT("Create %s session %d", fragmentation ? "fragmentation" : "master", current_master_session.token); current_master_session.config.qos = d7asp_master_session_config->qos; current_master_session.config.dormant_timeout = d7asp_master_session_config->dormant_timeout; @@ -553,6 +609,37 @@ uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* payload_buffer, uint void d7asp_process_received_response(packet_t* packet, bool extension) { hw_watchdog_feed(); // TODO do here? + + assert(d7asp_state == D7ASP_STATE_MASTER); + assert(packet->d7atp_dialog_id == current_master_session.token); + assert(packet->d7atp_transaction_id == current_request_id); + + if (current_master_session.fragmentation) + { + // handle the ACK_BITMAP + if (packet->d7atp_ctrl.ctrl_ack_not_void) + { + /* in case of broadcast, the success bitmap is an AND between the current bitmap and the bitmap provided by the node + for (int8_t i = 0; i < ACK_BITMAP_BYTE_COUNT; i++) + current_master_session.success_bitmap[i] &= packet->d7atp_ack_template.bitmap[i];*/ + /* + * For now, the fragmentation is allowed in unicast only + */ + memcpy(current_master_session.progress_bitmap, packet->d7atp_ack_template.bitmap, ACK_BITMAP_BYTE_COUNT); + memcpy(current_master_session.success_bitmap, packet->d7atp_ack_template.bitmap, ACK_BITMAP_BYTE_COUNT); + } + else + memset(current_master_session.success_bitmap, 0xFF, ACK_BITMAP_BYTE_COUNT); + + packet_queue_free_packet(packet); + current_request_id = NO_ACTIVE_REQUEST_ID; + schedule_current_session(); // continue flushing until all request handled ... + + // stop the current transaction + d7atp_stop_transaction(); + return; + } + d7ap_session_result_t result = { .channel = { .channel_header = packet->phy_config.rx.channel_id.channel_header_raw, @@ -573,10 +660,6 @@ void d7asp_process_received_response(packet_t* packet, bool extension) // .fifo_token and .seqnr filled below }; - assert(d7asp_state == D7ASP_STATE_MASTER); - assert(packet->d7atp_dialog_id == current_master_session.token); - assert(packet->d7atp_transaction_id == current_request_id); - // received ack DPRINT("Received ACK for request ID %d", current_request_id); if (current_master_session.config.qos.qos_resp_mode != SESSION_RESP_MODE_NO @@ -658,13 +741,70 @@ bool d7asp_process_received_packet(packet_t* packet) d7asp_state == D7ASP_STATE_PENDING_MASTER || d7asp_state == D7ASP_STATE_SLAVE_PENDING_MASTER); + if ((packet->d7atp_ctrl.ctrl_fragment) && + (d7asp_state == D7ASP_STATE_IDLE || d7asp_state == D7ASP_STATE_PENDING_MASTER)) + { + DPRINT("Fragmentation session is starting"); + init_fragmentation_session(&fragmentation_session); + fragmentation_session.total_fragments_nb = packet->d7atp_fragments_number; + } + // received a request, start slave session, process and respond if (d7asp_state == D7ASP_STATE_IDLE) switch_state(D7ASP_STATE_SLAVE); // don't switch when already in slave state else if (d7asp_state == D7ASP_STATE_PENDING_MASTER) switch_state(D7ASP_STATE_SLAVE_PENDING_MASTER); - if (packet->payload_length > 0) + // check if a fragmentation session is ongoing + if (packet->d7atp_ctrl.ctrl_fragment) + { + assert(fragmentation_session.received_fragment_nb < MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT); + + // add fragment to buffer + fragmentation_session.fragment_indices[packet->d7atp_transaction_id] = fragmentation_session.fragment_buffer_tail_idx; + fragmentation_session.fragment_lengths[packet->d7atp_transaction_id] = packet->payload_length; + memcpy(fragmentation_session.fragments_buffer + fragmentation_session.fragment_buffer_tail_idx, packet->payload, packet->payload_length); + fragmentation_session.fragment_buffer_tail_idx += packet->payload_length + 1; + fragmentation_session.received_fragment_nb++; + + // check if fragmentation session is completed + if (fragmentation_session.received_fragment_nb == fragmentation_session.total_fragments_nb) + { + //re-assembly of the fragments + uint8_t payload[MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT * D7A_PAYLOAD_MAX_SIZE]; + uint16_t payload_length = 0; + for(uint8_t i = 0; i < fragmentation_session.total_fragments_nb; i++) + { + memcpy(payload + payload_length, + fragmentation_session.fragments_buffer + fragmentation_session.fragment_indices[i], + fragmentation_session.fragment_lengths[i]); + payload_length += fragmentation_session.fragment_lengths[i]; + } + d7ap_session_result_t result = { + .channel = { + .channel_header = packet->phy_config.rx.channel_id.channel_header_raw, + .center_freq_index = packet->phy_config.rx.channel_id.center_freq_index, + }, + .rx_level = - packet->hw_radio_packet.rx_meta.rssi, + .link_budget = (packet->dll_header.control_eirp_index - 32) - packet->hw_radio_packet.rx_meta.rssi, + .target_rx_level = 80, // TODO not implemented yet, use default for now + .status = { + .ucast = 0, // TODO + .nls = (packet->d7anp_ctrl.nls_method ? true : false), + .retry = false, // TODO + .missed = false, // TODO + }, + .response_to = packet->d7atp_tc, + .response_expected = packet->d7atp_ctrl.ctrl_is_ack_requested, + .addressee = *packet->d7anp_addressee, + .fifo_token = packet->d7atp_dialog_id, + .seqnr = packet->d7atp_transaction_id // the request ID is identified by the last fragment Id + }; + + expect_upper_layer_resp_payload = d7ap_stack_process_unsolicited_request(payload, payload_length, result); + } + } + else if (packet->payload_length > 0) { d7ap_session_result_t result = { .channel = { @@ -788,10 +928,10 @@ static void on_request_completed() // request completed, no retries needed so we can free the packet packet_queue_free_packet(current_request_packet); - // terminate the dialog if all request handled + // terminate the dialog if all request handled and if we are not in a fragmentation session // we need to switch to the state idle otherwise we may receive a new packet before the task flush_fifos is handled // in this case, we may assert since the state remains MASTER - if (current_request_id == current_master_session.next_request_id - 1) + if ((current_request_id == current_master_session.next_request_id - 1) && (!current_master_session.fragmentation)) { flush_completed(); return; @@ -814,6 +954,11 @@ void d7asp_signal_packet_transmitted(packet_t *packet) mark_current_request_done(); mark_current_request_successful(); } + else if (current_master_session.fragmentation) + { + // success bitmap is set when receiving the ACK_template from the node if ACK_REQ is set + mark_current_request_done(); + } } else if (d7asp_state == D7ASP_STATE_SLAVE || d7asp_state == D7ASP_STATE_SLAVE_PENDING_MASTER) { diff --git a/stack/modules/d7ap/d7asp.h b/stack/modules/d7ap/d7asp.h index 93b31bafe..28ae12e84 100644 --- a/stack/modules/d7ap/d7asp.h +++ b/stack/modules/d7ap/d7asp.h @@ -56,7 +56,7 @@ typedef struct d7asp_master_session d7asp_master_session_t; void d7asp_init(); void d7asp_stop(); -uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_config); +uint8_t d7asp_master_session_create(d7ap_session_config_t* d7asp_master_session_config, bool fragmentation); uint8_t d7asp_queue_request(uint8_t session_token, uint8_t* payload_buffer, uint8_t payload_length, uint8_t expected_response_length); diff --git a/stack/modules/d7ap/d7atp.c b/stack/modules/d7ap/d7atp.c index 49d2d8f64..aae83982c 100644 --- a/stack/modules/d7ap/d7atp.c +++ b/stack/modules/d7ap/d7atp.c @@ -23,6 +23,7 @@ #include #include "debug.h" +#include "bitmap.h" #include "hwdebug.h" #include "d7ap.h" #include "d7atp.h" @@ -70,10 +71,14 @@ static dae_access_profile_t NGDEF(_active_addressee_access_profile); static bool NGDEF(_stop_dialog_after_tx); #define stop_dialog_after_tx NG(_stop_dialog_after_tx) +static bool NGDEF(_terminate_transaction); +#define terminate_transaction NG(_terminate_transaction) + static timer_event d7atp_response_period_expired_timer; static timer_event d7atp_execution_delay_expired_timer; static bool ctrl_xoff; +static d7atp_ack_template_t recorded_ack_bitmap; typedef enum { D7ATP_STATE_STOPPED, @@ -137,6 +142,14 @@ static void execution_delay_timeout_handler() // After the Execution Delay period, the Requester engages in a DLL foreground scan for a duration of TC DPRINT("Execution Delay period is expired @%i", timer_get_counter_value()); + if (terminate_transaction) + { + current_transaction_id = NO_ACTIVE_REQUEST_ID; + d7asp_signal_transaction_terminated(); + terminate_transaction = false; + return; + } + d7anp_start_foreground_scan(); } @@ -149,6 +162,8 @@ static void terminate_dialog() current_transaction_id = NO_ACTIVE_REQUEST_ID; current_Tl_received = 0; stop_dialog_after_tx = false; + terminate_transaction = false; + memset(&recorded_ack_bitmap, 0, sizeof(d7atp_ack_template_t)); // Discard eventually the Tc timer timer_cancel_event(&d7atp_response_period_expired_timer); @@ -284,11 +299,14 @@ void d7atp_init() current_dialog_id = 0; current_Tl_received = 0; stop_dialog_after_tx = false; + terminate_transaction = false; timer_init_event(&d7atp_response_period_expired_timer, &response_period_timeout_handler); timer_init_event(&d7atp_execution_delay_expired_timer, &execution_delay_timeout_handler); d7ap_fs_register_file_modified_callback(D7A_FILE_SEL_CONF_FILE_ID, &sel_config_modified_callback); sel_config_modified_callback(D7A_FILE_SEL_CONF_FILE_ID); + + memset(&recorded_ack_bitmap, 0, sizeof(d7atp_ack_template_t)); } void d7atp_notify_access_profile_file_changed(uint8_t file_id) @@ -305,12 +323,10 @@ void d7atp_stop() } error_t d7atp_send_request(uint8_t dialog_id, uint8_t transaction_id, bool is_last_transaction, - packet_t* packet, d7ap_session_qos_t* qos_settings, uint8_t listen_timeout, uint8_t expected_response_length) + packet_t* packet, d7ap_session_qos_t* qos_settings, + uint8_t listen_timeout, uint8_t expected_response_length, + bool fragmentation, uint8_t total_fragments) { - // unused parameters - (void)is_last_transaction; - (void)listen_timeout; - /* check that we are not initiating a different dialog if a dialog is still ongoing */ if (current_dialog_id) { @@ -320,7 +336,8 @@ error_t d7atp_send_request(uint8_t dialog_id, uint8_t transaction_id, bool is_la if (d7atp_state != D7ATP_STATE_MASTER_TRANSACTION_REQUEST_PERIOD) switch_state(D7ATP_STATE_MASTER_TRANSACTION_REQUEST_PERIOD); - if ( packet->type == RETRY_REQUEST ) + // In case of fragmentation, request may be retried but after the end of the pool of requests + if ((packet->type == RETRY_REQUEST) && (!packet->d7atp_ctrl.ctrl_fragment)) { DPRINT("Retry the transmission with the same packet content"); current_transaction_id = transaction_id; @@ -346,6 +363,10 @@ error_t d7atp_send_request(uint8_t dialog_id, uint8_t transaction_id, bool is_la && expected_response_length == 0) ack_requested = false; + // ACK only requested for the last fragment + if ((ack_requested) && (fragmentation) && (!is_last_transaction)) + ack_requested = false; + // TODO based on what do we calculate Tc? payload length alone is not enough, depends on for example use of FEC, encryption .. // keep the same as transmission timeout for now @@ -355,12 +376,18 @@ error_t d7atp_send_request(uint8_t dialog_id, uint8_t transaction_id, bool is_la .ctrl_is_start = (packet->type == INITIAL_REQUEST) ? true : false, .ctrl_is_ack_requested = ack_requested, .ctrl_ack_not_void = qos_settings->qos_resp_mode == SESSION_RESP_MODE_ON_ERR? true : false, - .ctrl_te = false, + .ctrl_te = fragmentation, //Te is required in case of fragmentation .ctrl_agc = false, - .ctrl_ack_record = false, - .ctrl_tl = listen_timeout ? true : false + .ctrl_tl = listen_timeout ? true : false, + .ctrl_fragment = fragmentation }; + if (fragmentation) + { + packet->d7atp_fragments_number = total_fragments; + packet->d7atp_te = 100; //FIXME how to adjust this value? should come from upper layer + } + if (listen_timeout) packet->d7atp_tl = listen_timeout; @@ -399,8 +426,23 @@ error_t d7atp_send_response(packet_t* packet) d7atp_ctrl_t* d7atp = &(packet->d7atp_ctrl); // leave ctrl_is_ack_requested as is, keep the requester value - d7atp->ctrl_ack_not_void = false; // TODO - d7atp->ctrl_ack_record = false; // TODO validate + d7atp->ctrl_ack_not_void = false; + d7atp->ctrl_tl = false; + d7atp->ctrl_te = false; + + if (d7atp->ctrl_fragment) // TODO valid also if ACK_RECORD bit is set + { + int8_t first_missing_fragment = bitmap_search(recorded_ack_bitmap.bitmap, false, packet->d7atp_fragments_number); + if (first_missing_fragment != -1) + { + d7atp->ctrl_ack_not_void = true; + packet->d7atp_ack_template.ack_transaction_id_start = first_missing_fragment; + packet->d7atp_ack_template.ack_transaction_id_stop = current_transaction_id; + } + + // fragment flag is not set in the response + d7atp->ctrl_fragment = false; + } bool should_include_origin_template = false; // we don't need to send origin ID, the requester will filter based on dialogID, but ... @@ -441,6 +483,13 @@ uint8_t d7atp_assemble_packet_header(packet_t* packet, uint8_t* data_ptr) (*data_ptr) = packet->d7atp_ctrl.ctrl_raw; data_ptr++; (*data_ptr) = packet->d7atp_dialog_id; data_ptr++; (*data_ptr) = packet->d7atp_transaction_id; data_ptr++; + + // add the fragment total number only if it is a request + if ((packet->d7atp_ctrl.ctrl_fragment) && (d7atp_state == D7ATP_STATE_MASTER_TRANSACTION_REQUEST_PERIOD)) { + (*data_ptr) = packet->d7atp_fragments_number; + data_ptr++; + } + if (packet->d7atp_ctrl.ctrl_agc) { (*data_ptr) = packet->d7atp_target_rx_level_i; data_ptr++; @@ -467,9 +516,13 @@ uint8_t d7atp_assemble_packet_header(packet_t* packet, uint8_t* data_ptr) if (packet->d7atp_ctrl.ctrl_is_ack_requested && packet->d7atp_ctrl.ctrl_ack_not_void) { // add Responder ACK template - (*data_ptr) = packet->d7atp_transaction_id; data_ptr++; // transaction ID start - (*data_ptr) = packet->d7atp_transaction_id; data_ptr++; // transaction ID stop - // TODO ACK bitmap, support for multiple segments to ack not implemented yet + (*data_ptr) = packet->d7atp_ack_template.ack_transaction_id_start; data_ptr++; // transaction ID start + (*data_ptr) = packet->d7atp_ack_template.ack_transaction_id_stop; data_ptr++; // transaction ID stop + + //FIXME send compressed ACK_BITMAP + // for now, we send the entire BITMAP since the ACK_WIN is limited + memcpy(data_ptr, recorded_ack_bitmap.bitmap, ACK_BITMAP_BYTE_COUNT); + data_ptr += ACK_BITMAP_BYTE_COUNT; } return data_ptr - d7atp_header_start; @@ -480,6 +533,12 @@ bool d7atp_disassemble_packet_header(packet_t *packet, uint8_t *data_idx) packet->d7atp_ctrl.ctrl_raw = packet->hw_radio_packet.data[(*data_idx)]; (*data_idx)++; packet->d7atp_dialog_id = packet->hw_radio_packet.data[(*data_idx)]; (*data_idx)++; packet->d7atp_transaction_id = packet->hw_radio_packet.data[(*data_idx)]; (*data_idx)++; + + if (packet->d7atp_ctrl.ctrl_fragment) { + packet->d7atp_fragments_number = packet->hw_radio_packet.data[(*data_idx)]; + (*data_idx)++; + } + if (packet->d7atp_ctrl.ctrl_agc) { packet->d7atp_target_rx_level_i = packet->hw_radio_packet.data[(*data_idx)]; (*data_idx)++; @@ -508,7 +567,14 @@ bool d7atp_disassemble_packet_header(packet_t *packet, uint8_t *data_idx) { packet->d7atp_ack_template.ack_transaction_id_start = packet->hw_radio_packet.data[(*data_idx)]; (*data_idx)++; packet->d7atp_ack_template.ack_transaction_id_stop = packet->hw_radio_packet.data[(*data_idx)]; (*data_idx)++; - // TODO ACK bitmap, support for multiple segments to ack not implemented yet + + //FIXME receive compressed ACK_BITMAP + // for now, we send the entire BITMAP since the ACK_WIN is limited + //uint8_t bitmap_indexes = (packet->d7atp_ack_template.ack_transaction_id_stop -packet->d7atp_ack_template.ack_transaction_id_start); + //uint8_t bitmap_len = bitmap_indexes/8 + (bitmap_indexes%8 ? 1 : 0); + + memcpy(packet->d7atp_ack_template.bitmap, packet->hw_radio_packet.data + (*data_idx), ACK_BITMAP_BYTE_COUNT); + (*data_idx) += ACK_BITMAP_BYTE_COUNT; } return true; @@ -550,6 +616,19 @@ void d7atp_signal_packet_transmitted(packet_t* packet) } else { + // Wait the execution delay before terminating the transaction and flushing the next fragment + if ((packet->d7atp_ctrl.ctrl_fragment) && (packet->d7atp_ctrl.ctrl_te)) + { + timer_tick_t Te = adjust_timeout_value(CT_DECOMPRESS(packet->d7atp_te), packet->hw_radio_packet.tx_meta.timestamp); + if (Te) + { + d7atp_execution_delay_expired_timer.next_event = Te; + timer_add_event(&d7atp_execution_delay_expired_timer); + terminate_transaction = true; + return; + } + } + current_transaction_id = NO_ACTIVE_REQUEST_ID; d7asp_signal_transaction_terminated(); } @@ -593,6 +672,7 @@ void d7atp_process_received_packet(packet_t* packet) timer_tick_t Tc = 0; assert(d7atp_state == D7ATP_STATE_MASTER_TRANSACTION_RESPONSE_PERIOD + || d7atp_state == D7ATP_STATE_SLAVE_TRANSACTION_RECEIVED_REQUEST || d7atp_state == D7ATP_STATE_SLAVE_TRANSACTION_RESPONSE_PERIOD || d7atp_state == D7ATP_STATE_IDLE); // IDLE: when doing channel scanning outside of transaction @@ -662,10 +742,20 @@ void d7atp_process_received_packet(packet_t* packet) // When not participating in a Dialog if ((!current_dialog_id) && (!packet->d7atp_ctrl.ctrl_is_start)) { - //Responders discard segments marked with START flag set to 0 until they receive a segment with START flag set to 1 - DPRINT("Filtered frame with START cleared"); - packet_queue_free_packet(packet); - return; + // check if Frame is part of a fragmented transmission but not the first part. + if (packet->d7atp_ctrl.ctrl_fragment) + { + DPRINT("Start dialog with fragments but we may have probably already lost some fragments. Expect %d fragments", packet->d7atp_fragments_number); + // set the Transaction ID of the first non-received segment of the Dialog + recorded_ack_bitmap.ack_transaction_id_start = 0; // assuming that the dialog starts with transaction_id equal zero + } + else + { + //Responders discard segments marked with START flag set to 0 until they receive a segment with START flag set to 1 + DPRINT("Filtered frame with START cleared"); + packet_queue_free_packet(packet); + return; + } } // The FG scan is only started when the response period expires. @@ -712,11 +802,20 @@ void d7atp_process_received_packet(packet_t* packet) } } - switch_state(D7ATP_STATE_SLAVE_TRANSACTION_RECEIVED_REQUEST); + if (d7atp_state == D7ATP_STATE_IDLE || d7atp_state == D7ATP_STATE_SLAVE_TRANSACTION_RESPONSE_PERIOD) + switch_state(D7ATP_STATE_SLAVE_TRANSACTION_RECEIVED_REQUEST); + + if ((packet->d7atp_ctrl.ctrl_fragment) && (packet->d7atp_ctrl.ctrl_is_start)) + { + DPRINT("Start dialog containing fragments. Expect %d fragments", packet->d7atp_fragments_number); + } current_dialog_id = packet->d7atp_dialog_id; current_transaction_id = packet->d7atp_transaction_id; + // received segment is marked with 1 in the ack_bitmap + bitmap_set(recorded_ack_bitmap.bitmap, current_transaction_id); + // store the received timestamp for later usage (eg CCA). the rx_meta.timestamp can be // overwritten since it is stored in a union with tx_meta and can thus be changed when // trying to transmit diff --git a/stack/modules/d7ap/d7atp.h b/stack/modules/d7ap/d7atp.h index 53ad390f9..b1380ee97 100644 --- a/stack/modules/d7ap/d7atp.h +++ b/stack/modules/d7ap/d7atp.h @@ -35,8 +35,11 @@ #include "stdint.h" #include "stdbool.h" +#include "MODULE_D7AP_defs.h" #include "d7ap.h" +#define ACK_BITMAP_BYTE_COUNT (MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT/8) + (MODULE_D7AP_FIFO_MAX_REQUESTS_COUNT%8 ? 1 : 0) + typedef struct packet packet_t; /*! \brief The D7ATP CTRL header @@ -50,7 +53,7 @@ typedef struct { uint8_t ctrl_raw; struct { uint8_t ctrl_agc : 1; - bool ctrl_ack_record : 1; + bool ctrl_fragment : 1; bool ctrl_ack_not_void : 1; bool ctrl_is_ack_requested : 1; bool ctrl_te : 1; @@ -76,15 +79,17 @@ typedef struct { } d7a_segment_filter_options_t; typedef struct { - uint8_t ack_transaction_id_start; - uint8_t ack_transaction_id_stop; - // TODO ACK bitmap + uint8_t ack_transaction_id_start; // Transaction ID of the first non-received segment of the Dialog + uint8_t ack_transaction_id_stop; // Transaction ID of the last received segment of the Dialog + uint8_t bitmap[ACK_BITMAP_BYTE_COUNT]; } d7atp_ack_template_t; void d7atp_init(); void d7atp_stop(); error_t d7atp_send_request(uint8_t dialog_id, uint8_t transaction_id, bool is_last_transaction, - packet_t* packet, d7ap_session_qos_t* qos_settings, uint8_t listen_timeout, uint8_t expected_response_length); + packet_t* packet, d7ap_session_qos_t* qos_settings, + uint8_t listen_timeout, uint8_t expected_response_length, + bool fragmentation, uint8_t total_fragments); error_t d7atp_send_response(packet_t* packet); uint8_t d7atp_assemble_packet_header(packet_t* packet, uint8_t* data_ptr); bool d7atp_disassemble_packet_header(packet_t* packet, uint8_t* data_idx); diff --git a/stack/modules/d7ap/packet.h b/stack/modules/d7ap/packet.h index 87b7ba0c4..9675bbcdf 100644 --- a/stack/modules/d7ap/packet.h +++ b/stack/modules/d7ap/packet.h @@ -30,6 +30,7 @@ #include "stdint.h" #include "d7atp.h" #include "dll.h" +#include "d7ap.h" #include "d7anp.h" #include "phy.h" #include "hwradio.h" @@ -59,6 +60,7 @@ struct packet d7atp_ack_template_t d7atp_ack_template; uint8_t d7atp_dialog_id; uint8_t d7atp_transaction_id; + uint8_t d7atp_fragments_number; uint8_t d7atp_tc; uint8_t d7atp_tl; uint8_t d7atp_te; @@ -66,9 +68,8 @@ struct packet packet_type type; uint16_t ETA; uint16_t tx_duration; - // TODO d7atp ack template uint8_t payload_length; - uint8_t payload[239]; // TODO make max size configurable using cmake + uint8_t payload[D7A_PAYLOAD_MAX_SIZE]; // TODO make max size configurable using cmake // TODO store payload here or only pointer to file where we need to fetch it? can we assume data will not be changed in between phy_config_t phy_config; hw_radio_packet_t hw_radio_packet; // TODO we might not need all metadata included in hw_radio_packet_t. If not copy needed data fields From f52226d7101d9b6dee2caf2990cfa5430772ac47 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Fri, 12 Feb 2021 16:02:35 +0100 Subject: [PATCH 24/26] sensor_without_alp: fragmentation test --- .../sensor_without_alp/sensor_without_alp.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stack/apps/sensor_without_alp/sensor_without_alp.c b/stack/apps/sensor_without_alp/sensor_without_alp.c index c4a732cc8..ec0478636 100644 --- a/stack/apps/sensor_without_alp/sensor_without_alp.c +++ b/stack/apps/sensor_without_alp/sensor_without_alp.c @@ -71,7 +71,7 @@ static d7ap_session_config_t d7ap_session_config = (d7ap_session_config_t){ void on_receive(uint16_t trans_id, uint8_t* payload, uint8_t len, d7ap_session_result_t result); void on_transmitted(uint16_t trans_id, error_t error); -bool on_unsolicited_response(uint8_t* payload, uint8_t len, d7ap_session_result_t result); +bool on_unsolicited_response(uint8_t* payload, uint16_t len, d7ap_session_result_t result); d7ap_resource_desc_t callbacks = { .receive_cb = &on_receive, @@ -83,17 +83,17 @@ uint8_t d7_client_id; void execute_sensor_measurement() { - // first get the sensor reading ... - int16_t temperature = 0; // in decicelsius. When there is no sensor, we just transmit 0 degrees + int8_t metadata[1024]; -#if defined USE_HTS221 - HTS221_Get_Temperature(hts221_handle, &temperature); -#endif - - temperature = __builtin_bswap16(temperature); // convert to big endian before transmission + for (int i = 0, j = 0x30; i < 1024; i++) + { + metadata[i] = j++; + if (j == 0x3A) + j = 0x30; + } uint16_t trans_id; - d7ap_send(d7_client_id, &d7ap_session_config, (uint8_t*)&temperature, sizeof(temperature), 0, &trans_id); + d7ap_send(d7_client_id, &d7ap_session_config, metadata, sizeof(metadata), 0, &trans_id); } void on_receive(uint16_t trans_id, uint8_t* payload, uint8_t len, d7ap_session_result_t result) @@ -107,7 +107,7 @@ void on_transmitted(uint16_t trans_id, error_t error) timer_post_task_delay(&execute_sensor_measurement, SENSOR_INTERVAL_SEC); } -bool on_unsolicited_response(uint8_t* payload, uint8_t len, d7ap_session_result_t result) +bool on_unsolicited_response(uint8_t* payload, uint16_t len, d7ap_session_result_t result) { log_print_string("Unsolicited response received\n"); return false; From b6d53e42de458ba421549b5c31eec8195ea91c94 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 3 Mar 2021 11:48:18 +0100 Subject: [PATCH 25/26] crc: extend crc computation to larger payloads --- stack/framework/components/crc/crc.c | 2 +- stack/framework/inc/crc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stack/framework/components/crc/crc.c b/stack/framework/components/crc/crc.c index 5283a04aa..e9db088f1 100644 --- a/stack/framework/components/crc/crc.c +++ b/stack/framework/components/crc/crc.c @@ -38,7 +38,7 @@ static void update_crc(uint8_t x) crc = crc_new; } -uint16_t crc_calculate(uint8_t* data, uint8_t length) +uint16_t crc_calculate(uint8_t* data, uint16_t length) { crc = 0xffff; uint8_t i = 0; diff --git a/stack/framework/inc/crc.h b/stack/framework/inc/crc.h index 89112867d..feef25605 100644 --- a/stack/framework/inc/crc.h +++ b/stack/framework/inc/crc.h @@ -33,7 +33,7 @@ #include -uint16_t crc_calculate(uint8_t* data, uint8_t length); +uint16_t crc_calculate(uint8_t* data, uint16_t length); #endif /* CRC_H_ */ From 892b89717891d2631f69a62da9d7e13d4a5288b7 Mon Sep 17 00:00:00 2001 From: Philippe Nunes Date: Wed, 3 Mar 2021 11:51:22 +0100 Subject: [PATCH 26/26] modem_interface: extend length byte to handle larger payloads --- .../modem_interface/modem_interface.c | 29 ++++++++++--------- stack/framework/inc/modem_interface.h | 4 +-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/stack/framework/components/modem_interface/modem_interface.c b/stack/framework/components/modem_interface/modem_interface.c index 20d960c99..d1d6ad347 100644 --- a/stack/framework/components/modem_interface/modem_interface.c +++ b/stack/framework/components/modem_interface/modem_interface.c @@ -23,9 +23,9 @@ #include "log.h" -#define RX_BUFFER_SIZE 256 +#define RX_BUFFER_SIZE 512 -#define TX_FIFO_FLUSH_CHUNK_SIZE 10 // at a baudrate of 115200 this ensures completion within 1 ms +#define TX_FIFO_FLUSH_CHUNK_SIZE 20 // at a baudrate of 115200 this ensures completion within 1 ms // TODO baudrate dependent static uart_handle_t* uart; @@ -44,20 +44,21 @@ static fifo_t rx_fifo; #define SERIAL_FRAME_SYNC_BYTE 0xC0 #define SERIAL_FRAME_VERSION 0x00 -#define SERIAL_FRAME_HEADER_SIZE 7 -#define SERIAL_FRAME_SIZE 4 +#define SERIAL_FRAME_HEADER_SIZE 8 +#define SERIAL_FRAME_SIZE_MSB 4 +#define SERIAL_FRAME_SIZE_LSB 5 #define SERIAL_FRAME_COUNTER 2 #define SERIAL_FRAME_TYPE 3 -#define SERIAL_FRAME_CRC1 5 -#define SERIAL_FRAME_CRC2 6 +#define SERIAL_FRAME_CRC1 6 +#define SERIAL_FRAME_CRC2 7 -#define MODEM_INTERFACE_TX_FIFO_SIZE 255 +#define MODEM_INTERFACE_TX_FIFO_SIZE 512 static uint8_t modem_interface_tx_buffer[MODEM_INTERFACE_TX_FIFO_SIZE]; static fifo_t modem_interface_tx_fifo; static bool request_pending = false; uint8_t header[SERIAL_FRAME_HEADER_SIZE]; -static uint8_t payload_len = 0; +static uint16_t payload_len = 0; static uint8_t packet_up_counter = 0; static uint8_t packet_down_counter = 0; static pin_id_t uart_state_pin; @@ -269,8 +270,9 @@ static void execute_state_machine() */ static bool verify_payload(fifo_t* bytes, uint8_t* header) { + uint16_t payload_length = ((header[SERIAL_FRAME_SIZE_MSB] << 8) | header[SERIAL_FRAME_SIZE_LSB]); static uint8_t payload[RX_BUFFER_SIZE - SERIAL_FRAME_HEADER_SIZE]; // statically allocated so this does not end up on stack - fifo_peek(bytes, (uint8_t*) &payload, 0, header[SERIAL_FRAME_SIZE]); + fifo_peek(bytes, (uint8_t*) &payload, 0, payload_length); //check for missing packages packet_down_counter++; @@ -286,7 +288,7 @@ static bool verify_payload(fifo_t* bytes, uint8_t* header) DPRINT("RX PAYLOAD: "); DPRINT_DATA(payload, header[SERIAL_FRAME_SIZE]); - uint16_t calculated_crc = crc_calculate(payload, header[SERIAL_FRAME_SIZE]); + uint16_t calculated_crc = crc_calculate(payload, payload_length); if(header[SERIAL_FRAME_CRC1]!=((calculated_crc >> 8) & 0x00FF) || header[SERIAL_FRAME_CRC2]!=(calculated_crc & 0x00FF)) { @@ -352,7 +354,7 @@ static void process_rx_fifo(void *arg) } parsed_header = true; fifo_skip(&rx_fifo, SERIAL_FRAME_HEADER_SIZE); - payload_len = header[SERIAL_FRAME_SIZE]; + payload_len = ((header[SERIAL_FRAME_SIZE_MSB] << 8) | header[SERIAL_FRAME_SIZE_LSB]); DPRINT("UART RX, payload size = %i", payload_len); sched_post_task(&process_rx_fifo); } @@ -485,7 +487,7 @@ void modem_interface_init(uint8_t idx, uint32_t baudrate, pin_id_t uart_state_pi modem_interface_transfer_bytes(&reboot_reason, 1, SERIAL_MESSAGE_TYPE_REBOOTED); } -void modem_interface_transfer_bytes(uint8_t* bytes, uint8_t length, serial_message_type_t type) +void modem_interface_transfer_bytes(uint8_t* bytes, uint16_t length, serial_message_type_t type) { uint8_t header[SERIAL_FRAME_HEADER_SIZE]; uint16_t crc=crc_calculate(bytes,length); @@ -496,7 +498,8 @@ void modem_interface_transfer_bytes(uint8_t* bytes, uint8_t length, serial_messa header[SERIAL_FRAME_COUNTER] = packet_up_counter; header[SERIAL_FRAME_TYPE] = type; - header[SERIAL_FRAME_SIZE] = length; + header[SERIAL_FRAME_SIZE_MSB] = ((length & 0xFF00) >> 8); + header[SERIAL_FRAME_SIZE_LSB] = (length & 0x00FF); header[SERIAL_FRAME_CRC1] = (crc >> 8) & 0x00FF; header[SERIAL_FRAME_CRC2] = crc & 0x00FF; diff --git a/stack/framework/inc/modem_interface.h b/stack/framework/inc/modem_interface.h index 1ae5acaee..7410fb990 100644 --- a/stack/framework/inc/modem_interface.h +++ b/stack/framework/inc/modem_interface.h @@ -21,7 +21,7 @@ typedef void (*target_rebooted_callback_t)(system_reboot_reason_t reboot_reason) /* ---------------HEADER(bytes)--------------------- -|sync|sync|counter|message type|length|crc1|crc2| +|sync|sync|counter|message type|length_msb|length_lsb|crc1|crc2| ------------------------------------------------- */ @@ -41,7 +41,7 @@ void modem_interface_init(uint8_t idx, uint32_t baudrate, pin_id_t uart_state_pi * @param type type of message (SERIAL_MESSAGE_TYPE_ALP, SERIAL_MESSAGE_TYPE_PING_REQUEST, SERIAL_MESSAGE_TYPE_LOGGING, ...) * @return Void. */ -void modem_interface_transfer_bytes(uint8_t* bytes, uint8_t length, serial_message_type_t type); +void modem_interface_transfer_bytes(uint8_t* bytes, uint16_t length, serial_message_type_t type); /** @brief Transmits a string by adding a header and putting it in the UART fifo * @param string Bytes that need to be transmitted * @return Void.