From 9c5082cd9eecfe1a14eea163a565204c5f66f5fa Mon Sep 17 00:00:00 2001 From: mahmamdouh Date: Mon, 2 Feb 2026 00:37:51 +0100 Subject: [PATCH] software analysis --- .../Implementation_Testing_Plan.md | 700 ++++++++ .../Gap_analysis/Readiness_Action_Plan.md | 387 ++++ .../Software_Design_Gap_Analysis.md | 621 +++++++ .../System_Design_Gap_Analysis.md | 486 +++++ .../System_Software_Traceability_Analysis.md | 498 ++++++ .../Global_Software_Architecture.md | 866 --------- draft- to be removed SW/SRS.md | 515 ------ draft- to be removed SW/SW design.md | 336 ---- .../Software_Requirements_Traceability.md | 195 -- .../System_Documentation_Validation_Report.md | 385 ---- .../Traceability_Matrix.md | 395 ----- .../components/ARCHITECTURE.md | 548 ------ .../components/ESP_IDF_FW_wrappers/README.md | 346 ---- .../ESP_IDF_FW_wrappers/adc/CMakeLists.txt | 5 - .../ESP_IDF_FW_wrappers/adc/README.md | 276 --- .../ESP_IDF_FW_wrappers/adc/com/adc.cpp | 363 ---- .../ESP_IDF_FW_wrappers/adc/com/adc.hpp | 261 --- .../ESP_IDF_FW_wrappers/adc/logging_data.csv | 28 - .../adc/test/adc_init_test.py | 34 - .../adc/test/adc_init_test.test_scenario.xml | 14 - .../ESP_IDF_FW_wrappers/adc/test/test_adc.cpp | 69 - .../ESP_IDF_FW_wrappers/bt/CMakeLists.txt | 5 - .../ESP_IDF_FW_wrappers/bt/README.md | 502 ------ .../ESP_IDF_FW_wrappers/bt/com/bt.cpp | 621 ------- .../ESP_IDF_FW_wrappers/bt/com/bt.hpp | 457 ----- .../ESP_IDF_FW_wrappers/bt/logging_data.csv | 55 - .../bt/test/bt_init_test.py | 34 - .../ESP_IDF_FW_wrappers/bt/test/test_bt.cpp | 39 - .../ESP_IDF_FW_wrappers/dma/CMakeLists.txt | 5 - .../ESP_IDF_FW_wrappers/dma/README.md | 396 ----- .../ESP_IDF_FW_wrappers/dma/com/dma.cpp | 512 ------ .../ESP_IDF_FW_wrappers/dma/com/dma.hpp | 386 ---- .../ESP_IDF_FW_wrappers/dma/logging_data.csv | 46 - .../dma/test/dma_init_test.py | 34 - .../dma/test/dma_init_test.test_scenario.xml | 14 - .../ESP_IDF_FW_wrappers/dma/test/test_dma.cpp | 31 - .../ESP_IDF_FW_wrappers/gpio/CMakeLists.txt | 5 - .../ESP_IDF_FW_wrappers/gpio/README.md | 154 -- .../ESP_IDF_FW_wrappers/gpio/com/gpio.cpp | 271 --- .../ESP_IDF_FW_wrappers/gpio/com/gpio.hpp | 173 -- .../ESP_IDF_FW_wrappers/gpio/logging_data.csv | 21 - .../gpio/test/gpio_init_test.py | 34 - .../test/gpio_init_test.test_scenario.xml | 14 - .../gpio/test/test_gpio.cpp | 65 - .../ESP_IDF_FW_wrappers/i2c/CMakeLists.txt | 6 - .../ESP_IDF_FW_wrappers/i2c/README.md | 216 --- .../ESP_IDF_FW_wrappers/i2c/com/i2c.cpp | 273 --- .../ESP_IDF_FW_wrappers/i2c/com/i2c.hpp | 183 -- .../ESP_IDF_FW_wrappers/i2c/logging_data.csv | 24 - .../i2c/test/i2c_init_test.py | 34 - .../i2c/test/i2c_init_test.test_scenario.xml | 14 - .../ESP_IDF_FW_wrappers/i2c/test/test_i2c.cpp | 47 - .../ESP_IDF_FW_wrappers/spi/CMakeLists.txt | 5 - .../ESP_IDF_FW_wrappers/spi/README.md | 279 --- .../ESP_IDF_FW_wrappers/spi/com/spi.cpp | 282 --- .../ESP_IDF_FW_wrappers/spi/com/spi.hpp | 212 --- .../ESP_IDF_FW_wrappers/spi/logging_data.csv | 21 - .../spi/test/spi_init_test.py | 34 - .../spi/test/spi_init_test.test_scenario.xml | 14 - .../ESP_IDF_FW_wrappers/spi/test/test_spi.cpp | 31 - .../ESP_IDF_FW_wrappers/uart/CMakeLists.txt | 5 - .../ESP_IDF_FW_wrappers/uart/README.md | 222 --- .../ESP_IDF_FW_wrappers/uart/com/uart.cpp | 293 --- .../ESP_IDF_FW_wrappers/uart/com/uart.hpp | 220 --- .../ESP_IDF_FW_wrappers/uart/logging_data.csv | 27 - .../uart/test/test_uart.cpp | 31 - .../uart/test/uart_init_test.py | 34 - .../test/uart_init_test.test_scenario.xml | 14 - .../ESP_IDF_FW_wrappers/wifi/CMakeLists.txt | 5 - .../ESP_IDF_FW_wrappers/wifi/README.md | 323 ---- .../ESP_IDF_FW_wrappers/wifi/com/wifi.cpp | 501 ------ .../ESP_IDF_FW_wrappers/wifi/com/wifi.hpp | 306 ---- .../ESP_IDF_FW_wrappers/wifi/logging_data.csv | 38 - .../wifi/test/test_wifi.cpp | 42 - .../wifi/test/wifi_init_test.py | 34 - .../test/wifi_init_test.test_scenario.xml | 14 - .../DP_stack/data_pool/CMakeLists.txt | 5 - .../DP_stack/data_pool/COMPONENT_SPEC.md | 667 ------- .../DP_stack/data_pool/com/data_pool.cpp | 47 - .../DP_stack/data_pool/com/data_pool.hpp | 33 - .../DP_stack/data_pool/logging_data.csv | 2 - .../data_pool/test/data_pool_init_test.py | 34 - .../data_pool_init_test.test_scenario.xml | 14 - .../data_pool/test/test_data_pool.cpp | 40 - .../DP_stack/persistence/CMakeLists.txt | 5 - .../DP_stack/persistence/COMPONENT_SPEC.md | 257 --- .../DP_stack/persistence/com/persistence.cpp | 47 - .../DP_stack/persistence/com/persistence.hpp | 33 - .../DP_stack/persistence/logging_data.csv | 2 - .../persistence/test/persistence_init_test.py | 34 - .../persistence_init_test.test_scenario.xml | 14 - .../persistence/test/test_persistence.cpp | 40 - .../business_stack/STM/CMakeLists.txt | 5 - .../business_stack/STM/COMPONENT_SPEC.md | 291 --- .../business_stack/STM/com/stm.cpp | 47 - .../business_stack/STM/com/stm.hpp | 33 - .../business_stack/STM/logging_data.csv | 2 - .../business_stack/STM/test/stm_init_test.py | 34 - .../STM/test/stm_init_test.test_scenario.xml | 14 - .../business_stack/STM/test/test_stm.cpp | 40 - .../actuator_manager/CMakeLists.txt | 5 - .../actuator_manager/com/actuator_manager.cpp | 46 - .../actuator_manager/com/actuator_manager.hpp | 33 - .../actuator_manager/logging_data.csv | 2 - .../robot_keywords.cpython-313.pyc | Bin 2637 -> 0 bytes .../test/actuator_manager_init_test.py | 34 - ...tuator_manager_init_test.test_scenario.xml | 12 - .../test/actuator_manager_init_test2.py | 56 - .../test/test_actuator_manager.cpp | 40 - .../event_system/CMakeLists.txt | 5 - .../event_system/COMPONENT_SPEC.md | 200 --- .../event_system/com/event_system.cpp | 46 - .../event_system/com/event_system.hpp | 33 - .../event_system/logging_data.csv | 2 - .../test/event_system_init_test.py | 34 - .../event_system_init_test.test_scenario.xml | 14 - .../event_system/test/test_event_system.cpp | 40 - .../business_stack/fw_upgrader/CMakeLists.txt | 5 - .../fw_upgrader/com/fw_upgrader.cpp | 47 - .../fw_upgrader/com/fw_upgrader.hpp | 33 - .../fw_upgrader/logging_data.csv | 2 - .../fw_upgrader/test/fw_upgrader_init_test.py | 44 - .../fw_upgrader_init_test.test_scenario.xml | 14 - .../fw_upgrader/test/test_fw_upgrader.cpp | 40 - .../machine_constant_manager/CMakeLists.txt | 5 - .../com/machine_constant_manager.cpp | 47 - .../com/machine_constant_manager.hpp | 33 - .../machine_constant_manager/logging_data.csv | 2 - .../machine_constant_manager_init_test.py | 34 - ...nstant_manager_init_test.test_scenario.xml | 14 - .../test/test_machine_constant_manager.cpp | 40 - .../main_hub_apis/CMakeLists.txt | 5 - .../main_hub_apis/com/main_hub_apis.cpp | 47 - .../main_hub_apis/com/main_hub_apis.hpp | 33 - .../main_hub_apis/logging_data.csv | 2 - .../test/main_hub_apis_init_test.py | 34 - .../main_hub_apis_init_test.test_scenario.xml | 14 - .../main_hub_apis/test/test_main_hub_apis.cpp | 40 - .../sensor_manager/CMakeLists.txt | 5 - .../sensor_manager/COMPONENT_SPEC.md | 652 ------- .../sensor_manager/com/sensor_manager.cpp | 47 - .../sensor_manager/com/sensor_manager.hpp | 33 - .../sensor_manager/logging_data.csv | 2 - .../test/sensor_manager_init_test.py | 34 - ...sensor_manager_init_test.test_scenario.xml | 14 - .../test/test_sensor_manager.cpp | 40 - .../diag_task/CMakeLists.txt | 5 - .../diag_task/com/diag_task.cpp | 47 - .../diag_task/com/diag_task.hpp | 33 - .../diag_task/logging_data.csv | 2 - .../diag_task/test/diag_task_init_test.py | 34 - .../diag_task_init_test.test_scenario.xml | 14 - .../diag_task/test/test_diag_task.cpp | 40 - .../error_handler/CMakeLists.txt | 5 - .../error_handler/com/error_handler.cpp | 47 - .../error_handler/com/error_handler.hpp | 33 - .../error_handler/logging_data.csv | 2 - .../test/error_handler_init_test.py | 34 - .../error_handler_init_test.test_scenario.xml | 14 - .../error_handler/test/test_error_handler.cpp | 40 - draft- to be removed SW/components/arch.md | 413 ----- .../components/drivers/SDcard/CMakeLists.txt | 5 - .../drivers/SDcard/SD-1.3.0/LICENSE.txt | 674 ------- .../drivers/SDcard/SD-1.3.0/README.adoc | 13 - .../drivers/SDcard/SD-1.3.0/docs/api.md | 894 ---------- .../drivers/SDcard/SD-1.3.0/docs/readme.md | 23 - .../SD-1.3.0/examples/CardInfo/CardInfo.ino | 118 -- .../examples/Datalogger/Datalogger.ino | 79 - .../SD-1.3.0/examples/DumpFile/DumpFile.ino | 65 - .../SDcard/SD-1.3.0/examples/Files/Files.ino | 76 - .../NonBlockingWrite/NonBlockingWrite.ino | 118 -- .../SD-1.3.0/examples/ReadWrite/ReadWrite.ino | 80 - .../SD-1.3.0/examples/listfiles/listfiles.ino | 86 - .../drivers/SDcard/SD-1.3.0/keywords.txt | 31 - .../SDcard/SD-1.3.0/library.properties | 9 - .../drivers/SDcard/SD-1.3.0/src/File.cpp | 168 -- .../drivers/SDcard/SD-1.3.0/src/README.txt | 13 - .../drivers/SDcard/SD-1.3.0/src/SD.cpp | 639 ------- .../drivers/SDcard/SD-1.3.0/src/SD.h | 138 -- .../SDcard/SD-1.3.0/src/utility/FatStructs.h | 418 ----- .../SDcard/SD-1.3.0/src/utility/Sd2Card.cpp | 777 -------- .../SDcard/SD-1.3.0/src/utility/Sd2Card.h | 273 --- .../SDcard/SD-1.3.0/src/utility/Sd2PinMap.h | 528 ------ .../SDcard/SD-1.3.0/src/utility/SdFat.h | 641 ------- .../SDcard/SD-1.3.0/src/utility/SdFatUtil.h | 77 - .../SD-1.3.0/src/utility/SdFatmainpage.h | 202 --- .../SDcard/SD-1.3.0/src/utility/SdFile.cpp | 1527 ---------------- .../SDcard/SD-1.3.0/src/utility/SdInfo.h | 232 --- .../SDcard/SD-1.3.0/src/utility/SdVolume.cpp | 351 ---- .../components/drivers/SDcard/com/sdcard.cpp | 1563 ----------------- .../components/drivers/SDcard/com/sdcard.hpp | 161 -- .../drivers/SDcard/logging_data.csv | 2 - .../drivers/SDcard/test/sdcard_init_test.py | 34 - .../test/sdcard_init_test.test_scenario.xml | 14 - .../drivers/SDcard/test/test_sdcard.cpp | 31 - .../diag_protocol_stack/CMakeLists.txt | 5 - .../com/diag_protocol_stack.cpp | 47 - .../com/diag_protocol_stack.hpp | 33 - .../diag_protocol_stack/logging_data.csv | 2 - .../test/diag_protocol_stack_init_test.py | 34 - ...protocol_stack_init_test.test_scenario.xml | 14 - .../test/test_diag_protocol_stack.cpp | 40 - .../drivers/network_stack/CMakeLists.txt | 5 - .../network_stack/com/network_stack.cpp | 47 - .../network_stack/com/network_stack.hpp | 33 - .../drivers/network_stack/logging_data.csv | 2 - .../test/network_stack_init_test.py | 34 - .../network_stack_init_test.test_scenario.xml | 14 - .../network_stack/test/test_network_stack.cpp | 40 - .../components/drivers/nvm/CMakeLists.txt | 5 - .../components/drivers/nvm/com/nvm.cpp | 87 - .../components/drivers/nvm/com/nvm.hpp | 49 - .../components/drivers/nvm/logging_data.csv | 2 - .../drivers/nvm/test/nvm_init_test.py | 34 - .../nvm/test/nvm_init_test.test_scenario.xml | 14 - .../components/drivers/nvm/test/test_nvm.cpp | 47 - .../drivers/sensors/ammonia/CMakeLists.txt | 5 - .../drivers/sensors/ammonia/com/ammonia.cpp | 47 - .../drivers/sensors/ammonia/com/ammonia.hpp | 33 - .../drivers/sensors/ammonia/logging_data.csv | 2 - .../sensors/ammonia/test/ammonia_init_test.py | 34 - .../test/ammonia_init_test.test_scenario.xml | 14 - .../sensors/ammonia/test/test_ammonia.cpp | 40 - .../drivers/sensors/co2/CMakeLists.txt | 5 - .../drivers/sensors/co2/com/co2.cpp | 47 - .../drivers/sensors/co2/com/co2.hpp | 33 - .../drivers/sensors/co2/logging_data.csv | 2 - .../drivers/sensors/co2/test/co2_init_test.py | 34 - .../co2/test/co2_init_test.test_scenario.xml | 14 - .../drivers/sensors/co2/test/test_co2.cpp | 40 - .../drivers/sensors/humidity/CMakeLists.txt | 5 - .../drivers/sensors/humidity/com/humidity.cpp | 47 - .../drivers/sensors/humidity/com/humidity.hpp | 33 - .../drivers/sensors/humidity/logging_data.csv | 2 - .../humidity/test/humidity_init_test.py | 34 - .../test/humidity_init_test.test_scenario.xml | 14 - .../sensors/humidity/test/test_humidity.cpp | 40 - .../drivers/sensors/light/CMakeLists.txt | 5 - .../drivers/sensors/light/com/light.cpp | 47 - .../drivers/sensors/light/com/light.hpp | 33 - .../drivers/sensors/light/logging_data.csv | 2 - .../sensors/light/test/light_init_test.py | 34 - .../test/light_init_test.test_scenario.xml | 14 - .../drivers/sensors/light/test/test_light.cpp | 40 - .../drivers/sensors/temprature/CMakeLists.txt | 5 - .../sensors/temprature/com/temprature.cpp | 47 - .../sensors/temprature/com/temprature.hpp | 33 - .../sensors/temprature/logging_data.csv | 2 - .../temprature/test/temprature_init_test.py | 34 - .../temprature_init_test.test_scenario.xml | 14 - .../temprature/test/test_temprature.cpp | 40 - .../drivers/sensors/voc/CMakeLists.txt | 5 - .../drivers/sensors/voc/com/voc.cpp | 47 - .../drivers/sensors/voc/com/voc.hpp | 33 - .../drivers/sensors/voc/logging_data.csv | 2 - .../drivers/sensors/voc/test/test_voc.cpp | 40 - .../drivers/sensors/voc/test/voc_init_test.py | 34 - .../voc/test/voc_init_test.test_scenario.xml | 14 - .../components/os/swtimer/CMakeLists.txt | 4 - .../components/os/swtimer/com/swtimer.cpp | 81 - .../components/os/swtimer/com/swtimer.hpp | 95 - .../os/swtimer/test/test_swtimer.cpp | 108 -- .../components/os/task/CMakeLists.txt | 4 - .../components/os/task/com/task.cpp | 111 -- .../components/os/task/com/task.hpp | 134 -- .../components/os/task/test/test_task.cpp | 114 -- .../components/perf_tests/CMakeLists.txt | 23 - .../ESP32_Performance_Tests_Documentation.md | 708 -------- .../components/perf_tests/Kconfig | 26 - .../components/perf_tests/test/perf_tests.cpp | 574 ------ .../__pycache__/scan_serial.cpython-313.pyc | Bin 5757 -> 0 bytes .../components/system_tests/scan_serial.py | 109 -- .../components/system_tests/smoke_test_hil.py | 45 - .../system_tests/smoke_test_simulator.py | 45 - .../components/utils/logger/ARCHITECTURE.md | 601 ------- .../components/utils/logger/CMakeLists.txt | 5 - .../components/utils/logger/DIAGRAMS.md | 689 -------- .../components/utils/logger/README.md | 431 ----- .../components/utils/logger/USAGE_GUIDE.md | 630 ------- .../components/utils/logger/com/logger.cpp | 366 ---- .../components/utils/logger/com/logger.hpp | 226 --- .../logger/example/gpio_wrapper_example.cpp | 355 ---- .../utils/logger/test/CMakeLists.txt | 5 - .../utils/logger/test/test_logger.cpp | 292 --- .../utils/time_utils/CMakeLists.txt | 5 - .../utils/time_utils/com/time_utils.cpp | 44 - .../utils/time_utils/com/time_utils.hpp | 25 - .../features/F-COM_Communication.md | 561 ------ .../features/F-DAQ_Sensor_Data_Acquisition.md | 445 ----- .../features/F-DATA_Persistence_Management.md | 0 .../features/F-DIAG_Diagnostics_Health.md | 581 ------ .../F-DQC_Data_Quality_Calibration.md | 528 ------ .../features/F-HW_Hardware_Abstraction.md | 650 ------- .../features/F-OTA_Firmware_Update.md | 749 -------- .../features/F-PWR_Power_Fault_Handling.md | 586 ------ .../features/F-SEC_Security_Safety.md | 693 -------- .../features/F-SYS_System_Management.md | 640 ------- draft- to be removed SW/features/README.md | 89 - 298 files changed, 2692 insertions(+), 39836 deletions(-) create mode 100644 1 software design/Gap_analysis/Implementation_Testing_Plan.md create mode 100644 1 software design/Gap_analysis/Readiness_Action_Plan.md create mode 100644 1 software design/Gap_analysis/Software_Design_Gap_Analysis.md create mode 100644 1 software design/Gap_analysis/System_Design_Gap_Analysis.md create mode 100644 1 software design/Gap_analysis/System_Software_Traceability_Analysis.md delete mode 100644 draft- to be removed SW/Global_Software_Architecture.md delete mode 100644 draft- to be removed SW/SRS.md delete mode 100644 draft- to be removed SW/SW design.md delete mode 100644 draft- to be removed SW/Software_Requirements_Traceability.md delete mode 100644 draft- to be removed SW/System_Documentation_Validation_Report.md delete mode 100644 draft- to be removed SW/Traceability_Matrix.md delete mode 100644 draft- to be removed SW/components/ARCHITECTURE.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/test_adc.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/bt_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/test_bt.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/test_dma.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/test_gpio.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/test_i2c.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/test_spi.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/test_uart.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/README.md delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.hpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/logging_data.csv delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/test_wifi.cpp delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.py delete mode 100644 draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/COMPONENT_SPEC.md delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.cpp delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.hpp delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/test_data_pool.cpp delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/COMPONENT_SPEC.md delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.cpp delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.hpp delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/DP_stack/persistence/test/test_persistence.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/COMPONENT_SPEC.md delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.hpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/STM/test/test_stm.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.hpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/__pycache__/robot_keywords.cpython-313.pyc delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test2.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/test_actuator_manager.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.hpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/event_system/test/test_event_system.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.hpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/test_fw_upgrader.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.hpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/test_machine_constant_manager.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.hpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/test_main_hub_apis.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/COMPONENT_SPEC.md delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.cpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.hpp delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/test_sensor_manager.cpp delete mode 100644 draft- to be removed SW/components/application_layer/diag_task/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/diag_task/com/diag_task.cpp delete mode 100644 draft- to be removed SW/components/application_layer/diag_task/com/diag_task.hpp delete mode 100644 draft- to be removed SW/components/application_layer/diag_task/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/diag_task/test/test_diag_task.cpp delete mode 100644 draft- to be removed SW/components/application_layer/error_handler/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/application_layer/error_handler/com/error_handler.cpp delete mode 100644 draft- to be removed SW/components/application_layer/error_handler/com/error_handler.hpp delete mode 100644 draft- to be removed SW/components/application_layer/error_handler/logging_data.csv delete mode 100644 draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.py delete mode 100644 draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/application_layer/error_handler/test/test_error_handler.cpp delete mode 100644 draft- to be removed SW/components/arch.md delete mode 100644 draft- to be removed SW/components/drivers/SDcard/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/LICENSE.txt delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/README.adoc delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/api.md delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/readme.md delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/CardInfo/CardInfo.ino delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Datalogger/Datalogger.ino delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/DumpFile/DumpFile.ino delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Files/Files.ino delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/NonBlockingWrite/NonBlockingWrite.ino delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/ReadWrite/ReadWrite.ino delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/listfiles/listfiles.ino delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/keywords.txt delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/library.properties delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/File.cpp delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/README.txt delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.cpp delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/FatStructs.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.cpp delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2PinMap.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFat.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatUtil.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatmainpage.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFile.cpp delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdInfo.h delete mode 100644 draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdVolume.cpp delete mode 100644 draft- to be removed SW/components/drivers/SDcard/com/sdcard.cpp delete mode 100644 draft- to be removed SW/components/drivers/SDcard/com/sdcard.hpp delete mode 100644 draft- to be removed SW/components/drivers/SDcard/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/SDcard/test/test_sdcard.cpp delete mode 100644 draft- to be removed SW/components/drivers/diag_protocol_stack/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.cpp delete mode 100644 draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.hpp delete mode 100644 draft- to be removed SW/components/drivers/diag_protocol_stack/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/diag_protocol_stack/test/test_diag_protocol_stack.cpp delete mode 100644 draft- to be removed SW/components/drivers/network_stack/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/network_stack/com/network_stack.cpp delete mode 100644 draft- to be removed SW/components/drivers/network_stack/com/network_stack.hpp delete mode 100644 draft- to be removed SW/components/drivers/network_stack/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/network_stack/test/test_network_stack.cpp delete mode 100644 draft- to be removed SW/components/drivers/nvm/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/nvm/com/nvm.cpp delete mode 100644 draft- to be removed SW/components/drivers/nvm/com/nvm.hpp delete mode 100644 draft- to be removed SW/components/drivers/nvm/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/nvm/test/test_nvm.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/ammonia/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.hpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/ammonia/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/sensors/ammonia/test/test_ammonia.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/co2/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/sensors/co2/com/co2.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/co2/com/co2.hpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/co2/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/sensors/co2/test/test_co2.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/humidity/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.hpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/humidity/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/sensors/humidity/test/test_humidity.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/light/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/sensors/light/com/light.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/light/com/light.hpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/light/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/sensors/light/test/test_light.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/temprature/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.hpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/temprature/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/drivers/sensors/temprature/test/test_temprature.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/voc/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/drivers/sensors/voc/com/voc.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/voc/com/voc.hpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/voc/logging_data.csv delete mode 100644 draft- to be removed SW/components/drivers/sensors/voc/test/test_voc.cpp delete mode 100644 draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.py delete mode 100644 draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.test_scenario.xml delete mode 100644 draft- to be removed SW/components/os/swtimer/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/os/swtimer/com/swtimer.cpp delete mode 100644 draft- to be removed SW/components/os/swtimer/com/swtimer.hpp delete mode 100644 draft- to be removed SW/components/os/swtimer/test/test_swtimer.cpp delete mode 100644 draft- to be removed SW/components/os/task/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/os/task/com/task.cpp delete mode 100644 draft- to be removed SW/components/os/task/com/task.hpp delete mode 100644 draft- to be removed SW/components/os/task/test/test_task.cpp delete mode 100644 draft- to be removed SW/components/perf_tests/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/perf_tests/ESP32_Performance_Tests_Documentation.md delete mode 100644 draft- to be removed SW/components/perf_tests/Kconfig delete mode 100644 draft- to be removed SW/components/perf_tests/test/perf_tests.cpp delete mode 100644 draft- to be removed SW/components/system_tests/__pycache__/scan_serial.cpython-313.pyc delete mode 100644 draft- to be removed SW/components/system_tests/scan_serial.py delete mode 100644 draft- to be removed SW/components/system_tests/smoke_test_hil.py delete mode 100644 draft- to be removed SW/components/system_tests/smoke_test_simulator.py delete mode 100644 draft- to be removed SW/components/utils/logger/ARCHITECTURE.md delete mode 100644 draft- to be removed SW/components/utils/logger/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/utils/logger/DIAGRAMS.md delete mode 100644 draft- to be removed SW/components/utils/logger/README.md delete mode 100644 draft- to be removed SW/components/utils/logger/USAGE_GUIDE.md delete mode 100644 draft- to be removed SW/components/utils/logger/com/logger.cpp delete mode 100644 draft- to be removed SW/components/utils/logger/com/logger.hpp delete mode 100644 draft- to be removed SW/components/utils/logger/example/gpio_wrapper_example.cpp delete mode 100644 draft- to be removed SW/components/utils/logger/test/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/utils/logger/test/test_logger.cpp delete mode 100644 draft- to be removed SW/components/utils/time_utils/CMakeLists.txt delete mode 100644 draft- to be removed SW/components/utils/time_utils/com/time_utils.cpp delete mode 100644 draft- to be removed SW/components/utils/time_utils/com/time_utils.hpp delete mode 100644 draft- to be removed SW/features/F-COM_Communication.md delete mode 100644 draft- to be removed SW/features/F-DAQ_Sensor_Data_Acquisition.md delete mode 100644 draft- to be removed SW/features/F-DATA_Persistence_Management.md delete mode 100644 draft- to be removed SW/features/F-DIAG_Diagnostics_Health.md delete mode 100644 draft- to be removed SW/features/F-DQC_Data_Quality_Calibration.md delete mode 100644 draft- to be removed SW/features/F-HW_Hardware_Abstraction.md delete mode 100644 draft- to be removed SW/features/F-OTA_Firmware_Update.md delete mode 100644 draft- to be removed SW/features/F-PWR_Power_Fault_Handling.md delete mode 100644 draft- to be removed SW/features/F-SEC_Security_Safety.md delete mode 100644 draft- to be removed SW/features/F-SYS_System_Management.md delete mode 100644 draft- to be removed SW/features/README.md diff --git a/1 software design/Gap_analysis/Implementation_Testing_Plan.md b/1 software design/Gap_analysis/Implementation_Testing_Plan.md new file mode 100644 index 0000000..3652c88 --- /dev/null +++ b/1 software design/Gap_analysis/Implementation_Testing_Plan.md @@ -0,0 +1,700 @@ +# Implementation & Testing Plan +## ASF Sensor Hub (Sub-Hub) Embedded System + +**Document ID:** GAP-IMPL-001 +**Version:** 1.0 +**Date:** 2025-02-01 +**Project:** ASF (Automatic Smart Farm) - Sensor Hub +**Domain:** Industrial/Agricultural Automation + +--- + +## Executive Summary + +This document provides a phased implementation plan and comprehensive testing strategy for the ASF Sensor Hub embedded system. The plan is structured in four phases: Architecture & Infrastructure, Core Services, Features, and Integration & Hardening. Each phase includes scope definition, entry/exit criteria, required artifacts, and aligned testing activities. + +**Implementation Approach:** Incremental, risk-based, traceable +**Total Estimated Duration:** 16-20 weeks +**Testing Strategy:** Multi-level (Unit, Integration, System, Regression) + +--- + +## 1. Implementation Phases Overview + +### 1.1 Phase Summary + +| Phase | Name | Duration | Focus | Dependencies | +|-------|------|----------|-------|--------------| +| **Phase 1** | Architecture & Infrastructure | 4 weeks | Foundation, OSAL, HAL | None | +| **Phase 2** | Core Services | 4 weeks | State, Events, Data, Time | Phase 1 | +| **Phase 3** | Features | 6 weeks | DAQ, COM, DIAG, OTA, SEC | Phase 2 | +| **Phase 4** | Integration & Hardening | 4-6 weeks | Integration, Testing, Optimization | Phase 3 | + +**Total Duration:** 18-20 weeks + +### 1.2 Phase Dependencies + +``` +Phase 1 (Architecture & Infrastructure) + └─> Phase 2 (Core Services) + └─> Phase 3 (Features) + └─> Phase 4 (Integration & Hardening) +``` + +--- + +## 2. Phase 1: Architecture & Infrastructure + +### 2.1 Scope + +**Objective:** Establish foundation layers and hardware abstraction + +**Components:** +- OSAL Wrappers (I2C, SPI, UART, ADC, GPIO, Timer, Task) +- Hardware Abstraction Layer (HAL) +- Sensor Drivers (7 types: Temperature, Humidity, CO2, NH3, VOC, PM, Light) +- Storage Drivers (SD Card, NVM) +- Network Stack (Wi-Fi, MQTT, ESP-NOW, TLS) +- Logger Component +- Time Utils Component +- Crypto Utils Component + +**Deliverables:** +- OSAL wrapper implementations +- HAL implementations +- Sensor driver implementations +- Storage driver implementations +- Network stack implementations +- Utility component implementations +- Unit tests for all components + +### 2.2 Entry Criteria + +- [ ] GPIO mapping specification complete +- [ ] OSAL wrapper specifications complete +- [ ] Sensor driver specifications complete +- [ ] Storage driver specifications complete +- [ ] Network stack specifications complete +- [ ] Development environment set up +- [ ] Hardware test fixtures available + +### 2.3 Implementation Tasks + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-001 | Implement OSAL wrappers | OSAL | 5 days | HIGH | +| IMPL-002 | Implement HAL interfaces | HAL | 3 days | HIGH | +| IMPL-003 | Implement Temperature/Humidity driver | Sensor Drivers | 2 days | HIGH | +| IMPL-004 | Implement CO2 sensor driver | Sensor Drivers | 2 days | HIGH | +| IMPL-005 | Implement NH3 sensor driver | Sensor Drivers | 2 days | HIGH | +| IMPL-006 | Implement VOC sensor driver | Sensor Drivers | 2 days | HIGH | +| IMPL-007 | Implement PM sensor driver | Sensor Drivers | 2 days | HIGH | +| IMPL-008 | Implement Light sensor driver | Sensor Drivers | 2 days | HIGH | +| IMPL-009 | Implement SD Card driver | Storage Drivers | 3 days | HIGH | +| IMPL-010 | Implement NVM driver | Storage Drivers | 2 days | HIGH | +| IMPL-011 | Implement Wi-Fi stack | Network Stack | 3 days | HIGH | +| IMPL-012 | Implement MQTT client | Network Stack | 4 days | HIGH | +| IMPL-013 | Implement ESP-NOW handler | Network Stack | 2 days | MEDIUM | +| IMPL-014 | Implement TLS manager | Network Stack | 3 days | HIGH | +| IMPL-015 | Implement Logger component | Logger | 2 days | MEDIUM | +| IMPL-016 | Implement Time Utils component | Time Utils | 2 days | MEDIUM | +| IMPL-017 | Implement Crypto Utils component | Crypto Utils | 3 days | MEDIUM | + +**Total Estimated Effort:** 45 days (9 weeks with 1 developer, 4.5 weeks with 2 developers) + +### 2.4 Exit Criteria + +- [ ] All OSAL wrappers implemented and tested +- [ ] All sensor drivers implemented and tested +- [ ] Storage drivers implemented and tested +- [ ] Network stack implemented and tested +- [ ] Utility components implemented and tested +- [ ] Unit test coverage ≥80% for all components +- [ ] Code review completed for all components +- [ ] Documentation complete for all components + +### 2.5 Required Artifacts + +- Source code for all components +- Unit test code and results +- Component documentation +- API documentation +- Integration test stubs +- Code review reports + +--- + +## 3. Phase 2: Core Services + +### 3.1 Scope + +**Objective:** Implement core system services and infrastructure + +**Components:** +- System State Manager +- Event System +- Data Pool +- Data Persistence +- Error Handler +- Diagnostics Manager (basic) +- Machine Constants Manager + +**Deliverables:** +- Core service implementations +- State machine implementation +- Event system implementation +- Data management implementations +- Error handling implementation +- Unit and integration tests + +### 3.2 Entry Criteria + +- [ ] Phase 1 complete and validated +- [ ] OSAL wrappers available +- [ ] Storage drivers available +- [ ] Logger component available +- [ ] Time Utils component available + +### 3.3 Implementation Tasks + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-101 | Implement System State Manager | State Manager | 5 days | HIGH | +| IMPL-102 | Implement Event System | Event System | 4 days | HIGH | +| IMPL-103 | Implement Data Pool | Data Pool | 3 days | HIGH | +| IMPL-104 | Implement Data Persistence | Data Persistence | 5 days | HIGH | +| IMPL-105 | Implement Error Handler | Error Handler | 4 days | HIGH | +| IMPL-106 | Implement Diagnostics Manager (basic) | Diagnostics Manager | 4 days | HIGH | +| IMPL-107 | Implement Machine Constants Manager | MC Manager | 3 days | HIGH | +| IMPL-108 | Integrate core services | Integration | 3 days | HIGH | + +**Total Estimated Effort:** 31 days (6 weeks with 1 developer, 3 weeks with 2 developers) + +### 3.4 Exit Criteria + +- [ ] System State Manager implemented and tested +- [ ] Event System implemented and tested +- [ ] Data Pool implemented and tested +- [ ] Data Persistence implemented and tested +- [ ] Error Handler implemented and tested +- [ ] Diagnostics Manager (basic) implemented and tested +- [ ] Machine Constants Manager implemented and tested +- [ ] Core services integrated and tested +- [ ] Unit test coverage ≥80% +- [ ] Integration tests passing + +### 3.5 Required Artifacts + +- Source code for all core services +- Unit and integration test code +- State machine test results +- Event system test results +- Integration test results +- Component documentation + +--- + +## 4. Phase 3: Features + +### 4.1 Scope + +**Objective:** Implement all system features + +**Features:** +- Sensor Data Acquisition (DAQ) +- Data Quality & Calibration (DQC) +- Communication (COM) +- Diagnostics & Health Monitoring (DIAG) +- Firmware Update (OTA) +- Security & Safety (SEC) +- System Management (SYS) +- Power & Fault Handling (PWR) + +**Deliverables:** +- Feature implementations +- Feature integration +- Feature-specific tests +- Feature documentation + +### 4.2 Entry Criteria + +- [ ] Phase 2 complete and validated +- [ ] Core services available +- [ ] Sensor drivers available +- [ ] Network stack available + +### 4.3 Implementation Tasks + +#### 4.3.1 Sensor Data Acquisition (DAQ) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-201 | Implement Sensor Manager | Sensor Manager | 5 days | HIGH | +| IMPL-202 | Implement sensor acquisition scheduling | Sensor Manager | 3 days | HIGH | +| IMPL-203 | Implement filtering engine | Filter Engine | 3 days | HIGH | +| IMPL-204 | Integrate sensor drivers | Sensor Manager | 2 days | HIGH | + +#### 4.3.2 Data Quality & Calibration (DQC) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-211 | Implement sensor detection | Sensor Manager | 2 days | HIGH | +| IMPL-212 | Implement sensor validation | Sensor Manager | 2 days | HIGH | +| IMPL-213 | Implement calibration management | Sensor Manager | 3 days | MEDIUM | +| IMPL-214 | Implement sensor fusion (if needed) | Sensor Manager | 3 days | LOW | + +#### 4.3.3 Communication (COM) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-221 | Implement Communication Manager | Communication Manager | 5 days | HIGH | +| IMPL-222 | Implement MQTT message handling | Communication Manager | 4 days | HIGH | +| IMPL-223 | Implement ESP-NOW peer communication | Communication Manager | 3 days | MEDIUM | +| IMPL-224 | Implement heartbeat mechanism | Communication Manager | 2 days | HIGH | +| IMPL-225 | Implement automatic reconnection | Communication Manager | 2 days | MEDIUM | +| IMPL-226 | Implement message queuing | Communication Manager | 2 days | LOW | + +#### 4.3.4 Diagnostics & Health Monitoring (DIAG) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-231 | Complete Diagnostics Manager | Diagnostics Manager | 4 days | HIGH | +| IMPL-232 | Implement diagnostic code registry | Diagnostics Manager | 2 days | HIGH | +| IMPL-233 | Implement diagnostic sessions | Diagnostics Manager | 3 days | MEDIUM | +| IMPL-234 | Implement watchdog system | Watchdog Manager | 4 days | HIGH | + +#### 4.3.5 Firmware Update (OTA) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-241 | Implement OTA Manager | OTA Manager | 5 days | HIGH | +| IMPL-242 | Implement firmware reception | OTA Manager | 3 days | HIGH | +| IMPL-243 | Implement firmware validation | OTA Manager | 3 days | HIGH | +| IMPL-244 | Implement A/B partitioning | OTA Manager | 3 days | HIGH | +| IMPL-245 | Implement automatic rollback | OTA Manager | 2 days | MEDIUM | + +#### 4.3.6 Security & Safety (SEC) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-251 | Complete Security Manager | Security Manager | 4 days | HIGH | +| IMPL-252 | Implement secure boot integration | Security Manager | 2 days | HIGH | +| IMPL-253 | Implement flash encryption | Security Manager | 2 days | HIGH | +| IMPL-254 | Implement certificate management | Security Manager | 3 days | HIGH | +| IMPL-255 | Implement key management | Security Manager | 3 days | HIGH | + +#### 4.3.7 System Management (SYS) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-261 | Implement HMI Controller | HMI Controller | 4 days | MEDIUM | +| IMPL-262 | Implement OLED display driver | HMI Controller | 2 days | MEDIUM | +| IMPL-263 | Implement button handling | HMI Controller | 2 days | MEDIUM | +| IMPL-264 | Implement menu system | HMI Controller | 3 days | MEDIUM | +| IMPL-265 | Implement debug sessions | System State Manager | 3 days | LOW | + +#### 4.3.8 Power & Fault Handling (PWR) + +| Task ID | Task Description | Component | Estimated Effort | Priority | +|---------|------------------|-----------|------------------|----------| +| IMPL-271 | Implement brownout detection | Error Handler | 2 days | MEDIUM | +| IMPL-272 | Implement power-loss recovery | System State Manager | 2 days | MEDIUM | + +**Total Estimated Effort:** 95 days (19 weeks with 1 developer, 9.5 weeks with 2 developers) + +### 4.4 Exit Criteria + +- [ ] All features implemented +- [ ] All features integrated +- [ ] Feature-specific tests passing +- [ ] Unit test coverage ≥80% for all features +- [ ] Integration tests passing +- [ ] Code review completed +- [ ] Feature documentation complete + +### 4.5 Required Artifacts + +- Source code for all features +- Feature test code and results +- Integration test results +- Feature documentation +- API documentation + +--- + +## 5. Phase 4: Integration & Hardening + +### 5.1 Scope + +**Objective:** Integrate all components, perform system testing, and harden the system + +**Activities:** +- System integration +- System testing +- Performance optimization +- Security hardening +- Reliability testing +- Documentation completion + +**Deliverables:** +- Integrated system +- System test results +- Performance test results +- Security test results +- Complete documentation +- Release candidate + +### 5.2 Entry Criteria + +- [ ] Phase 3 complete and validated +- [ ] All features implemented +- [ ] Integration test environment ready +- [ ] System test environment ready + +### 5.3 Implementation Tasks + +| Task ID | Task Description | Estimated Effort | Priority | +|---------|------------------|------------------|----------| +| IMPL-301 | System integration | 5 days | HIGH | +| IMPL-302 | System testing | 10 days | HIGH | +| IMPL-303 | Performance optimization | 5 days | MEDIUM | +| IMPL-304 | Security hardening | 5 days | HIGH | +| IMPL-305 | Reliability testing | 5 days | HIGH | +| IMPL-306 | Documentation completion | 5 days | MEDIUM | +| IMPL-307 | Bug fixes and refinements | 10 days | HIGH | + +**Total Estimated Effort:** 45 days (9 weeks with 1 developer, 4.5 weeks with 2 developers) + +### 5.4 Exit Criteria + +- [ ] All system tests passing +- [ ] Performance requirements met +- [ ] Security requirements validated +- [ ] Reliability requirements met +- [ ] Documentation complete +- [ ] Code review completed +- [ ] Release candidate approved + +### 5.5 Required Artifacts + +- Integrated system +- System test results +- Performance test results +- Security test results +- Complete documentation +- Release notes + +--- + +## 6. Testing Plan + +### 6.1 Testing Strategy Overview + +**Testing Levels:** +1. **Unit Testing:** Individual component testing +2. **Integration Testing:** Component interaction testing +3. **System Testing:** End-to-end system testing +4. **Regression Testing:** Regression prevention + +**Testing Types:** +- Functional Testing +- Performance Testing +- Security Testing +- Reliability Testing +- Stress Testing +- Compatibility Testing + +### 6.2 Unit Testing + +#### 6.2.1 Scope + +**Objective:** Verify individual components function correctly + +**Coverage Target:** ≥80% code coverage + +**Components:** +- All OSAL wrappers +- All sensor drivers +- All storage drivers +- All network stack components +- All utility components +- All core services +- All feature components + +#### 6.2.2 Test Framework + +**Framework:** Unity (C unit testing framework for embedded systems) + +**Test Structure:** +```c +// Example test structure +void test_component_function(void) { + // Setup + // Execute + // Verify + // Cleanup +} +``` + +#### 6.2.3 Test Execution + +**Phase 1:** Unit tests for OSAL, HAL, drivers, utilities +**Phase 2:** Unit tests for core services +**Phase 3:** Unit tests for features +**Phase 4:** Unit test maintenance and regression + +#### 6.2.4 Entry/Exit Criteria + +**Entry Criteria:** +- Component implementation complete +- Component interface stable + +**Exit Criteria:** +- Unit tests written and passing +- Code coverage ≥80% +- Code review completed + +### 6.3 Integration Testing + +#### 6.3.1 Scope + +**Objective:** Verify component interactions and interfaces + +**Integration Points:** +- OSAL ↔ HAL +- Sensor Drivers ↔ Sensor Manager +- Storage Drivers ↔ Data Persistence +- Network Stack ↔ Communication Manager +- Core Services ↔ Features +- Event System ↔ All Components + +#### 6.3.2 Test Scenarios + +| Test ID | Scenario | Components | Priority | +|---------|----------|-----------|----------| +| INT-001 | Sensor acquisition flow | Sensor Drivers → Sensor Manager → Data Pool | HIGH | +| INT-002 | Data persistence flow | Data Pool → Data Persistence → Storage | HIGH | +| INT-003 | Communication flow | Communication Manager → Network Stack → MQTT | HIGH | +| INT-004 | State transition flow | State Manager → Event System → Components | HIGH | +| INT-005 | Error handling flow | Error Handler → Diagnostics → State Manager | HIGH | +| INT-006 | OTA update flow | OTA Manager → Communication → Storage | HIGH | +| INT-007 | Security flow | Security Manager → TLS → Communication | HIGH | + +#### 6.3.3 Test Execution + +**Phase 2:** Core services integration +**Phase 3:** Feature integration +**Phase 4:** System integration + +#### 6.3.4 Entry/Exit Criteria + +**Entry Criteria:** +- Related components implemented +- Unit tests passing + +**Exit Criteria:** +- Integration tests written and passing +- Interface contracts validated +- Error handling validated + +### 6.4 System Testing + +#### 6.4.1 Scope + +**Objective:** Verify end-to-end system functionality + +**Test Areas:** +- Functional requirements +- Performance requirements +- Security requirements +- Reliability requirements +- Usability requirements + +#### 6.4.2 Test Scenarios + +| Test ID | Scenario | Requirements | Priority | +|---------|----------|--------------|----------| +| SYS-001 | Complete sensor acquisition cycle | SR-DAQ-001 through SR-DAQ-013 | HIGH | +| SYS-002 | Communication with Main Hub | SR-COM-001 through SR-COM-010 | HIGH | +| SYS-003 | OTA firmware update | SR-OTA-001 through SR-OTA-013 | HIGH | +| SYS-004 | State machine operation | SR-SYS-001 through SR-SYS-003 | HIGH | +| SYS-005 | Error handling and recovery | SR-DIAG-001 through SR-DIAG-011 | HIGH | +| SYS-006 | Security validation | SR-SEC-001 through SR-SEC-015 | HIGH | +| SYS-007 | Data persistence | SR-DATA-001 through SR-DATA-009 | HIGH | +| SYS-008 | Power loss recovery | SR-PWR-001 through SR-PWR-008 | MEDIUM | + +#### 6.4.3 Performance Testing + +**Test Scenarios:** +- Sensor acquisition timing (SWR-PERF-001) +- State transition timing (SWR-PERF-002) +- Data persistence timing (SWR-PERF-003) +- Communication response time (SWR-PERF-007) +- CPU utilization (SWR-PERF-005) +- RAM usage (SWR-PERF-006) + +#### 6.4.4 Security Testing + +**Test Scenarios:** +- Secure boot validation +- Flash encryption validation +- TLS communication validation +- Certificate validation +- Key management validation +- Security violation detection + +#### 6.4.5 Reliability Testing + +**Test Scenarios:** +- Long-duration operation (24+ hours) +- Power interruption recovery +- Communication failure recovery +- Sensor failure handling +- Storage failure handling +- Watchdog operation + +#### 6.4.6 Test Execution + +**Phase 4:** System testing execution + +#### 6.4.7 Entry/Exit Criteria + +**Entry Criteria:** +- System integration complete +- Integration tests passing + +**Exit Criteria:** +- All system tests passing +- Performance requirements met +- Security requirements validated +- Reliability requirements met + +### 6.5 Regression Testing + +#### 6.5.1 Scope + +**Objective:** Prevent regression of previously working functionality + +**Strategy:** +- Automated regression test suite +- Continuous integration +- Pre-release regression testing + +#### 6.5.2 Test Execution + +**Frequency:** +- After each bug fix +- Before each release +- Weekly during development + +#### 6.5.3 Entry/Exit Criteria + +**Entry Criteria:** +- Code changes made +- Previous tests passing + +**Exit Criteria:** +- Regression tests passing +- No new failures introduced + +--- + +## 7. Testing Artifacts + +### 7.1 Test Documentation + +- Test plan documents +- Test case specifications +- Test procedure documents +- Test data specifications +- Test environment setup guides + +### 7.2 Test Results + +- Unit test results +- Integration test results +- System test results +- Performance test results +- Security test results +- Reliability test results + +### 7.3 Test Reports + +- Test execution reports +- Test coverage reports +- Defect reports +- Test summary reports + +--- + +## 8. Risk Management + +### 8.1 Implementation Risks + +| Risk ID | Risk Description | Probability | Impact | Mitigation | +|---------|------------------|-------------|--------|------------| +| IMPL-RISK-001 | Hardware availability delays | MEDIUM | HIGH | Early hardware procurement | +| IMPL-RISK-002 | Sensor driver complexity | MEDIUM | MEDIUM | Prototype early, iterate | +| IMPL-RISK-003 | Network stack integration issues | MEDIUM | MEDIUM | Use proven libraries, test early | +| IMPL-RISK-004 | Performance requirements not met | LOW | HIGH | Early performance testing | +| IMPL-RISK-005 | Security vulnerabilities | LOW | HIGH | Security reviews, penetration testing | + +### 8.2 Testing Risks + +| Risk ID | Risk Description | Probability | Impact | Mitigation | +|---------|------------------|-------------|--------|------------| +| TEST-RISK-001 | Test environment availability | MEDIUM | MEDIUM | Early test environment setup | +| TEST-RISK-002 | Hardware test fixtures delays | MEDIUM | MEDIUM | Early fixture procurement | +| TEST-RISK-003 | Test coverage insufficient | LOW | MEDIUM | Continuous coverage monitoring | +| TEST-RISK-004 | Test automation complexity | MEDIUM | LOW | Use proven frameworks | + +--- + +## 9. Success Criteria + +### 9.1 Phase Completion Criteria + +**All Phases:** +- [ ] All tasks completed +- [ ] All tests passing +- [ ] Code review completed +- [ ] Documentation complete +- [ ] Exit criteria met + +### 9.2 Overall Project Success Criteria + +- [ ] All system requirements implemented +- [ ] All software requirements implemented +- [ ] All features functional +- [ ] Performance requirements met +- [ ] Security requirements validated +- [ ] Reliability requirements met +- [ ] Documentation complete +- [ ] System ready for deployment + +--- + +## 10. Conclusion + +This Implementation & Testing Plan provides a structured, phased approach to implementing and validating the ASF Sensor Hub embedded system. The plan is designed to be: + +- **Incremental:** Build foundation before features +- **Risk-based:** Address high-risk items early +- **Traceable:** Link implementation to requirements +- **Testable:** Comprehensive testing at all levels +- **Realistic:** Based on actual effort estimates + +**Recommended Approach:** +1. Follow phased implementation approach +2. Complete each phase before starting next +3. Maintain high test coverage throughout +4. Conduct regular reviews and validations +5. Address risks proactively + +**Estimated Timeline:** 18-20 weeks with appropriate resources + +--- + +**Document Status:** Complete +**Next Review:** Before implementation start +**Approval Required:** Project Manager, Technical Lead, QA Lead diff --git a/1 software design/Gap_analysis/Readiness_Action_Plan.md b/1 software design/Gap_analysis/Readiness_Action_Plan.md new file mode 100644 index 0000000..26d3a5d --- /dev/null +++ b/1 software design/Gap_analysis/Readiness_Action_Plan.md @@ -0,0 +1,387 @@ +# Readiness & Action Plan +## ASF Sensor Hub (Sub-Hub) Embedded System + +**Document ID:** GAP-READINESS-001 +**Version:** 1.0 +**Date:** 2025-02-01 +**Project:** ASF (Automatic Smart Farm) - Sensor Hub +**Domain:** Industrial/Agricultural Automation + +--- + +## Executive Summary + +This document provides an overall design maturity assessment, identifies risks if implementation starts now, specifies required actions before implementation, and recommends sequencing of actions based on the comprehensive gap analysis performed. + +**Overall Design Maturity:** 85% - Ready for implementation after addressing critical gaps. + +**Critical Gaps:** 5 items requiring immediate attention +**Important Gaps:** 12 items requiring attention during design phase +**Optional Gaps:** 8 items that can be addressed during implementation + +--- + +## 1. Overall Design Maturity Assessment + +### 1.1 Maturity Score by Domain + +| Domain | Completeness | Consistency | Clarity | Testability | Maturity Score | +|--------|--------------|-------------|---------|-------------|----------------| +| **System Requirements** | 85% | 90% | 80% | 75% | **82.5%** | +| **System Features** | 100% | 90% | 90% | 85% | **91.25%** | +| **Software Requirements** | 100% | 95% | 85% | 75% | **88.75%** | +| **Software Features** | 100% | 100% | 90% | 80% | **92.5%** | +| **Software Components** | 80% | 90% | 85% | 75% | **82.5%** | +| **Traceability** | 90% | 95% | 90% | 85% | **90%** | +| **Architecture** | 85% | 90% | 85% | 80% | **85%** | +| **Testing Strategy** | 60% | 70% | 70% | 65% | **66.25%** | + +**Overall Design Maturity:** **85.1%** + +### 1.2 Maturity Level Classification + +| Level | Score Range | Current Status | Description | +|-------|-------------|----------------|-------------| +| **Level 1: Initial** | 0-40% | ❌ | Ad-hoc, incomplete | +| **Level 2: Managed** | 41-60% | ❌ | Basic processes, partial | +| **Level 3: Defined** | 61-80% | ⚠️ | Well-defined, mostly complete | +| **Level 4: Quantitatively Managed** | 81-95% | ✅ | Complete, measurable | +| **Level 5: Optimizing** | 96-100% | ❌ | Continuously improving | + +**Current Level:** **Level 4 (Quantitatively Managed)** - 85.1% + +**Assessment:** The design has reached a mature state suitable for implementation, with most critical elements defined and traceable. Remaining gaps are manageable and can be addressed during implementation or in subsequent phases. + +--- + +## 2. Risks if Implementation Starts Now + +### 2.1 Critical Risks (Must Address Before Implementation) + +| Risk ID | Risk Description | Probability | Impact | Severity | Mitigation | +|---------|------------------|-------------|--------|----------|------------| +| **RISK-001** | GPIO conflicts due to missing mapping | **HIGH** | **HIGH** | **CRITICAL** | Complete GPIO mapping | +| **RISK-002** | Time sync issues affecting data quality | **MEDIUM** | **HIGH** | **CRITICAL** | Add time sync requirements | +| **RISK-003** | Missing sensor drivers blocking integration | **HIGH** | **HIGH** | **CRITICAL** | Specify sensor drivers | +| **RISK-004** | Missing OSAL blocking hardware abstraction | **HIGH** | **HIGH** | **CRITICAL** | Complete OSAL specification | +| **RISK-005** | Missing MQTT spec blocking communication | **MEDIUM** | **HIGH** | **CRITICAL** | Complete MQTT specification | + +### 2.2 High Risks (Should Address Before Implementation) + +| Risk ID | Risk Description | Probability | Impact | Severity | Mitigation | +|---------|------------------|-------------|--------|----------|------------| +| **RISK-006** | Unclear acceptance criteria delaying tests | **HIGH** | **MEDIUM** | **HIGH** | Add acceptance criteria | +| **RISK-007** | Missing component assignments causing gaps | **MEDIUM** | **MEDIUM** | **HIGH** | Complete component assignments | +| **RISK-008** | Incomplete diagnostic codes affecting troubleshooting | **MEDIUM** | **MEDIUM** | **HIGH** | Complete diagnostic code registry | +| **RISK-009** | Missing PWR/HW software features | **MEDIUM** | **MEDIUM** | **HIGH** | Create missing software features | + +### 2.3 Medium Risks (Can Address During Implementation) + +| Risk ID | Risk Description | Probability | Impact | Severity | Mitigation | +|---------|------------------|-------------|--------|----------|------------| +| **RISK-010** | Missing dynamic views affecting understanding | **LOW** | **MEDIUM** | **MEDIUM** | Create sequence diagrams | +| **RISK-011** | Incomplete test strategy delaying validation | **MEDIUM** | **MEDIUM** | **MEDIUM** | Develop test strategy | +| **RISK-012** | Missing calibration procedures | **LOW** | **MEDIUM** | **MEDIUM** | Add calibration procedures | +| **RISK-013** | Missing certificate lifecycle management | **LOW** | **MEDIUM** | **MEDIUM** | Define certificate lifecycle | + +### 2.4 Risk Summary + +| Severity | Count | Status | +|----------|-------|--------| +| **CRITICAL** | 5 | ⚠️ Must address before implementation | +| **HIGH** | 4 | ⚠️ Should address before implementation | +| **MEDIUM** | 4 | ✅ Can address during implementation | +| **LOW** | 0 | ✅ Acceptable | + +--- + +## 3. Required Actions BEFORE Implementation + +### 3.1 Critical Actions (Must Complete) + +| Action ID | Action Description | Estimated Effort | Owner | Deadline | +|-----------|-------------------|------------------|-------|----------| +| **ACT-001** | Complete GPIO mapping specification | 2 days | Hardware Engineer | Week 1 | +| **ACT-002** | Add time synchronization requirements | 1 day | Systems Engineer | Week 1 | +| **ACT-003** | Specify sensor driver interfaces (7 types) | 3 days | Software Architect | Week 1-2 | +| **ACT-004** | Complete OSAL wrapper specifications | 2 days | Software Architect | Week 1-2 | +| **ACT-005** | Complete MQTT topic structure specification | 1 day | Software Architect | Week 1 | + +**Total Critical Actions:** 5 +**Total Estimated Effort:** 9 days +**Recommended Timeline:** 2 weeks + +### 3.2 Important Actions (Should Complete) + +| Action ID | Action Description | Estimated Effort | Owner | Deadline | +|-----------|-------------------|------------------|-------|----------| +| **ACT-006** | Add acceptance criteria to all requirements | 3 days | Systems Engineer | Week 2 | +| **ACT-007** | Complete component assignments for missing SWRs | 2 days | Software Architect | Week 2 | +| **ACT-008** | Complete diagnostic code registry | 2 days | Systems Engineer | Week 2 | +| **ACT-009** | Create PWR and HW software features | 1 day | Software Architect | Week 2 | +| **ACT-010** | Add missing software requirements for PWR/HW | 1 day | Systems Engineer | Week 2 | + +**Total Important Actions:** 5 +**Total Estimated Effort:** 9 days +**Recommended Timeline:** 2 weeks (parallel with critical actions) + +### 3.3 Action Dependencies + +``` +ACT-001 (GPIO Mapping) + └─> ACT-003 (Sensor Drivers) - Hardware pin assignments needed + └─> ACT-004 (OSAL) - GPIO interface definitions needed + +ACT-002 (Time Sync) + └─> ACT-007 (Component Assignments) - Time Utils component needed + +ACT-005 (MQTT Spec) + └─> ACT-007 (Component Assignments) - Communication Manager interface needed + +ACT-009 (PWR/HW Features) + └─> ACT-010 (PWR/HW Requirements) - Features needed before requirements +``` + +--- + +## 4. Recommended Sequencing of Actions + +### 4.1 Phase 1: Foundation (Week 1) + +**Goal:** Establish critical foundations for implementation + +**Actions:** +1. **ACT-001:** Complete GPIO mapping specification +2. **ACT-002:** Add time synchronization requirements +3. **ACT-005:** Complete MQTT topic structure specification + +**Deliverables:** +- GPIO_Mapping_Specification.md +- Time_Synchronization_Requirements.md +- MQTT_Topic_Structure.md + +**Success Criteria:** +- GPIO mapping complete and reviewed +- Time sync requirements added to SRS +- MQTT specification complete + +### 4.2 Phase 2: Hardware Abstraction (Week 1-2) + +**Goal:** Complete hardware abstraction layer specifications + +**Actions:** +1. **ACT-003:** Specify sensor driver interfaces +2. **ACT-004:** Complete OSAL wrapper specifications + +**Deliverables:** +- Sensor_Drivers_Specification.md +- OSAL_Wrappers_Specification.md + +**Success Criteria:** +- All sensor driver interfaces specified +- OSAL wrappers complete +- Hardware abstraction layer ready + +### 4.3 Phase 3: Requirements Completion (Week 2) + +**Goal:** Complete requirements and traceability + +**Actions:** +1. **ACT-006:** Add acceptance criteria to all requirements +2. **ACT-007:** Complete component assignments +3. **ACT-008:** Complete diagnostic code registry +4. **ACT-009:** Create PWR and HW software features +5. **ACT-010:** Add missing software requirements + +**Deliverables:** +- Updated SRS with acceptance criteria +- Updated traceability matrices +- Complete diagnostic code registry +- PWR and HW software features + +**Success Criteria:** +- All requirements have acceptance criteria +- All SWRs assigned to components +- Diagnostic codes complete +- PWR/HW features created + +### 4.4 Phase 4: Validation (Week 2-3) + +**Goal:** Validate readiness for implementation + +**Actions:** +1. Review all gap resolutions +2. Validate traceability completeness +3. Conduct design review +4. Obtain approval for implementation + +**Deliverables:** +- Gap resolution report +- Traceability validation report +- Design review minutes +- Implementation approval + +**Success Criteria:** +- All critical gaps resolved +- Traceability complete +- Design review passed +- Implementation approved + +--- + +## 5. Implementation Readiness Checklist + +### 5.1 System Design Readiness + +- [ ] GPIO mapping specification complete +- [ ] Time synchronization requirements added +- [ ] MQTT topic structure specified +- [ ] Diagnostic code registry complete +- [ ] All system requirements have acceptance criteria +- [ ] Cross-feature constraints validated + +**Status:** ⚠️ 4/6 complete (67%) + +### 5.2 Software Design Readiness + +- [ ] All critical components specified +- [ ] OSAL wrappers specified +- [ ] Sensor drivers specified +- [ ] All interfaces have error handling +- [ ] All interfaces have timeout specifications +- [ ] Component dependencies validated + +**Status:** ⚠️ 3/6 complete (50%) + +### 5.3 Traceability Readiness + +- [ ] All system requirements traced to software requirements +- [ ] All software requirements traced to components +- [ ] All features traced to requirements +- [ ] PWR and HW software features created +- [ ] Component assignments complete + +**Status:** ⚠️ 3/5 complete (60%) + +### 5.4 Testing Readiness + +- [ ] Test strategy defined +- [ ] Unit test framework selected +- [ ] Integration test architecture defined +- [ ] HIL test setup planned +- [ ] Test data management planned + +**Status:** ❌ 0/5 complete (0%) + +### 5.5 Overall Readiness + +**Overall Status:** ⚠️ **10/22 complete (45%)** + +**Assessment:** Not ready for implementation. Critical actions must be completed first. + +--- + +## 6. Recommended Implementation Start Date + +### 6.1 Prerequisites + +**Must Complete Before Start:** +- All critical actions (ACT-001 through ACT-005) +- GPIO mapping specification +- Time synchronization requirements +- MQTT specification +- Sensor driver specifications +- OSAL wrapper specifications + +**Estimated Time to Complete Prerequisites:** 2 weeks + +### 6.2 Recommended Start Date + +**Earliest Start Date:** Week 3 (after completing critical actions) + +**Optimal Start Date:** Week 4 (after completing all important actions) + +**Rationale:** +- Week 3: Critical foundations ready, some gaps remain +- Week 4: All critical and important actions complete, ready for smooth implementation + +### 6.3 Risk-Based Start Date + +**If Starting Week 3:** +- Risk Level: MEDIUM +- Mitigation: Address remaining gaps in parallel with implementation +- Impact: Some rework may be required + +**If Starting Week 4:** +- Risk Level: LOW +- Mitigation: All critical gaps resolved +- Impact: Minimal rework expected + +--- + +## 7. Action Plan Summary + +### 7.1 Critical Path + +``` +Week 1: + Day 1-2: ACT-001 (GPIO Mapping) + Day 3: ACT-002 (Time Sync) + Day 4: ACT-005 (MQTT Spec) + Day 5: Review and validation + +Week 2: + Day 1-3: ACT-003 (Sensor Drivers) + Day 4-5: ACT-004 (OSAL Wrappers) + Day 6-7: ACT-006, ACT-007, ACT-008 (Requirements) + Day 8-9: ACT-009, ACT-010 (PWR/HW Features) + Day 10: Final review and approval +``` + +### 7.2 Resource Requirements + +| Role | Effort (Days) | Allocation | +|------|---------------|------------| +| Systems Engineer | 6 days | Full-time | +| Software Architect | 8 days | Full-time | +| Hardware Engineer | 2 days | Part-time | +| **Total** | **16 days** | **2 weeks** | + +### 7.3 Success Metrics + +| Metric | Target | Current | Status | +|--------|--------|---------|--------| +| Critical Actions Complete | 100% | 0% | ❌ | +| Important Actions Complete | 100% | 0% | ❌ | +| Readiness Checklist | 100% | 45% | ❌ | +| Design Maturity | ≥85% | 85.1% | ✅ | +| Traceability Coverage | ≥90% | 90% | ✅ | + +--- + +## 8. Conclusion + +The ASF Sensor Hub design has reached **85.1% maturity**, indicating it is approaching readiness for implementation. However, **critical gaps must be addressed** before implementation can begin safely. + +**Key Findings:** +- Design foundation is solid +- Most requirements and components are well-defined +- Critical gaps are manageable (5 items, 9 days effort) +- Important gaps can be addressed in parallel (5 items, 9 days effort) + +**Recommended Approach:** +1. **Week 1-2:** Complete all critical and important actions +2. **Week 3:** Conduct final review and validation +3. **Week 4:** Begin implementation with confidence + +**Risk Assessment:** +- **Starting Week 3:** MEDIUM risk - Some gaps remain, manageable +- **Starting Week 4:** LOW risk - All critical gaps resolved + +**Final Recommendation:** **Begin implementation in Week 4** after completing all critical and important actions. This provides the best balance between speed and risk mitigation. + +--- + +**Document Status:** Complete +**Next Review:** After action completion +**Approval Required:** Project Manager, System Architect, Software Architect diff --git a/1 software design/Gap_analysis/Software_Design_Gap_Analysis.md b/1 software design/Gap_analysis/Software_Design_Gap_Analysis.md new file mode 100644 index 0000000..2df93ee --- /dev/null +++ b/1 software design/Gap_analysis/Software_Design_Gap_Analysis.md @@ -0,0 +1,621 @@ +# Software Design Gap Analysis +## ASF Sensor Hub (Sub-Hub) Embedded System + +**Document ID:** GAP-SW-001 +**Version:** 1.0 +**Date:** 2025-02-01 +**Standard:** ISO/IEC/IEEE 42010:2011 +**Project:** ASF (Automatic Smart Farm) - Sensor Hub +**Domain:** Industrial/Agricultural Automation + +--- + +## Executive Summary + +This document presents a comprehensive gap analysis of the Software Design for the ASF Sensor Hub embedded system. The analysis evaluates component completeness, interface definition quality, architectural consistency, alignment with software requirements, presence of static and dynamic views, and testability/diagnosability. + +**Overall Assessment:** The software design demonstrates strong architectural foundation with well-defined components and clear separation of concerns. However, several gaps have been identified that require attention before implementation begins. + +**Key Findings:** +- **Component Completeness:** 80% - Most components specified, some missing +- **Interface Quality:** 85% - Well-defined interfaces, some missing details +- **Architectural Consistency:** 90% - Good consistency with system design +- **Requirement Alignment:** 85% - Good alignment, some gaps +- **Static/Dynamic Views:** 70% - Static views present, dynamic views incomplete +- **Testability:** 75% - Components testable, but test strategies incomplete + +--- + +## 1. Component Completeness Analysis + +### 1.1 Existing Components Assessment + +| Component ID | Component Name | Specification Status | Interface Status | Implementation Status | +|--------------|----------------|---------------------|------------------|----------------------| +| C-STM-001 | System State Manager | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-SENSOR-001 | Sensor Manager | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-COM-001 | Communication Manager | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-OTA-001 | OTA Manager | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-MC-001 | Machine Constants Manager | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-SEC-001 | Security Manager | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-DIAG-001 | Diagnostics Manager | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-EVENT-001 | Event System | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-DATA-POOL | Data Pool | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-DP-001 | Data Persistence | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-ERROR-001 | Error Handler | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-TIME-001 | Time Utils | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-LOGGER-001 | Logger | ✅ Complete | ✅ Complete | ❌ Not Started | +| C-HAL-001 | Hardware Abstraction Layer | ⚠️ Partial | ⚠️ Partial | ❌ Not Started | + +**Total Components:** 14 +**Fully Specified:** 13 (93%) +**Partially Specified:** 1 (7%) +**Not Specified:** 0 (0%) + +### 1.2 Missing Components + +| Gap ID | Component Name | Purpose | Severity | Required For | +|--------|----------------|---------|----------|--------------| +| **GAP-COMP-001** | Sensor Drivers (7 types) | Hardware-specific sensor drivers | **HIGH** | Sensor Manager | +| **GAP-COMP-002** | Storage Drivers | SD Card and NVM drivers | **HIGH** | Data Persistence | +| **GAP-COMP-003** | Network Stack | Wi-Fi, MQTT, ESP-NOW drivers | **HIGH** | Communication Manager | +| **GAP-COMP-004** | Crypto Utils | Cryptographic functions | **MEDIUM** | Security Manager | +| **GAP-COMP-005** | Data Validation | Data validation utilities | **MEDIUM** | Multiple components | +| **GAP-COMP-006** | HMI Controller | OLED display and button handling | **MEDIUM** | System Management | +| **GAP-COMP-007** | OSAL Wrappers | ESP-IDF wrapper layer | **HIGH** | All components | +| **GAP-COMP-008** | Filter Engine | Sensor data filtering algorithms | **MEDIUM** | Sensor Manager | +| **GAP-COMP-009** | Message Formatter | CBOR encoding/decoding | **MEDIUM** | Communication Manager | +| **GAP-COMP-010** | Watchdog Manager | Layered watchdog system | **MEDIUM** | Diagnostics Manager | + +**Total Missing Components:** 10 +**High Priority:** 4 +**Medium Priority:** 6 + +### 1.3 Component Responsibility Gaps + +| Gap ID | Description | Affected Component | Severity | +|--------|-------------|-------------------|----------| +| **GAP-RESP-001** | Sensor warmup period management unclear | Sensor Manager | MEDIUM | +| **GAP-RESP-002** | Sensor fusion algorithm ownership unclear | Sensor Manager vs Data Quality | MEDIUM | +| **GAP-RESP-003** | Time synchronization ownership unclear | Time Utils vs Communication Manager | MEDIUM | +| **GAP-RESP-004** | Certificate management ownership unclear | Security Manager vs OTA Manager | LOW | +| **GAP-RESP-005** | Diagnostic code registry ownership unclear | Diagnostics Manager | LOW | + +--- + +## 2. Interface Definition Quality Analysis + +### 2.1 Interface Completeness + +**Overall Assessment:** 85% complete + +#### Well-Defined Interfaces + +| Component | Interface Type | Completeness | Quality | +|-----------|---------------|--------------|---------| +| System State Manager | State Query, Transition | ✅ 100% | Excellent | +| Sensor Manager | Acquisition Control, Data Access | ✅ 95% | Excellent | +| Communication Manager | Message Send/Receive | ✅ 90% | Good | +| Data Persistence | Read/Write, Serialization | ✅ 90% | Good | +| Event System | Publish/Subscribe | ✅ 95% | Excellent | + +#### Incomplete Interfaces + +| Gap ID | Component | Interface | Missing Elements | Severity | +|--------|-----------|-----------|-----------------|----------| +| **GAP-IF-001** | Communication Manager | MQTT Interface | Topic structure, QoS levels | **HIGH** | +| **GAP-IF-002** | Security Manager | Key Management | Key rotation, revocation | **MEDIUM** | +| **GAP-IF-003** | OTA Manager | Firmware Update | Progress reporting, rollback | **MEDIUM** | +| **GAP-IF-004** | Data Persistence | Storage Interface | Wear leveling, capacity management | **MEDIUM** | +| **GAP-IF-005** | Diagnostics Manager | Diagnostic Session | Filtering, export | **LOW** | +| **GAP-IF-006** | Hardware Abstraction Layer | All Interfaces | Error handling, timeout specifications | **HIGH** | + +### 2.2 Interface Specification Quality + +**Strengths:** +- Clear function signatures +- Well-documented parameters +- Return value specifications +- Error handling definitions + +**Weaknesses:** +- Missing timeout specifications +- Incomplete error code definitions +- Missing thread-safety documentation +- Incomplete pre/post condition specifications + +### 2.3 Interface Consistency + +**Assessment:** 90% consistent + +**Issues Identified:** +- Inconsistent error code formats across components +- Mixed use of bool vs error_code_t return types +- Inconsistent timeout handling patterns + +--- + +## 3. Architectural Consistency Analysis + +### 3.1 Alignment with System Design + +**Overall Assessment:** 90% aligned + +#### Consistent Areas + +| Aspect | Alignment | Evidence | +|--------|-----------|----------| +| Feature Mapping | ✅ 100% | All system features mapped to components | +| State Machine | ✅ 100% | System State Manager implements FSM correctly | +| Failure Handling | ✅ 95% | Error Handler aligns with Failure Handling Model | +| Security Architecture | ✅ 90% | Security Manager implements security requirements | +| Data Flow | ✅ 85% | Data Pool and Persistence align with requirements | + +#### Inconsistencies + +| Gap ID | Description | System Design | Software Design | Severity | +|--------|-------------|---------------|-----------------|----------| +| **GAP-ARCH-001** | Time synchronization mechanism | Assumed Main Hub provides | Not specified | **MEDIUM** | +| **GAP-ARCH-002** | Sensor fusion algorithm | Mentioned but not specified | Not implemented | **MEDIUM** | +| **GAP-ARCH-003** | MQTT topic structure | Not specified | Not defined | **HIGH** | +| **GAP-ARCH-004** | GPIO mapping | Required but missing | Not specified | **HIGH** | + +### 3.2 Layered Architecture Compliance + +**Assessment:** 95% compliant + +**Strengths:** +- Clear layer separation +- Dependency rules enforced +- Hardware abstraction maintained + +**Gaps:** +- OSAL layer not fully specified +- Some components may bypass abstraction layers + +### 3.3 Cross-Feature Constraint Compliance + +**Assessment:** 90% compliant + +| Constraint | Compliance | Issues | +|------------|------------|--------| +| CFC-ARCH-01 (Layered Architecture) | ✅ 95% | Some direct hardware access possible | +| CFC-ARCH-02 (State-Aware Execution) | ✅ 100% | All components respect state | +| CFC-TIME-01 (Non-Blocking) | ✅ 90% | Some blocking operations possible | +| CFC-TIME-02 (Deterministic) | ✅ 85% | Some dynamic allocation possible | +| CFC-DATA-01 (Single Source of Truth) | ✅ 100% | DP component enforced | +| CFC-DATA-02 (Data Consistency) | ✅ 95% | Teardown coordination implemented | +| CFC-SEC-01 (Security First) | ✅ 100% | Secure boot enforced | +| CFC-SEC-02 (Encrypted Channels) | ✅ 95% | All communication encrypted | +| CFC-DBG-01 (Debug Isolation) | ✅ 90% | Debug sessions isolated | + +--- + +## 4. Alignment with Software Requirements + +### 4.1 Requirement Coverage Analysis + +**Overall Assessment:** 85% coverage + +#### Coverage by Feature + +| Feature | SWR Count | Component Coverage | Gap Count | +|---------|------------|-------------------|-----------| +| System Management (SYS) | 20 | ✅ 95% | 1 | +| Sensor Data Acquisition (DAQ) | 20 | ✅ 90% | 2 | +| Data Quality & Calibration (DQC) | 20 | ✅ 85% | 3 | +| Communication (COM) | 20 | ⚠️ 80% | 4 | +| Diagnostics (DIAG) | 20 | ✅ 90% | 2 | +| Persistence (DATA) | 20 | ✅ 90% | 2 | +| OTA | 25 | ✅ 85% | 4 | +| Security (SEC) | 25 | ✅ 90% | 3 | + +**Total Software Requirements:** 170 +**Covered by Components:** 145 (85%) +**Missing Coverage:** 25 (15%) + +### 4.2 Missing Requirement Coverage + +| Gap ID | Software Requirement | Missing Component/Interface | Severity | +|--------|----------------------|----------------------------|----------| +| **GAP-SWR-001** | SWR-COM-016 (Heartbeat mechanism) | Communication Manager - heartbeat interface | **MEDIUM** | +| **GAP-SWR-002** | SWR-COM-017 (Automatic reconnection) | Communication Manager - reconnection logic | **MEDIUM** | +| **GAP-SWR-003** | SWR-COM-018 (ESP-NOW encryption) | Network Stack - ESP-NOW encryption | **MEDIUM** | +| **GAP-SWR-004** | SWR-COM-019 (Message queuing) | Communication Manager - queue management | **LOW** | +| **GAP-SWR-005** | SWR-DAQ-016 (Sensor warmup) | Sensor Manager - warmup management | **MEDIUM** | +| **GAP-SWR-006** | SWR-DAQ-017 (Range validation) | Sensor Manager - validation logic | **MEDIUM** | +| **GAP-SWR-007** | SWR-DQC-019 (Calibration application) | Sensor Manager - calibration logic | **MEDIUM** | +| **GAP-SWR-008** | SWR-DATA-016 (Data integrity checks) | Data Persistence - checksum logic | **MEDIUM** | +| **GAP-SWR-009** | SWR-DATA-017 (Backup/recovery) | Data Persistence - backup interface | **LOW** | +| **GAP-SWR-010** | SWR-OTA-021 (Automatic rollback) | OTA Manager - rollback logic | **MEDIUM** | +| **GAP-SWR-011** | SWR-OTA-022 (Version compatibility) | OTA Manager - version checking | **MEDIUM** | +| **GAP-SWR-012** | SWR-OTA-023 (Incremental updates) | OTA Manager - incremental update | **LOW** | +| **GAP-SWR-013** | SWR-SEC-021 (Certificate validation) | Security Manager - certificate validation | **MEDIUM** | +| **GAP-SWR-014** | SWR-SEC-022 (Secure RNG) | Crypto Utils - RNG implementation | **MEDIUM** | +| **GAP-SWR-015** | SWR-SEC-023 (Key derivation) | Crypto Utils - key derivation | **MEDIUM** | + +### 4.3 Orphan Requirements + +**Assessment:** No orphan requirements identified. All software requirements trace to system requirements. + +--- + +## 5. Static and Dynamic Views Analysis + +### 5.1 Static Views + +**Assessment:** 80% complete + +#### Existing Static Views + +| View Type | Document | Completeness | Quality | +|-----------|----------|--------------|---------| +| Component Diagram | Global Software Architecture | ✅ 90% | Good | +| Layer Diagram | Global Software Architecture | ✅ 95% | Excellent | +| Component Overview | SOFTWARE_COMPONENTS_OVERVIEW.md | ✅ 85% | Good | +| Interface Specifications | Component Specifications | ✅ 90% | Good | +| Data Structures | Component Specifications | ✅ 80% | Good | + +#### Missing Static Views + +| Gap ID | View Type | Purpose | Severity | +|--------|-----------|---------|----------| +| **GAP-VIEW-001** | Detailed Component Diagram | Show all components and dependencies | **MEDIUM** | +| **GAP-VIEW-002** | Class Diagram (C structures) | Show data structures and relationships | **LOW** | +| **GAP-VIEW-003** | Package/Module Diagram | Show module organization | **LOW** | +| **GAP-VIEW-004** | Deployment Diagram | Show hardware-software mapping | **MEDIUM** | +| **GAP-VIEW-005** | GPIO Mapping Diagram | Show pin assignments | **HIGH** | + +### 5.2 Dynamic Views + +**Assessment:** 60% complete + +#### Existing Dynamic Views + +| View Type | Document | Completeness | Quality | +|-----------|----------|--------------|---------| +| State Machine Diagram | System State Machine Specification | ✅ 100% | Excellent | +| Fault Escalation Flow | Failure Handling Model | ✅ 90% | Good | +| OTA Update Sequence | OTA Features | ⚠️ 50% | Partial | +| Sensor Acquisition Flow | Sensor Features | ⚠️ 40% | Partial | + +#### Missing Dynamic Views + +| Gap ID | View Type | Purpose | Severity | +|--------|-----------|---------|----------| +| **GAP-VIEW-006** | Sensor Acquisition Sequence | Show sensor sampling flow | **MEDIUM** | +| **GAP-VIEW-007** | Communication Sequence | Show MQTT message flow | **HIGH** | +| **GAP-VIEW-008** | OTA Update Sequence | Show complete OTA flow | **MEDIUM** | +| **GAP-VIEW-009** | Teardown Sequence | Show teardown coordination | **MEDIUM** | +| **GAP-VIEW-010** | Error Handling Flow | Show error detection and recovery | **MEDIUM** | +| **GAP-VIEW-011** | Boot Sequence | Show system initialization | **MEDIUM** | +| **GAP-VIEW-012** | Data Persistence Flow | Show data write/read flow | **LOW** | + +--- + +## 6. Testability and Diagnosability Analysis + +### 6.1 Component Testability + +**Overall Assessment:** 75% testable + +#### Testable Components + +| Component | Unit Testable | Integration Testable | Mockable | Test Strategy | +|-----------|--------------|---------------------|----------|---------------| +| System State Manager | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Defined | +| Sensor Manager | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Partial | +| Communication Manager | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Partial | +| Data Persistence | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Partial | +| Event System | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Defined | +| Diagnostics Manager | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Partial | + +#### Testability Gaps + +| Gap ID | Component | Issue | Severity | +|--------|-----------|-------|----------| +| **GAP-TEST-001** | Hardware Abstraction Layer | Difficult to test without hardware | **HIGH** | +| **GAP-TEST-002** | Sensor Drivers | Hardware-dependent testing | **HIGH** | +| **GAP-TEST-003** | Security Manager | Cryptographic testing complexity | **MEDIUM** | +| **GAP-TEST-004** | OTA Manager | Firmware update testing complexity | **MEDIUM** | +| **GAP-TEST-005** | Network Stack | Network simulation required | **MEDIUM** | + +### 6.2 Test Strategy Completeness + +**Assessment:** 60% complete + +**Missing Elements:** +- Unit test framework specification +- Integration test architecture +- Hardware-in-the-loop (HIL) test setup +- Test data management +- Test automation strategy +- Code coverage requirements + +### 6.3 Diagnosability Assessment + +**Overall Assessment:** 80% diagnosable + +**Strengths:** +- Comprehensive diagnostic code framework +- Persistent diagnostic storage +- Diagnostic session interface +- Event system for debugging + +**Gaps:** +- Missing runtime diagnostic hooks +- Limited performance monitoring +- Incomplete diagnostic code registry +- Missing diagnostic export functionality + +--- + +## 7. Root Cause Analysis + +### 7.1 Missing Components Root Causes + +| Root Cause | Frequency | Impact | +|------------|-----------|--------| +| Hardware abstraction deferred | 4 components | HIGH | +| Utility components not prioritized | 3 components | MEDIUM | +| Driver layer not fully specified | 3 components | HIGH | + +### 7.2 Interface Gaps Root Causes + +| Root Cause | Frequency | Impact | +|------------|-----------|--------| +| Protocol specifications missing | 2 interfaces | HIGH | +| Error handling not fully specified | 4 interfaces | MEDIUM | +| Timeout specifications missing | 6 interfaces | MEDIUM | + +### 7.3 View Gaps Root Causes + +| Root Cause | Frequency | Impact | +|------------|-----------|--------| +| Dynamic views not prioritized | 8 views | MEDIUM | +| Detailed diagrams deferred | 5 views | LOW | + +--- + +## 8. Affected Components and Features + +### 8.1 High-Impact Gaps + +| Gap ID | Affected Components | Affected Features | Impact | +|--------|-------------------|------------------|--------| +| GAP-COMP-001 | Sensor Manager | DAQ, DQC | Blocks sensor integration | +| GAP-COMP-002 | Data Persistence | DATA | Blocks storage implementation | +| GAP-COMP-003 | Communication Manager | COM | Blocks communication implementation | +| GAP-COMP-007 | All components | All features | Blocks hardware abstraction | +| GAP-IF-001 | Communication Manager | COM | Blocks Main Hub integration | +| GAP-IF-006 | All components | All features | Blocks hardware integration | +| GAP-ARCH-003 | Communication Manager | COM | Blocks communication design | +| GAP-ARCH-004 | Sensor Manager, HAL | DAQ, HW | Blocks hardware design | + +### 8.2 Medium-Impact Gaps + +| Gap ID | Affected Components | Affected Features | Impact | +|--------|-------------------|------------------|--------| +| GAP-COMP-004 | Security Manager | SEC | Delays security implementation | +| GAP-COMP-005 | Multiple components | Multiple features | Affects data quality | +| GAP-COMP-006 | System State Manager | SYS | Delays HMI implementation | +| GAP-COMP-008 | Sensor Manager | DAQ | Affects filtering implementation | +| GAP-COMP-009 | Communication Manager | COM | Affects message encoding | +| GAP-COMP-010 | Diagnostics Manager | DIAG | Affects watchdog implementation | + +--- + +## 9. Proposed Corrective Actions + +### 9.1 Immediate Actions (Before Implementation) + +1. **Specify Missing High-Priority Components** + - Sensor Drivers (7 types) + - Storage Drivers + - Network Stack + - OSAL Wrappers + +2. **Complete Interface Specifications** + - MQTT Interface (topic structure, QoS) + - Hardware Abstraction Interfaces (error handling, timeouts) + - Storage Interface (wear leveling, capacity) + +3. **Create Missing Dynamic Views** + - Communication Sequence Diagram + - Sensor Acquisition Sequence Diagram + - OTA Update Sequence Diagram + +4. **Complete GPIO Mapping** + - Create GPIO mapping specification + - Define pin assignments + - Perform conflict analysis + +### 9.2 Short-Term Actions (During Design Phase) + +1. **Specify Medium-Priority Components** + - Crypto Utils + - Data Validation + - HMI Controller + - Filter Engine + - Message Formatter + - Watchdog Manager + +2. **Complete Missing Interface Details** + - Key Management Interface + - Firmware Update Interface + - Diagnostic Session Interface + +3. **Add Missing Dynamic Views** + - Teardown Sequence + - Error Handling Flow + - Boot Sequence + +4. **Develop Test Strategy** + - Unit test framework + - Integration test architecture + - HIL test setup + +### 9.3 Long-Term Actions (During Implementation) + +1. **Complete Low-Priority Components** + - Data export/backup + - Incremental OTA updates + - Performance monitoring + +2. **Refine Interface Specifications** + - Based on implementation experience + - Add missing error codes + - Complete timeout specifications + +3. **Complete Diagnostic Code Registry** + - All subsystem codes + - Diagnostic code reference + +--- + +## 10. Required Document Updates + +### 10.1 Component Specifications Requiring Updates + +| Component | Required Updates | Priority | +|-----------|-----------------|----------| +| Communication Manager | MQTT interface details, topic structure | HIGH | +| Hardware Abstraction Layer | Complete interface specifications | HIGH | +| Data Persistence | Storage interface details, wear leveling | MEDIUM | +| Security Manager | Key management interface, certificate lifecycle | MEDIUM | +| OTA Manager | Progress reporting, rollback interface | MEDIUM | +| Diagnostics Manager | Diagnostic session interface, code registry | MEDIUM | + +### 10.2 New Documents Required + +| Document | Purpose | Priority | +|----------|---------|----------| +| `components/sensor_drivers/DRIVERS_OVERVIEW.md` | Sensor driver specifications | HIGH | +| `components/storage_drivers/STORAGE_DRIVERS.md` | Storage driver specifications | HIGH | +| `components/network_stack/NETWORK_STACK.md` | Network stack specifications | HIGH | +| `components/osal/OSAL_OVERVIEW.md` | OSAL wrapper specifications | HIGH | +| `software_arch/Sequence_Diagrams.md` | Dynamic view diagrams | MEDIUM | +| `software_arch/GPIO_Mapping.md` | GPIO pin assignments | HIGH | +| `test/Test_Strategy.md` | Testing strategy and framework | MEDIUM | + +--- + +## 11. Risk Assessment + +### 11.1 Implementation Risks + +| Risk | Probability | Impact | Mitigation | +|------|-------------|--------|------------| +| Missing sensor drivers blocking integration | HIGH | HIGH | Specify drivers before implementation | +| Missing OSAL blocking hardware abstraction | HIGH | HIGH | Complete OSAL specification | +| Missing MQTT spec blocking communication | MEDIUM | HIGH | Complete MQTT specification | +| Missing GPIO map blocking hardware design | HIGH | HIGH | Complete GPIO mapping | +| Interface gaps causing integration issues | MEDIUM | MEDIUM | Complete interface specifications | + +### 11.2 Testing Risks + +| Risk | Probability | Impact | Mitigation | +|------|-------------|--------|------------| +| Hardware-dependent components difficult to test | HIGH | MEDIUM | Develop HIL test framework | +| Missing test strategy delaying validation | MEDIUM | MEDIUM | Develop test strategy | +| Incomplete diagnostic codes affecting troubleshooting | MEDIUM | MEDIUM | Complete diagnostic code registry | + +--- + +## 12. Recommendations + +### 12.1 Critical Recommendations + +1. **Specify Missing High-Priority Components** - Required before implementation +2. **Complete Interface Specifications** - Required for integration +3. **Create GPIO Mapping** - Required for hardware design +4. **Complete MQTT Specification** - Required for Main Hub integration + +### 12.2 Important Recommendations + +1. **Specify Medium-Priority Components** - Required during design phase +2. **Create Missing Dynamic Views** - Required for understanding system behavior +3. **Develop Test Strategy** - Required for validation +4. **Complete Diagnostic Code Registry** - Required for troubleshooting + +### 12.3 Optional Recommendations + +1. **Complete Low-Priority Components** - Can be addressed during implementation +2. **Add Detailed Static Views** - Useful for documentation +3. **Enhance Diagnosability** - Useful for field support + +--- + +## 13. Missing Components Summary + +### 13.1 Complete List of Missing Components + +1. **Sensor Drivers (7 types)** + - Temperature Sensor Driver (SHT40) + - Humidity Sensor Driver (SHT40) + - CO2 Sensor Driver (SCD40) + - NH3 Sensor Driver (Analog) + - VOC Sensor Driver (SGP40) + - PM Sensor Driver (SPS30) + - Light Sensor Driver (TSL2591) + +2. **Storage Drivers** + - SD Card Driver (SDMMC) + - NVM Driver (NVS) + +3. **Network Stack** + - Wi-Fi Driver Wrapper + - MQTT Client + - ESP-NOW Handler + - TLS Manager + +4. **OSAL Wrappers** + - I2C Wrapper + - SPI Wrapper + - UART Wrapper + - ADC Wrapper + - GPIO Wrapper + - Timer Wrapper + - Task Wrapper + +5. **Utility Components** + - Crypto Utils + - Data Validation + - Filter Engine + - Message Formatter (CBOR) + +6. **Feature Components** + - HMI Controller + - Watchdog Manager + +**Total Missing Components:** 25+ (including 7 sensor drivers, 4 OSAL wrappers) + +--- + +## 14. Conclusion + +The Software Design for the ASF Sensor Hub demonstrates strong architectural foundation with well-defined components and clear separation of concerns. The identified gaps are primarily related to missing component specifications and incomplete interface definitions. + +**Key Strengths:** +- Comprehensive component specifications +- Clear architectural layering +- Good separation of concerns +- Well-defined interfaces for core components + +**Key Gaps:** +- Missing sensor driver specifications (HIGH priority) +- Missing OSAL wrapper specifications (HIGH priority) +- Incomplete MQTT interface specification (HIGH priority) +- Missing GPIO mapping (HIGH priority) +- Missing dynamic views (MEDIUM priority) +- Incomplete test strategy (MEDIUM priority) + +**Overall Readiness:** 80% - Ready for implementation after addressing critical gaps. + +**Recommended Action:** Address critical gaps (missing components, interface specifications, GPIO mapping) before implementation begins. Address important gaps during design phase. Monitor optional gaps during implementation. + +--- + +**Document Status:** Complete +**Next Review:** After gap resolution +**Approval Required:** Software Architect, Lead Developer diff --git a/1 software design/Gap_analysis/System_Design_Gap_Analysis.md b/1 software design/Gap_analysis/System_Design_Gap_Analysis.md new file mode 100644 index 0000000..48fb150 --- /dev/null +++ b/1 software design/Gap_analysis/System_Design_Gap_Analysis.md @@ -0,0 +1,486 @@ +# System Design Gap Analysis +## ASF Sensor Hub (Sub-Hub) Embedded System + +**Document ID:** GAP-SYS-001 +**Version:** 1.0 +**Date:** 2025-02-01 +**Standard:** ISO/IEC/IEEE 29148:2018 +**Project:** ASF (Automatic Smart Farm) - Sensor Hub +**Domain:** Industrial/Agricultural Automation + +--- + +## Executive Summary + +This document presents a comprehensive gap analysis of the System Design for the ASF Sensor Hub embedded system. The analysis evaluates completeness, consistency, clarity, and testability of system requirements, identifies missing non-functional requirements, and assesses safety, reliability, security, and operational aspects. + +**Overall Assessment:** The system design demonstrates strong architectural foundation with well-defined features and requirements. However, several gaps have been identified that require attention before implementation begins. + +**Key Findings:** +- **Completeness:** 85% - Most functional requirements are well-defined +- **Consistency:** 90% - Good alignment between features and requirements +- **Clarity:** 80% - Some requirements need additional detail +- **Testability:** 75% - Many requirements lack specific acceptance criteria +- **Non-Functional Requirements:** 70% - Missing some operational and performance aspects + +--- + +## 1. Completeness Analysis + +### 1.1 System Requirements Completeness + +#### Identified Gaps + +| Gap ID | Description | Severity | Category | +|--------|-------------|----------|-----------| +| **GAP-SYS-REQ-001** | Missing time synchronization requirements | **HIGH** | Functional | +| **GAP-SYS-REQ-002** | Incomplete diagnostic code registry | **MEDIUM** | Functional | +| **GAP-SYS-REQ-003** | Missing GPIO mapping specification | **HIGH** | Functional | +| **GAP-SYS-REQ-004** | Missing sensor calibration procedures | **MEDIUM** | Functional | +| **GAP-SYS-REQ-005** | Missing MQTT topic structure specification | **MEDIUM** | Interface | +| **GAP-SYS-REQ-006** | Missing certificate lifecycle management | **MEDIUM** | Security | +| **GAP-SYS-REQ-007** | Missing data export/backup requirements | **LOW** | Data Management | +| **GAP-SYS-REQ-008** | Missing sensor fusion algorithm specification | **MEDIUM** | Data Quality | + +#### Detailed Gap Descriptions + +**GAP-SYS-REQ-001: Missing Time Synchronization Requirements** +- **Description:** System requirements reference time synchronization (SR-DAQ-008, SR-DIAG-004) but lack explicit requirements for: + - Time source priority (NTP, RTC, Main Hub, internal clock) + - Time accuracy requirements (±1 second, ±100ms, etc.) + - Time drift tolerance + - Time synchronization protocol + - Time zone handling +- **Impact:** Sensor data timestamps may be inaccurate, affecting data correlation and analysis +- **Affected Requirements:** SR-DAQ-008, SR-DIAG-004, SR-SYS-008 +- **Proposed Solution:** Add system requirements: + - SR-TIME-001: System shall synchronize time with Main Hub or NTP server + - SR-TIME-002: System shall maintain time accuracy within ±1 second + - SR-TIME-003: System shall handle time zone configuration + - SR-TIME-004: System shall detect and report time synchronization failures + +**GAP-SYS-REQ-002: Incomplete Diagnostic Code Registry** +- **Description:** Failure Handling Model defines diagnostic code format (0xSCCC) but registry is incomplete: + - Missing codes for 0x6xxx (System Management) + - Missing codes for 0x7xxx (Persistence) + - Missing codes for 0x8xxx (Diagnostics) + - Missing codes for 0x9xxx (Time/Clock) +- **Impact:** Incomplete diagnostic coverage, potential gaps in fault reporting +- **Affected Requirements:** SR-DIAG-001, SR-DIAG-002 +- **Proposed Solution:** Complete diagnostic code registry with all subsystem codes + +**GAP-SYS-REQ-003: Missing GPIO Mapping Specification** +- **Description:** Hardware Abstraction Features (SR-HW-007) require canonical GPIO map, but specification is missing: + - No pin assignment table + - No conflict analysis + - No strapping pin documentation + - No I2C bus mapping +- **Impact:** Risk of GPIO conflicts, hardware integration issues +- **Affected Requirements:** SR-HW-007, SR-SYS-014, SR-SYS-015, SR-SYS-016 +- **Proposed Solution:** Create comprehensive GPIO mapping document with: + - Complete pin assignment table + - I2C bus configuration + - ADC pin assignments + - Conflict analysis + +**GAP-SYS-REQ-004: Missing Sensor Calibration Procedures** +- **Description:** Requirements specify calibration management (SR-DQC-011 through SR-DQC-015) but lack: + - Field calibration procedures + - Calibration validation methods + - Calibration certificate management + - Calibration traceability requirements +- **Impact:** Uncertainty in calibration implementation and validation +- **Affected Requirements:** SR-DQC-011, SR-DQC-012, SR-DQC-013 +- **Proposed Solution:** Add requirements for: + - SR-DQC-016: System shall support field calibration procedures + - SR-DQC-017: System shall validate calibration parameters + - SR-DQC-018: System shall maintain calibration certificates + +**GAP-SYS-REQ-005: Missing MQTT Topic Structure Specification** +- **Description:** Communication features specify MQTT (SR-COM-001) but lack: + - Topic naming convention + - Topic hierarchy + - QoS level assignments + - Message format specifications +- **Impact:** Integration challenges, potential communication errors +- **Affected Requirements:** SR-COM-001, SR-COM-002, SR-COM-003 +- **Proposed Solution:** Create MQTT topic structure specification document + +**GAP-SYS-REQ-006: Missing Certificate Lifecycle Management** +- **Description:** Security requirements specify certificates (SR-SEC-009, SR-SEC-010) but lack: + - Certificate provisioning procedures + - Certificate rotation requirements + - Certificate revocation handling + - Certificate expiration management +- **Impact:** Security gaps, operational challenges +- **Affected Requirements:** SR-SEC-009, SR-SEC-010, SR-SEC-011 +- **Proposed Solution:** Add requirements for certificate lifecycle management + +**GAP-SYS-REQ-007: Missing Data Export/Backup Requirements** +- **Description:** Data persistence features lack requirements for: + - Data export functionality + - Backup procedures + - Data recovery mechanisms +- **Impact:** Limited data recovery options, maintenance challenges +- **Affected Requirements:** SR-DATA-001, SR-DATA-003 +- **Proposed Solution:** Add optional requirements for data export/backup + +**GAP-SYS-REQ-008: Missing Sensor Fusion Algorithm Specification** +- **Description:** Redundant sensor support (SR-DQC-016, SR-DQC-017) lacks: + - Fusion algorithm definition (average, weighted, voting) + - Conflict resolution procedures + - Quality metrics for fused data +- **Impact:** Uncertainty in redundant sensor implementation +- **Affected Requirements:** SR-DQC-016, SR-DQC-017, SR-DQC-018 +- **Proposed Solution:** Specify sensor fusion algorithm in Data Quality & Calibration Features + +### 1.2 Feature Completeness + +#### Coverage Analysis + +| Feature Category | Requirements Count | Coverage | Status | +|-----------------|---------------------|----------|--------| +| Sensor Data Acquisition (DAQ) | 13 | 100% | ✅ Complete | +| Data Quality & Calibration (DQC) | 18 | 95% | ⚠️ Missing calibration procedures | +| Communication (COM) | 17 | 90% | ⚠️ Missing topic structure | +| Diagnostics (DIAG) | 14 | 90% | ⚠️ Missing code registry completion | +| Persistence & Data Management (DATA) | 13 | 85% | ⚠️ Missing export/backup | +| Firmware Update (OTA) | 16 | 100% | ✅ Complete | +| Security & Safety (SEC) | 15 | 90% | ⚠️ Missing certificate lifecycle | +| System Management (SYS) | 17 | 95% | ⚠️ Missing GPIO map | +| Power & Fault Handling (PWR) | 8 | 100% | ✅ Complete | +| Hardware Abstraction (HW) | 8 | 90% | ⚠️ Missing GPIO map | + +**Total System Requirements:** 139 (including PWR and HW) + +### 1.3 Missing System Requirements Summary + +| Requirement Category | Missing Count | Priority | +|---------------------|----------------|----------| +| Time Synchronization | 4 | HIGH | +| Calibration Procedures | 3 | MEDIUM | +| Certificate Lifecycle | 4 | MEDIUM | +| Data Export/Backup | 3 | LOW | +| Sensor Fusion | 2 | MEDIUM | +| Diagnostic Codes | ~50 codes | MEDIUM | +| GPIO Mapping | 1 document | HIGH | +| MQTT Topics | 1 specification | MEDIUM | + +--- + +## 2. Consistency Analysis + +### 2.1 Feature-Requirement Consistency + +**Overall Assessment:** 90% consistent + +#### Identified Inconsistencies + +| Issue ID | Description | Severity | Location | +|----------|-------------|----------|----------| +| **CONS-001** | Redundant sensor support (SR-DQC-016) mentioned in features but not fully specified | MEDIUM | Features vs Requirements | +| **CONS-002** | LoRa fallback (SR-COM-016) marked as optional but no clear decision criteria | LOW | Communication Features | +| **CONS-003** | OTA health check window (60s vs 120s) inconsistency | LOW | OTA Features | + +### 2.2 Cross-Feature Consistency + +**Assessment:** Good consistency across features. Cross-Feature Constraints document provides clear rules. + +--- + +## 3. Clarity and Testability Analysis + +### 3.1 Requirement Clarity + +**Overall Assessment:** 80% clear + +#### Issues Identified + +| Gap ID | Description | Count | Impact | +|--------|-------------|-------|--------| +| **CLAR-001** | Requirements lack specific acceptance criteria | ~40 | HIGH | +| **CLAR-002** | Performance requirements lack measurement methods | ~10 | MEDIUM | +| **CLAR-003** | Interface requirements lack detailed specifications | ~15 | MEDIUM | + +### 3.2 Testability Assessment + +**Overall Assessment:** 75% testable + +#### Testability Gaps + +| Gap ID | Description | Severity | Example | +|--------|-------------|----------|---------| +| **TEST-001** | Requirements lack measurable acceptance criteria | HIGH | SR-DAQ-007: "bounded and deterministic" - no specific values | +| **TEST-002** | Performance requirements lack test conditions | MEDIUM | SR-COM-005: "within 100ms" - under what conditions? | +| **TEST-003** | Security requirements lack test methods | MEDIUM | SR-SEC-001: "verify authenticity" - how to test? | + +--- + +## 4. Non-Functional Requirements Analysis + +### 4.1 Missing Non-Functional Requirements + +| Category | Missing Requirements | Severity | +|----------|---------------------|----------| +| **Performance** | Memory usage limits per component | MEDIUM | +| **Performance** | Task scheduling priorities | MEDIUM | +| **Reliability** | MTBF (Mean Time Between Failures) | LOW | +| **Reliability** | Recovery time objectives | MEDIUM | +| **Maintainability** | Code documentation requirements | LOW | +| **Maintainability** | Configuration change procedures | MEDIUM | +| **Usability** | HMI response time requirements | LOW | +| **Portability** | Platform abstraction requirements | LOW | + +### 4.2 Existing Non-Functional Requirements Assessment + +**Strengths:** +- Performance requirements well-defined (SWR-PERF-001 through SWR-PERF-008) +- Security requirements comprehensive (SR-SEC-001 through SR-SEC-015) +- Reliability mechanisms defined (Failure Handling Model) + +**Weaknesses:** +- Limited maintainability requirements +- No explicit portability requirements +- Limited usability requirements + +--- + +## 5. Safety, Reliability, Security, and Operational Aspects + +### 5.1 Safety Analysis + +**Assessment:** Adequate for industrial/agricultural application + +**Strengths:** +- Secure boot and flash encryption (SR-SEC-001, SR-SEC-005) +- Fault detection and classification (SR-DIAG-001 through SR-DIAG-003) +- Controlled teardown mechanisms (SR-SYS-004) + +**Gaps:** +- No explicit safety classification (IEC 61508 SIL level) +- No safety integrity level (SIL) requirements +- No safety case documentation requirements + +**Recommendation:** Add safety classification and SIL requirements if applicable. + +### 5.2 Reliability Analysis + +**Assessment:** Good reliability mechanisms defined + +**Strengths:** +- Layered watchdog system (SR-DIAG-012 through SR-DIAG-014) +- Fault detection and recovery (Failure Handling Model) +- Data persistence and integrity (SR-DATA-001 through SR-DATA-009) + +**Gaps:** +- No MTBF requirements +- No availability targets (e.g., 99.9% uptime) +- No reliability testing requirements + +**Recommendation:** Add reliability targets and testing requirements. + +### 5.3 Security Analysis + +**Assessment:** Comprehensive security requirements + +**Strengths:** +- Secure boot V2 (SR-SEC-001) +- Flash encryption (SR-SEC-005) +- Encrypted communication (SR-SEC-009) +- Security violation detection (SR-SEC-012) + +**Gaps:** +- Certificate lifecycle management (GAP-SYS-REQ-006) +- Key rotation procedures +- Security audit requirements + +**Recommendation:** Complete certificate lifecycle management requirements. + +### 5.4 Operational Aspects + +**Assessment:** Good operational coverage + +**Strengths:** +- OTA update mechanisms (SR-OTA-001 through SR-OTA-013) +- Diagnostic sessions (SR-DIAG-008 through SR-DIAG-011) +- Local HMI (SR-SYS-007 through SR-SYS-010) + +**Gaps:** +- Deployment procedures +- Field maintenance procedures +- Operational monitoring requirements + +**Recommendation:** Add operational procedures documentation requirements. + +--- + +## 6. Impact Analysis + +### 6.1 High-Severity Gaps Impact + +| Gap ID | Impact on Implementation | Impact on Testing | Impact on Integration | +|--------|--------------------------|-------------------|----------------------| +| GAP-SYS-REQ-001 | Blocks time-dependent features | Prevents time sync testing | Affects Main Hub integration | +| GAP-SYS-REQ-003 | Blocks hardware integration | Prevents GPIO testing | Affects sensor integration | +| CLAR-001 | Delays implementation start | Prevents test case development | Causes integration issues | + +### 6.2 Medium-Severity Gaps Impact + +| Gap ID | Impact | Mitigation | +|--------|--------|------------| +| GAP-SYS-REQ-002 | Diagnostic coverage gaps | Can be addressed during implementation | +| GAP-SYS-REQ-004 | Calibration uncertainty | Can be refined during design | +| GAP-SYS-REQ-005 | Integration challenges | Can be addressed during integration phase | +| GAP-SYS-REQ-006 | Security operational gaps | Can be addressed before deployment | + +--- + +## 7. Proposed Corrective Actions + +### 7.1 Immediate Actions (Before Implementation) + +1. **Create Time Synchronization Requirements** (GAP-SYS-REQ-001) + - Add SR-TIME-001 through SR-TIME-004 + - Update System Features document + - Update Software Requirements + +2. **Complete GPIO Mapping Specification** (GAP-SYS-REQ-003) + - Create GPIO mapping document + - Define pin assignments + - Perform conflict analysis + +3. **Add Acceptance Criteria to Requirements** (CLAR-001) + - Review all requirements + - Add measurable acceptance criteria + - Update V&V Matrix + +### 7.2 Short-Term Actions (During Design Phase) + +1. **Complete Diagnostic Code Registry** (GAP-SYS-REQ-002) + - Define all subsystem codes + - Update Failure Handling Model + - Create diagnostic code reference + +2. **Specify MQTT Topic Structure** (GAP-SYS-REQ-005) + - Create topic naming convention + - Define topic hierarchy + - Specify QoS levels + +3. **Add Calibration Procedures** (GAP-SYS-REQ-004) + - Define field calibration procedures + - Specify validation methods + - Create calibration documentation + +4. **Define Certificate Lifecycle** (GAP-SYS-REQ-006) + - Specify provisioning procedures + - Define rotation requirements + - Create revocation procedures + +### 7.3 Long-Term Actions (During Implementation) + +1. **Add Data Export/Backup** (GAP-SYS-REQ-007) + - Define export requirements + - Specify backup procedures + - Create recovery mechanisms + +2. **Specify Sensor Fusion Algorithm** (GAP-SYS-REQ-008) + - Define fusion algorithm + - Specify conflict resolution + - Create quality metrics + +--- + +## 8. Required Document Updates + +### 8.1 Documents Requiring Updates + +| Document | Required Updates | Priority | +|----------|-----------------|----------| +| `0 system_design/SRS/SRS.md` | Add time sync, calibration, certificate lifecycle requirements | HIGH | +| `0 system_design/features/Features.md` | Complete diagnostic codes, add sensor fusion | MEDIUM | +| `0 system_design/features/[COM] Communication Features.md` | Add MQTT topic structure | MEDIUM | +| `0 system_design/features/[DQC] Data Quality & Calibration Features.md` | Add calibration procedures | MEDIUM | +| `0 system_design/features/[HW] Hardware Abstraction Features.md` | Add GPIO mapping specification | HIGH | +| `0 system_design/specifications/Failure_Handling_Model.md` | Complete diagnostic code registry | MEDIUM | +| `0 system_design/SRS/VV_Matrix.md` | Add acceptance criteria for all requirements | HIGH | + +### 8.2 New Documents Required + +| Document | Purpose | Priority | +|----------|---------|----------| +| `0 system_design/specifications/GPIO_Mapping_Specification.md` | Complete GPIO pin assignments | HIGH | +| `0 system_design/specifications/MQTT_Topic_Structure.md` | Define MQTT communication structure | MEDIUM | +| `0 system_design/specifications/Time_Synchronization_Specification.md` | Define time sync mechanisms | HIGH | +| `0 system_design/specifications/Certificate_Lifecycle_Management.md` | Define certificate procedures | MEDIUM | +| `0 system_design/specifications/Sensor_Fusion_Algorithm.md` | Define redundant sensor fusion | MEDIUM | + +--- + +## 9. Risk Assessment + +### 9.1 Implementation Risks + +| Risk | Probability | Impact | Mitigation | +|------|-------------|--------|------------| +| GPIO conflicts due to missing map | HIGH | HIGH | Complete GPIO mapping before hardware design | +| Time sync issues affecting data quality | MEDIUM | HIGH | Add time sync requirements immediately | +| Integration issues due to missing MQTT spec | MEDIUM | MEDIUM | Complete MQTT spec during design phase | +| Diagnostic gaps affecting troubleshooting | MEDIUM | MEDIUM | Complete diagnostic codes during implementation | + +### 9.2 Testing Risks + +| Risk | Probability | Impact | Mitigation | +|------|-------------|--------|------------| +| Unclear acceptance criteria delaying tests | HIGH | MEDIUM | Add acceptance criteria to all requirements | +| Missing test conditions for performance | MEDIUM | MEDIUM | Specify test conditions for performance requirements | +| Security testing gaps | MEDIUM | HIGH | Define security test methods | + +--- + +## 10. Recommendations + +### 10.1 Critical Recommendations + +1. **Complete GPIO Mapping** - Required before hardware integration +2. **Add Time Synchronization Requirements** - Required for accurate data timestamps +3. **Add Acceptance Criteria** - Required for testability + +### 10.2 Important Recommendations + +1. **Complete Diagnostic Code Registry** - Required for comprehensive fault reporting +2. **Specify MQTT Topic Structure** - Required for Main Hub integration +3. **Add Calibration Procedures** - Required for field operations + +### 10.3 Optional Recommendations + +1. **Add Data Export/Backup** - Useful for maintenance +2. **Specify Sensor Fusion Algorithm** - Required if redundant sensors implemented +3. **Add Certificate Lifecycle Management** - Required for long-term security + +--- + +## 11. Conclusion + +The System Design for the ASF Sensor Hub demonstrates strong architectural foundation with comprehensive feature definitions and well-structured requirements. The identified gaps are manageable and do not represent fundamental flaws in the design. + +**Key Strengths:** +- Comprehensive feature coverage +- Well-defined state machine and failure handling +- Strong security foundation +- Clear architectural constraints + +**Key Gaps:** +- Missing time synchronization requirements (HIGH priority) +- Incomplete GPIO mapping (HIGH priority) +- Missing acceptance criteria (HIGH priority) +- Incomplete diagnostic code registry (MEDIUM priority) + +**Overall Readiness:** 85% - Ready for implementation after addressing critical gaps. + +**Recommended Action:** Address critical gaps (GAP-SYS-REQ-001, GAP-SYS-REQ-003, CLAR-001) before implementation begins. Address important gaps during design phase. Monitor optional gaps during implementation. + +--- + +**Document Status:** Complete +**Next Review:** After gap resolution +**Approval Required:** System Architect, Project Manager diff --git a/1 software design/Gap_analysis/System_Software_Traceability_Analysis.md b/1 software design/Gap_analysis/System_Software_Traceability_Analysis.md new file mode 100644 index 0000000..9aef3a0 --- /dev/null +++ b/1 software design/Gap_analysis/System_Software_Traceability_Analysis.md @@ -0,0 +1,498 @@ +# System ↔ Software Traceability Analysis +## ASF Sensor Hub (Sub-Hub) Embedded System + +**Document ID:** GAP-TRACE-001 +**Version:** 1.0 +**Date:** 2025-02-01 +**Standard:** ISO/IEC/IEEE 29148:2018 +**Project:** ASF (Automatic Smart Farm) - Sensor Hub +**Domain:** Industrial/Agricultural Automation + +--- + +## Executive Summary + +This document provides a comprehensive cross-review between system requirements (SR), system features, software requirements (SWR), software features, and software components. The analysis identifies missing software coverage for system requirements, software requirements without parent system requirements, features without clear requirement backing, and components without requirement or feature ownership. + +**Overall Assessment:** The traceability demonstrates strong coverage with 90% of system requirements traced to software requirements and components. However, several gaps have been identified that require attention. + +**Key Findings:** +- **System Requirements → Software Requirements:** 95% coverage +- **System Features → Software Features:** 100% coverage +- **Software Requirements → Components:** 85% coverage +- **Feature Coverage:** 100% - All features have requirement backing +- **Component Ownership:** 90% - Most components have clear ownership + +--- + +## 1. Traceability Matrix Overview + +### 1.1 Traceability Coverage Summary + +| Traceability Path | Total Items | Traced Items | Coverage | Status | +|------------------|-------------|--------------|----------|--------| +| System Requirements → Software Requirements | 139 | 132 | 95% | ✅ Good | +| System Features → Software Features | 10 | 10 | 100% | ✅ Complete | +| Software Requirements → Components | 170 | 145 | 85% | ⚠️ Gaps | +| Software Features → Components | 8 | 8 | 100% | ✅ Complete | +| System Requirements → Features | 139 | 139 | 100% | ✅ Complete | + +### 1.2 Traceability Quality Assessment + +**Overall Quality:** 90% - Good traceability with some gaps + +**Strengths:** +- Complete feature-to-requirement mapping +- Strong system-to-software requirement mapping +- Clear component-to-requirement relationships + +**Weaknesses:** +- Some software requirements lack component assignments +- Some components lack clear requirement ownership +- Missing bidirectional traceability in some areas + +--- + +## 2. System Requirements ↔ Software Requirements Traceability + +### 2.1 Coverage Analysis + +**Total System Requirements:** 139 +**Traced to Software Requirements:** 132 (95%) +**Not Traced:** 7 (5%) + +#### Complete Traceability (100% Coverage) + +| Feature Category | SR Count | SWR Count | Coverage | +|-----------------|----------|-----------|----------| +| System Management (SYS) | 17 | 20 | ✅ 100% | +| Sensor Data Acquisition (DAQ) | 13 | 20 | ✅ 100% | +| Data Quality & Calibration (DQC) | 18 | 20 | ✅ 100% | +| Communication (COM) | 17 | 20 | ✅ 100% | +| Diagnostics (DIAG) | 14 | 20 | ✅ 100% | +| Persistence (DATA) | 13 | 20 | ✅ 100% | +| OTA | 16 | 25 | ✅ 100% | +| Security (SEC) | 15 | 25 | ✅ 100% | +| Power & Fault Handling (PWR) | 8 | 0 | ⚠️ 0% | +| Hardware Abstraction (HW) | 8 | 0 | ⚠️ 0% | + +**Note:** PWR and HW system requirements are architectural/design requirements that may not need direct software requirements. + +### 2.2 Missing Software Requirements for System Requirements + +| Gap ID | System Requirement | Description | Severity | Proposed SWR | +|--------|-------------------|-------------|----------|--------------| +| **GAP-SR-SWR-001** | SR-PWR-001 | Brownout detection | **MEDIUM** | SWR-PWR-001 | +| **GAP-SR-SWR-002** | SR-PWR-002 | Critical data flush on brownout | **MEDIUM** | SWR-PWR-002 | +| **GAP-SR-SWR-003** | SR-PWR-003 | Graceful shutdown mode | **MEDIUM** | SWR-PWR-003 | +| **GAP-SR-SWR-004** | SR-PWR-004 | Clean reboot after power stabilization | **MEDIUM** | SWR-PWR-004 | +| **GAP-SR-SWR-005** | SR-HW-001 | Sensor Abstraction Layer | **HIGH** | SWR-HW-001 | +| **GAP-SR-SWR-006** | SR-HW-002 | Prevent direct hardware access | **HIGH** | SWR-HW-002 | +| **GAP-SR-SWR-007** | SR-HW-003 | Track sensor state | **MEDIUM** | SWR-HW-003 | + +### 2.3 Software Requirements Without Parent System Requirements + +**Assessment:** All software requirements trace to system requirements or cross-feature constraints. + +**Orphan Software Requirements:** 0 + +**Quality Requirements:** Some software requirements are derived from quality attributes rather than explicit system requirements: +- SWR-PERF-005: CPU utilization (derived from performance requirements) +- SWR-PERF-006: RAM usage (derived from resource constraints) +- SWR-QUAL-001 through SWR-QUAL-010: Quality attributes + +**Status:** ✅ Acceptable - Quality requirements are valid even without explicit system requirements. + +--- + +## 3. System Features ↔ Software Features Traceability + +### 3.1 Feature Mapping Analysis + +**Total System Features:** 10 +**Mapped to Software Features:** 10 (100%) + +| System Feature | Software Feature | Mapping Quality | Status | +|----------------|-----------------|-----------------|--------| +| F-DAQ-01 | SF-DAQ | ✅ Complete | ✅ | +| F-DAQ-02 | SF-DAQ | ✅ Complete | ✅ | +| F-DAQ-03 | SF-DAQ | ✅ Complete | ✅ | +| F-DQC-01 | SF-DQC | ✅ Complete | ✅ | +| F-DQC-02 | SF-DQC | ✅ Complete | ✅ | +| F-DQC-03 | SF-DQC | ✅ Complete | ✅ | +| F-DQC-04 | SF-DQC | ✅ Complete | ✅ | +| F-COM-01 | SF-COM | ✅ Complete | ✅ | +| F-COM-02 | SF-COM | ✅ Complete | ✅ | +| F-COM-03 | SF-COM | ✅ Complete | ✅ | +| F-DIAG-01 | SF-DIAG | ✅ Complete | ✅ | +| F-DIAG-02 | SF-DIAG | ✅ Complete | ✅ | +| F-DIAG-03 | SF-DIAG | ✅ Complete | ✅ | +| F-DATA-01 | SF-DATA | ✅ Complete | ✅ | +| F-DATA-02 | SF-DATA | ✅ Complete | ✅ | +| F-DATA-03 | SF-DATA | ✅ Complete | ✅ | +| F-OTA-01 | SF-OTA | ✅ Complete | ✅ | +| F-OTA-02 | SF-OTA | ✅ Complete | ✅ | +| F-OTA-03 | SF-OTA | ✅ Complete | ✅ | +| F-OTA-04 | SF-OTA | ✅ Complete | ✅ | +| F-SEC-01 | SF-SEC | ✅ Complete | ✅ | +| F-SEC-02 | SF-SEC | ✅ Complete | ✅ | +| F-SEC-03 | SF-SEC | ✅ Complete | ✅ | +| F-SYS-01 | SF-SYS | ✅ Complete | ✅ | +| F-SYS-02 | SF-SYS | ✅ Complete | ✅ | +| F-SYS-03 | SF-SYS | ✅ Complete | ✅ | +| F-SYS-04 | SF-SYS | ✅ Complete | ✅ | +| F-PWR-01 | (No SW feature) | ⚠️ Missing | ⚠️ | +| F-PWR-02 | (No SW feature) | ⚠️ Missing | ⚠️ | +| F-HW-01 | (No SW feature) | ⚠️ Missing | ⚠️ | +| F-HW-02 | (No SW feature) | ⚠️ Missing | ⚠️ | + +**Gap Identified:** Power & Fault Handling (PWR) and Hardware Abstraction (HW) system features do not have corresponding software features. + +**Recommendation:** Create software features: +- SF-PWR: Power & Fault Handling +- SF-HW: Hardware Abstraction + +### 3.2 Feature Requirement Coverage + +**Assessment:** All software features have clear requirement backing. + +| Software Feature | SWR Count | Coverage | Status | +|-----------------|-----------|----------|--------| +| SF-SYS | 20 | ✅ 100% | ✅ | +| SF-DAQ | 20 | ✅ 100% | ✅ | +| SF-DQC | 20 | ✅ 100% | ✅ | +| SF-COM | 20 | ✅ 100% | ✅ | +| SF-DIAG | 20 | ✅ 100% | ✅ | +| SF-DATA | 20 | ✅ 100% | ✅ | +| SF-OTA | 25 | ✅ 100% | ✅ | +| SF-SEC | 25 | ✅ 100% | ✅ | + +--- + +## 4. Software Requirements ↔ Components Traceability + +### 4.1 Component Coverage Analysis + +**Total Software Requirements:** 170 +**Assigned to Components:** 145 (85%) +**Not Assigned:** 25 (15%) + +#### Coverage by Feature + +| Feature | SWR Count | Component Coverage | Missing Coverage | +|---------|-----------|-------------------|------------------| +| SF-SYS | 20 | ✅ 19 (95%) | 1 | +| SF-DAQ | 20 | ✅ 18 (90%) | 2 | +| SF-DQC | 20 | ✅ 17 (85%) | 3 | +| SF-COM | 20 | ⚠️ 16 (80%) | 4 | +| SF-DIAG | 20 | ✅ 18 (90%) | 2 | +| SF-DATA | 20 | ✅ 18 (90%) | 2 | +| SF-OTA | 25 | ✅ 21 (84%) | 4 | +| SF-SEC | 25 | ✅ 22 (88%) | 3 | + +### 4.2 Missing Component Assignments + +| Gap ID | Software Requirement | Description | Proposed Component | Severity | +|--------|---------------------|-------------|-------------------|----------| +| **GAP-SWR-COMP-001** | SWR-COM-016 | Heartbeat mechanism | Communication Manager | **MEDIUM** | +| **GAP-SWR-COMP-002** | SWR-COM-017 | Automatic reconnection | Communication Manager | **MEDIUM** | +| **GAP-SWR-COMP-003** | SWR-COM-018 | ESP-NOW encryption | Network Stack | **MEDIUM** | +| **GAP-SWR-COMP-004** | SWR-COM-019 | Message queuing | Communication Manager | **LOW** | +| **GAP-SWR-COMP-005** | SWR-DAQ-016 | Sensor warmup | Sensor Manager | **MEDIUM** | +| **GAP-SWR-COMP-006** | SWR-DAQ-017 | Range validation | Sensor Manager | **MEDIUM** | +| **GAP-SWR-COMP-007** | SWR-DQC-019 | Calibration application | Sensor Manager | **MEDIUM** | +| **GAP-SWR-COMP-008** | SWR-DATA-016 | Data integrity checks | Data Persistence | **MEDIUM** | +| **GAP-SWR-COMP-009** | SWR-DATA-017 | Backup/recovery | Data Persistence | **LOW** | +| **GAP-SWR-COMP-010** | SWR-OTA-021 | Automatic rollback | OTA Manager | **MEDIUM** | +| **GAP-SWR-COMP-011** | SWR-OTA-022 | Version compatibility | OTA Manager | **MEDIUM** | +| **GAP-SWR-COMP-012** | SWR-OTA-023 | Incremental updates | OTA Manager | **LOW** | +| **GAP-SWR-COMP-013** | SWR-SEC-021 | Certificate validation | Security Manager | **MEDIUM** | +| **GAP-SWR-COMP-014** | SWR-SEC-022 | Secure RNG | Crypto Utils | **MEDIUM** | +| **GAP-SWR-COMP-015** | SWR-SEC-023 | Key derivation | Crypto Utils | **MEDIUM** | + +### 4.3 Component Requirement Ownership + +**Assessment:** 90% of components have clear requirement ownership. + +#### Components with Complete Ownership + +| Component | SWR Count | Coverage | Status | +|-----------|-----------|----------|--------| +| System State Manager | 7 | ✅ 100% | ✅ | +| Sensor Manager | 13 | ✅ 100% | ✅ | +| Communication Manager | 11 | ⚠️ 85% | ⚠️ | +| OTA Manager | 9 | ⚠️ 80% | ⚠️ | +| Machine Constants Manager | 5 | ✅ 100% | ✅ | +| Security Manager | 8 | ⚠️ 88% | ⚠️ | +| Diagnostics Manager | 8 | ✅ 100% | ✅ | +| Event System | 3 | ✅ 100% | ✅ | +| Data Pool | 4 | ✅ 100% | ✅ | +| Data Persistence | 9 | ⚠️ 89% | ⚠️ | +| Error Handler | 5 | ✅ 100% | ✅ | +| Time Utils | 3 | ✅ 100% | ✅ | +| Logger | 2 | ✅ 100% | ✅ | + +#### Components with Incomplete Ownership + +| Component | Missing SWRs | Issue | Severity | +|-----------|--------------|-------|----------| +| Communication Manager | 4 | Missing heartbeat, reconnection, queuing | **MEDIUM** | +| OTA Manager | 4 | Missing rollback, version check, incremental | **MEDIUM** | +| Security Manager | 3 | Missing certificate validation, RNG, key derivation | **MEDIUM** | +| Data Persistence | 2 | Missing integrity checks, backup | **MEDIUM** | + +--- + +## 5. Missing or Weak Coverage Analysis + +### 5.1 System Requirements Without Software Coverage + +| Gap ID | System Requirement | Category | Severity | Impact | +|--------|-------------------|----------|----------|--------| +| **GAP-COV-001** | SR-PWR-001 through SR-PWR-008 | Power & Fault Handling | **MEDIUM** | Power management gaps | +| **GAP-COV-002** | SR-HW-001 through SR-HW-008 | Hardware Abstraction | **HIGH** | Hardware abstraction gaps | + +**Total Missing Coverage:** 16 system requirements (11.5%) + +### 5.2 Software Requirements Without Component Coverage + +**Total Missing Coverage:** 25 software requirements (15%) + +**Distribution:** +- Communication: 4 requirements +- OTA: 4 requirements +- Security: 3 requirements +- Data Quality: 3 requirements +- Sensor Acquisition: 2 requirements +- Data Persistence: 2 requirements +- Other: 7 requirements + +### 5.3 Features Without Clear Requirement Backing + +**Assessment:** All features have clear requirement backing. ✅ + +### 5.4 Components Without Requirement or Feature Ownership + +**Assessment:** All components have requirement or feature ownership. ✅ + +**Note:** Some utility components (Logger, Time Utils) have indirect ownership through multiple features. + +--- + +## 6. Consistency Analysis + +### 6.1 Requirement Consistency + +**Assessment:** 95% consistent + +#### Inconsistencies Identified + +| Issue ID | Description | Location | Severity | +|----------|-------------|----------|----------| +| **CONS-TRACE-001** | PWR and HW features not mapped to software features | Feature mapping | **MEDIUM** | +| **CONS-TRACE-002** | Some SWRs reference components not yet specified | Component assignments | **MEDIUM** | +| **CONS-TRACE-003** | Diagnostic code registry incomplete | Requirements vs Implementation | **MEDIUM** | + +### 6.2 Naming Consistency + +**Assessment:** 90% consistent + +**Issues:** +- Some component abbreviations inconsistent (STM vs State Manager) +- Some requirement IDs have variations + +--- + +## 7. Traceability Tables + +### 7.1 System Requirements ↔ Software Requirements + +| System Requirement | Software Requirements | Coverage | Status | +|-------------------|----------------------|----------|--------| +| SR-SYS-001 | SWR-SYS-001, SWR-SYS-002 | ✅ Complete | ✅ | +| SR-SYS-002 | SWR-SYS-003 | ✅ Complete | ✅ | +| SR-SYS-003 | SWR-SYS-004 | ✅ Complete | ✅ | +| SR-SYS-004 | SWR-SYS-005 | ✅ Complete | ✅ | +| SR-SYS-005 | SWR-SYS-006 | ✅ Complete | ✅ | +| SR-DAQ-001 | SWR-DAQ-001 | ✅ Complete | ✅ | +| SR-DAQ-002 | SWR-DAQ-002 | ✅ Complete | ✅ | +| ... | ... | ... | ... | +| SR-PWR-001 | (None) | ❌ Missing | ⚠️ | +| SR-PWR-002 | (None) | ❌ Missing | ⚠️ | +| SR-HW-001 | (None) | ❌ Missing | ⚠️ | +| SR-HW-002 | (None) | ❌ Missing | ⚠️ | + +**Complete Mapping:** 132 system requirements (95%) +**Missing Mapping:** 7 system requirements (5%) + +### 7.2 System Features ↔ Software Features + +| System Feature | Software Feature | Status | +|----------------|-----------------|--------| +| F-DAQ-01, F-DAQ-02, F-DAQ-03 | SF-DAQ | ✅ | +| F-DQC-01, F-DQC-02, F-DQC-03, F-DQC-04 | SF-DQC | ✅ | +| F-COM-01, F-COM-02, F-COM-03 | SF-COM | ✅ | +| F-DIAG-01, F-DIAG-02, F-DIAG-03 | SF-DIAG | ✅ | +| F-DATA-01, F-DATA-02, F-DATA-03 | SF-DATA | ✅ | +| F-OTA-01, F-OTA-02, F-OTA-03, F-OTA-04 | SF-OTA | ✅ | +| F-SEC-01, F-SEC-02, F-SEC-03 | SF-SEC | ✅ | +| F-SYS-01, F-SYS-02, F-SYS-03, F-SYS-04 | SF-SYS | ✅ | +| F-PWR-01, F-PWR-02 | (None) | ⚠️ Missing | +| F-HW-01, F-HW-02 | (None) | ⚠️ Missing | + +**Complete Mapping:** 8 feature groups (80%) +**Missing Mapping:** 2 feature groups (20%) + +### 7.3 Software Requirements ↔ Components + +| Software Requirement | Component(s) | Status | +|---------------------|--------------|--------| +| SWR-SYS-001 | System State Manager | ✅ | +| SWR-SYS-002 | System State Manager | ✅ | +| SWR-DAQ-001 | Sensor Manager | ✅ | +| SWR-DAQ-002 | Sensor Manager, Sensor Drivers | ✅ | +| ... | ... | ... | +| SWR-COM-016 | (None) | ⚠️ Missing | +| SWR-COM-017 | (None) | ⚠️ Missing | +| SWR-OTA-021 | (None) | ⚠️ Missing | +| SWR-SEC-021 | (None) | ⚠️ Missing | + +**Complete Mapping:** 145 software requirements (85%) +**Missing Mapping:** 25 software requirements (15%) + +--- + +## 8. Overall Architectural Health Assessment + +### 8.1 Traceability Health Score + +| Aspect | Score | Status | +|--------|-------|--------| +| System Requirements → Software Requirements | 95% | ✅ Good | +| System Features → Software Features | 80% | ⚠️ Needs Improvement | +| Software Requirements → Components | 85% | ⚠️ Needs Improvement | +| Feature Requirement Coverage | 100% | ✅ Excellent | +| Component Ownership | 90% | ✅ Good | +| **Overall Score** | **90%** | ✅ **Good** | + +### 8.2 Health Indicators + +**Green (Healthy):** +- Complete feature-to-requirement mapping +- Strong system-to-software requirement mapping +- Clear component ownership for core components + +**Yellow (Needs Attention):** +- Missing PWR and HW software features +- Some software requirements lack component assignments +- Some components have incomplete requirement coverage + +**Red (Critical):** +- None identified + +### 8.3 Recommendations for Improvement + +1. **Create Missing Software Features** + - SF-PWR: Power & Fault Handling + - SF-HW: Hardware Abstraction + +2. **Complete Component Assignments** + - Assign missing software requirements to components + - Update traceability matrix + +3. **Add Software Requirements for PWR and HW** + - Create SWR-PWR-001 through SWR-PWR-008 + - Create SWR-HW-001 through SWR-HW-008 + +--- + +## 9. Identified Gaps Summary + +### 9.1 High-Priority Gaps + +| Gap ID | Description | Impact | Action Required | +|--------|-------------|--------|-----------------| +| GAP-COV-002 | Missing HW software requirements | Blocks hardware abstraction | Add SWR-HW-001 through SWR-HW-008 | +| GAP-SWR-COMP-005 | Sensor warmup not assigned | Affects sensor initialization | Assign to Sensor Manager | +| GAP-SWR-COMP-006 | Range validation not assigned | Affects data quality | Assign to Sensor Manager | +| GAP-SWR-COMP-013 | Certificate validation not assigned | Affects security | Assign to Security Manager | + +### 9.2 Medium-Priority Gaps + +| Gap ID | Description | Impact | Action Required | +|--------|-------------|--------|-----------------| +| GAP-COV-001 | Missing PWR software requirements | Affects power management | Add SWR-PWR-001 through SWR-PWR-008 | +| GAP-SWR-COMP-001 | Heartbeat not assigned | Affects communication | Assign to Communication Manager | +| GAP-SWR-COMP-002 | Reconnection not assigned | Affects communication | Assign to Communication Manager | +| GAP-SWR-COMP-010 | Rollback not assigned | Affects OTA | Assign to OTA Manager | + +### 9.3 Low-Priority Gaps + +| Gap ID | Description | Impact | Action Required | +|--------|-------------|--------|-----------------| +| GAP-SWR-COMP-004 | Message queuing not assigned | Nice to have | Assign to Communication Manager | +| GAP-SWR-COMP-009 | Backup/recovery not assigned | Nice to have | Assign to Data Persistence | +| GAP-SWR-COMP-012 | Incremental updates not assigned | Nice to have | Assign to OTA Manager | + +--- + +## 10. Proposed Corrective Actions + +### 10.1 Immediate Actions + +1. **Create Missing Software Features** + - SF-PWR: Power & Fault Handling + - SF-HW: Hardware Abstraction + +2. **Add Missing Software Requirements** + - SWR-PWR-001 through SWR-PWR-008 + - SWR-HW-001 through SWR-HW-008 + +3. **Complete Component Assignments** + - Assign all missing software requirements to components + - Update traceability matrix + +### 10.2 Short-Term Actions + +1. **Update Traceability Documents** + - Update Combined_Traceability_Matrix.md + - Update Software_Requirements_to_Components.md + - Update Software_Requirements_to_Features.md + +2. **Complete Component Specifications** + - Add missing requirement coverage to component specs + - Update interface specifications + +### 10.3 Long-Term Actions + +1. **Maintain Traceability** + - Establish traceability maintenance process + - Regular traceability reviews + - Automated traceability checking + +--- + +## 11. Conclusion + +The System ↔ Software Traceability Analysis demonstrates strong coverage with 90% overall traceability health. The identified gaps are manageable and primarily relate to missing software features for Power & Fault Handling and Hardware Abstraction, and incomplete component assignments for some software requirements. + +**Key Strengths:** +- Complete feature-to-requirement mapping +- Strong system-to-software requirement mapping +- Clear component ownership for core components +- Good requirement coverage overall + +**Key Gaps:** +- Missing PWR and HW software features (20% of feature groups) +- Missing software requirements for PWR and HW (16 system requirements) +- Incomplete component assignments (15% of software requirements) + +**Overall Readiness:** 90% - Ready for implementation after addressing traceability gaps. + +**Recommended Action:** Create missing software features and requirements, complete component assignments, and update traceability documents before implementation begins. + +--- + +**Document Status:** Complete +**Next Review:** After gap resolution +**Approval Required:** System Architect, Software Architect diff --git a/draft- to be removed SW/Global_Software_Architecture.md b/draft- to be removed SW/Global_Software_Architecture.md deleted file mode 100644 index f3abe15..0000000 --- a/draft- to be removed SW/Global_Software_Architecture.md +++ /dev/null @@ -1,866 +0,0 @@ -# Global Software Architecture -# ASF Sensor Hub (Sub-Hub) Embedded System - -**Document Type:** Global Software Architecture Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Platform:** ESP32-S3, ESP-IDF v5.4, C/C++ -**Standard:** ISO/IEC/IEEE 42010:2011 - -## 1. Introduction - -### 1.1 Purpose - -This document defines the complete software architecture for the ASF Sensor Hub (Sub-Hub) embedded system. It provides a comprehensive view of the system's software structure, component relationships, data flows, and architectural decisions that guide implementation. - -### 1.2 Scope - -This architecture covers: -- Complete software component hierarchy and dependencies -- Layered architecture with strict dependency rules -- Component interfaces and interaction patterns -- Data flow and communication mechanisms -- Concurrency model and resource management -- State-aware operation and system lifecycle - -### 1.3 Architectural Objectives - -- **Modularity:** Clear separation of concerns with well-defined interfaces -- **Maintainability:** Structured design enabling easy modification and extension -- **Reliability:** Robust error handling and fault tolerance mechanisms -- **Performance:** Deterministic behavior meeting real-time constraints -- **Portability:** Hardware abstraction enabling platform independence -- **Security:** Layered security with hardware-enforced protection - -## 2. Architectural Overview - -### 2.1 Architectural Style - -The ASF Sensor Hub follows a **Layered Architecture** with the following characteristics: - -- **Strict Layering:** Dependencies flow downward only (Application → Drivers → OSAL → HAL) -- **Component-Based Design:** Modular components with well-defined responsibilities -- **Event-Driven Communication:** Asynchronous inter-component communication -- **State-Aware Operation:** All components respect system state constraints -- **Hardware Abstraction:** Complete isolation of application logic from hardware - -### 2.2 Architectural Principles - -| Principle | Description | Enforcement | -|-----------|-------------|-------------| -| **Separation of Concerns** | Each component has single, well-defined responsibility | Component specifications, code reviews | -| **Dependency Inversion** | High-level modules don't depend on low-level modules | Interface abstractions, dependency injection | -| **Single Source of Truth** | Data ownership clearly defined and centralized | Data Pool component, persistence abstraction | -| **Fail-Safe Operation** | System degrades gracefully under fault conditions | Error handling, state machine design | -| **Deterministic Behavior** | Predictable timing and resource usage | Static allocation, bounded operations | - -## 3. Layered Architecture - -### 3.1 Architecture Layers - -```mermaid -graph TB - subgraph "Application Layer" - subgraph "Business Stack" - STM[State Manager] - EventSys[Event System] - SensorMgr[Sensor Manager] - MCMgr[MC Manager] - OTAMgr[OTA Manager] - MainHubAPI[Main Hub APIs] - end - - subgraph "DP Stack" - DataPool[Data Pool] - Persistence[Persistence] - end - - DiagTask[Diagnostics Task] - ErrorHandler[Error Handler] - HMI[HMI Controller] - Engineering[Engineering Session] - end - - subgraph "Drivers Layer" - SensorDrivers[Sensor Drivers] - NetworkStack[Network Stack] - StorageDrivers[Storage Drivers] - DiagProtocol[Diagnostic Protocol] - GPIOManager[GPIO Manager] - end - - subgraph "ESP-IDF Wrappers (OSAL)" - I2CWrapper[I2C Wrapper] - SPIWrapper[SPI Wrapper] - UARTWrapper[UART Wrapper] - ADCWrapper[ADC Wrapper] - WiFiWrapper[WiFi Wrapper] - TaskWrapper[Task Wrapper] - TimerWrapper[Timer Wrapper] - end - - subgraph "ESP-IDF Framework (HAL)" - I2CHAL[I2C HAL] - SPIHAL[SPI HAL] - UARTHAL[UART HAL] - ADCHAL[ADC HAL] - WiFiHAL[WiFi HAL] - FreeRTOS[FreeRTOS Kernel] - SecureBoot[Secure Boot] - FlashEncryption[Flash Encryption] - end - - subgraph "Hardware" - ESP32S3[ESP32-S3 MCU] - Sensors[Environmental Sensors] - SDCard[SD Card] - OLED[OLED Display] - Buttons[Navigation Buttons] - end - - %% Layer Dependencies (downward only) - STM --> EventSys - SensorMgr --> SensorDrivers - SensorMgr --> EventSys - DataPool --> Persistence - Persistence --> StorageDrivers - MainHubAPI --> NetworkStack - - SensorDrivers --> I2CWrapper - SensorDrivers --> SPIWrapper - NetworkStack --> WiFiWrapper - StorageDrivers --> SPIWrapper - - I2CWrapper --> I2CHAL - SPIWrapper --> SPIHAL - WiFiWrapper --> WiFiHAL - TaskWrapper --> FreeRTOS - - I2CHAL --> ESP32S3 - SPIHAL --> ESP32S3 - WiFiHAL --> ESP32S3 - FreeRTOS --> ESP32S3 - - ESP32S3 --> Sensors - ESP32S3 --> SDCard - ESP32S3 --> OLED -``` - -### 3.2 Layer Descriptions - -#### 3.2.1 Application Layer - -**Purpose:** Implements business logic and system-specific functionality. - -**Components:** -- **Business Stack:** Core business logic components (STM, Event System, Managers) -- **DP Stack:** Data management components (Data Pool, Persistence) -- **Support Components:** Diagnostics, Error Handling, HMI, Engineering Access - -**Responsibilities:** -- System state management and lifecycle control -- Sensor data acquisition and processing -- Communication protocol implementation -- Data persistence and management -- User interface and engineering access - -**Constraints:** -- SHALL NOT access hardware directly -- SHALL use Event System for inter-component communication -- SHALL respect system state restrictions -- SHALL use Data Pool for runtime data access - -#### 3.2.2 Drivers Layer - -**Purpose:** Provides hardware abstraction and protocol implementation. - -**Components:** -- **Sensor Drivers:** Hardware-specific sensor interfaces -- **Network Stack:** Communication protocol implementation -- **Storage Drivers:** SD Card and NVM access -- **Diagnostic Protocol:** Engineering access protocol -- **GPIO Manager:** Hardware resource management - -**Responsibilities:** -- Hardware device abstraction -- Protocol implementation (I2C, SPI, UART, WiFi) -- Resource management and conflict resolution -- Error detection and reporting - -**Constraints:** -- SHALL provide uniform interfaces to application layer -- SHALL handle hardware-specific details -- SHALL implement proper error handling -- SHALL coordinate resource access - -#### 3.2.3 ESP-IDF Wrappers (OSAL) - -**Purpose:** Operating System Abstraction Layer providing platform independence. - -**Components:** -- **Hardware Wrappers:** I2C, SPI, UART, ADC, WiFi abstractions -- **OS Wrappers:** Task, Timer, Socket abstractions -- **System Services:** Logging, Time utilities - -**Responsibilities:** -- Platform abstraction for portability -- Uniform interface to ESP-IDF services -- Resource management and synchronization -- System service abstraction - -**Constraints:** -- SHALL provide platform-independent interfaces -- SHALL encapsulate ESP-IDF specific details -- SHALL maintain API stability across ESP-IDF versions -- SHALL handle platform-specific error conditions - -#### 3.2.4 ESP-IDF Framework (HAL) - -**Purpose:** Hardware Abstraction Layer and system services. - -**Components:** -- **Hardware Drivers:** Low-level hardware access -- **FreeRTOS Kernel:** Real-time operating system -- **Security Services:** Secure Boot, Flash Encryption -- **System Services:** Memory management, interrupt handling - -**Responsibilities:** -- Direct hardware access and control -- Real-time task scheduling -- Security enforcement -- System resource management - -## 4. Component Architecture - -### 4.1 Component Dependency Graph - -```mermaid -graph TB - subgraph "Application Components" - STM[State Manager
COMP-STM] - ES[Event System
COMP-EVENT] - SM[Sensor Manager
COMP-SENSOR-MGR] - MCM[MC Manager
COMP-MC-MGR] - OTA[OTA Manager
COMP-OTA-MGR] - MHA[Main Hub APIs
COMP-MAIN-HUB] - DP[Data Pool
COMP-DATA-POOL] - PERS[Persistence
COMP-PERSISTENCE] - DIAG[Diagnostics Task
COMP-DIAG-TASK] - ERR[Error Handler
COMP-ERROR-HANDLER] - HMI[HMI Controller
COMP-HMI] - ENG[Engineering Session
COMP-ENGINEERING] - end - - subgraph "Driver Components" - SD[Sensor Drivers
COMP-SENSOR-DRV] - NS[Network Stack
COMP-NETWORK] - STOR[Storage Drivers
COMP-STORAGE] - DIAG_PROT[Diagnostic Protocol
COMP-DIAG-PROT] - GPIO[GPIO Manager
COMP-GPIO] - end - - subgraph "Utility Components" - LOG[Logger
COMP-LOGGER] - TIME[Time Utils
COMP-TIME] - SEC[Security Manager
COMP-SECURITY] - end - - %% Primary Dependencies - STM --> ES - SM --> ES - SM --> SD - SM --> TIME - MCM --> PERS - OTA --> NS - OTA --> PERS - MHA --> NS - MHA --> DP - DP --> TIME - PERS --> STOR - DIAG --> PERS - ERR --> STM - ERR --> DIAG - HMI --> DP - ENG --> SEC - - %% Logging Dependencies - STM --> LOG - SM --> LOG - OTA --> LOG - MHA --> LOG - DIAG --> LOG - ERR --> LOG - - %% Event System Dependencies - ES --> DP - ES --> DIAG - ES --> HMI - - %% Cross-cutting Dependencies - SD --> GPIO - NS --> GPIO - STOR --> GPIO - HMI --> GPIO -``` - -### 4.2 Component Interaction Patterns - -#### 4.2.1 Event-Driven Communication - -```mermaid -sequenceDiagram - participant SM as Sensor Manager - participant ES as Event System - participant DP as Data Pool - participant MHA as Main Hub APIs - participant PERS as Persistence - - Note over SM,PERS: Sensor Data Update Flow - - SM->>SM: processSensorData() - SM->>ES: publish(SENSOR_DATA_UPDATE, data) - - par Parallel Event Delivery - ES->>DP: notify(SENSOR_DATA_UPDATE, data) - DP->>DP: updateSensorData(data) - and - ES->>MHA: notify(SENSOR_DATA_UPDATE, data) - MHA->>MHA: queueForTransmission(data) - and - ES->>PERS: notify(SENSOR_DATA_UPDATE, data) - PERS->>PERS: persistSensorData(data) - end - - Note over SM,PERS: All components updated asynchronously -``` - -#### 4.2.2 State-Aware Operation - -```mermaid -sequenceDiagram - participant COMP as Any Component - participant STM as State Manager - participant ES as Event System - - Note over COMP,ES: State-Aware Operation Pattern - - COMP->>STM: getCurrentState() - STM-->>COMP: current_state - - COMP->>COMP: checkOperationAllowed(current_state) - - alt Operation Allowed - COMP->>COMP: executeOperation() - COMP->>ES: publish(OPERATION_COMPLETE, result) - else Operation Not Allowed - COMP->>COMP: skipOperation() - COMP->>ES: publish(OPERATION_SKIPPED, reason) - end - - Note over COMP,ES: State changes trigger re-evaluation - ES->>COMP: notify(STATE_CHANGED, new_state) - COMP->>COMP: updateOperationPermissions(new_state) -``` - -#### 4.2.3 Data Access Pattern - -```mermaid -sequenceDiagram - participant COMP as Component - participant DP as Data Pool - participant PERS as Persistence - participant STOR as Storage Driver - - Note over COMP,STOR: Data Access Hierarchy - - COMP->>DP: getLatestSensorData() - DP-->>COMP: sensor_data (if available) - - alt Data Not Available in Pool - COMP->>PERS: loadSensorData() - PERS->>STOR: readFromStorage() - STOR-->>PERS: stored_data - PERS-->>COMP: sensor_data - PERS->>DP: updateDataPool(sensor_data) - end - - Note over COMP,STOR: Write operations go through persistence - COMP->>PERS: persistSensorData(data) - PERS->>DP: updateDataPool(data) - PERS->>STOR: writeToStorage(data) -``` - -## 5. Data Flow Architecture - -### 5.1 Primary Data Flows - -#### 5.1.1 Sensor Data Flow - -```mermaid -flowchart TD - SENSORS[Physical Sensors] --> SD[Sensor Drivers] - SD --> SM[Sensor Manager] - SM --> FILTER[Local Filtering] - FILTER --> TIMESTAMP[Timestamp Generation] - TIMESTAMP --> ES[Event System] - - ES --> DP[Data Pool] - ES --> PERS[Persistence] - ES --> MHA[Main Hub APIs] - - DP --> HMI[HMI Display] - DP --> DIAG[Diagnostics] - - PERS --> SD_CARD[SD Card Storage] - PERS --> NVM[NVM Storage] - - MHA --> NETWORK[Network Stack] - NETWORK --> MAIN_HUB[Main Hub] - - style SENSORS fill:#e1f5fe - style SD_CARD fill:#f3e5f5 - style MAIN_HUB fill:#e8f5e8 -``` - -#### 5.1.2 System State Flow - -```mermaid -flowchart TD - TRIGGER[State Trigger] --> STM[State Manager] - STM --> VALIDATE[Validate Transition] - VALIDATE --> TEARDOWN{Requires Teardown?} - - TEARDOWN -->|Yes| TD_SEQ[Teardown Sequence] - TEARDOWN -->|No| TRANSITION[Execute Transition] - - TD_SEQ --> STOP_OPS[Stop Operations] - STOP_OPS --> FLUSH_DATA[Flush Critical Data] - FLUSH_DATA --> TRANSITION - - TRANSITION --> ES[Event System] - ES --> ALL_COMPONENTS[All Components] - ALL_COMPONENTS --> UPDATE_BEHAVIOR[Update Behavior] - - STM --> PERS[Persistence] - PERS --> STATE_STORAGE[State Storage] - - style TRIGGER fill:#ffebee - style STATE_STORAGE fill:#f3e5f5 -``` - -#### 5.1.3 Diagnostic Data Flow - -```mermaid -flowchart TD - FAULT_SOURCE[Fault Source] --> ERR[Error Handler] - ERR --> CLASSIFY[Classify Fault] - CLASSIFY --> ESCALATE{Escalation Needed?} - - ESCALATE -->|Yes| STM[State Manager] - ESCALATE -->|No| DIAG[Diagnostics Task] - - STM --> STATE_CHANGE[State Transition] - STATE_CHANGE --> ES[Event System] - - DIAG --> DP[Data Pool] - DIAG --> PERS[Persistence] - DIAG --> ES - - DP --> HMI[HMI Display] - PERS --> DIAG_STORAGE[Diagnostic Storage] - ES --> ENG[Engineering Session] - - style FAULT_SOURCE fill:#ffebee - style DIAG_STORAGE fill:#f3e5f5 -``` - -### 5.2 Data Consistency Model - -#### 5.2.1 Data Ownership - -| Data Type | Owner | Access Pattern | Persistence | -|-----------|-------|----------------|-------------| -| **Sensor Data** | Sensor Manager | Write-once, read-many | Data Pool → Persistence | -| **System State** | State Manager | Single writer, multiple readers | Direct persistence | -| **Diagnostics** | Diagnostics Task | Append-only, read-many | Circular log | -| **Configuration** | MC Manager | Infrequent updates, cached reads | NVM storage | -| **Communication Status** | Network components | Frequent updates, latest value | Data Pool only | - -#### 5.2.2 Consistency Guarantees - -- **Sensor Data:** Eventually consistent across all consumers -- **System State:** Strongly consistent, atomic updates -- **Diagnostics:** Append-only, monotonic ordering -- **Configuration:** Consistent after successful update -- **Runtime Data:** Best-effort consistency, latest value wins - -## 6. Concurrency Architecture - -### 6.1 Task Model - -```mermaid -graph TB - subgraph "High Priority Tasks" - SENSOR_TASK[Sensor Acquisition Task
Priority: HIGH
Stack: 8KB
Period: 1s] - SYSTEM_TASK[System Management Task
Priority: HIGH
Stack: 6KB
Event-driven] - OTA_TASK[OTA Task
Priority: HIGH
Stack: 16KB
Event-driven] - end - - subgraph "Medium Priority Tasks" - COMM_TASK[Communication Task
Priority: MEDIUM
Stack: 12KB
Event-driven] - PERSIST_TASK[Persistence Task
Priority: MEDIUM
Stack: 6KB
Event-driven] - end - - subgraph "Low Priority Tasks" - DIAG_TASK[Diagnostics Task
Priority: LOW
Stack: 4KB
Period: 10s] - HMI_TASK[HMI Task
Priority: LOW
Stack: 4KB
Event-driven] - end - - subgraph "System Tasks" - IDLE_TASK[Idle Task
Priority: IDLE
Stack: 2KB] - TIMER_TASK[Timer Service Task
Priority: HIGH
Stack: 4KB] - end -``` - -### 6.2 Resource Synchronization - -#### 6.2.1 Synchronization Primitives - -| Resource | Synchronization | Access Pattern | Timeout | -|----------|----------------|----------------|---------| -| **Data Pool** | Reader-Writer Mutex | Multi-read, single-write | 100ms | -| **Event Queue** | Lock-free Queue | Producer-consumer | None | -| **Sensor Drivers** | Task-level ownership | Exclusive per task | N/A | -| **Storage** | Mutex | Single writer | 1s | -| **Network** | Mutex | Single writer | 5s | -| **Configuration** | Mutex | Infrequent updates | 500ms | - -#### 6.2.2 Deadlock Prevention - -- **Lock Ordering:** Consistent lock acquisition order across all components -- **Timeout-based Locking:** All mutex operations have bounded timeouts -- **Lock-free Structures:** Event queues use lock-free algorithms -- **Priority Inheritance:** Mutexes support priority inheritance - -### 6.3 Inter-Task Communication - -```mermaid -sequenceDiagram - participant ST as Sensor Task - participant ES as Event System - participant CT as Communication Task - participant PT as Persistence Task - participant HT as HMI Task - - Note over ST,HT: Event-Driven Communication - - ST->>ES: publish(SENSOR_DATA_UPDATE) - - par Parallel Notification - ES->>CT: notify(SENSOR_DATA_UPDATE) - CT->>CT: queueForTransmission() - and - ES->>PT: notify(SENSOR_DATA_UPDATE) - PT->>PT: persistData() - and - ES->>HT: notify(SENSOR_DATA_UPDATE) - HT->>HT: updateDisplay() - end - - Note over ST,HT: Non-blocking, asynchronous delivery -``` - -## 7. Security Architecture - -### 7.1 Security Layers - -```mermaid -graph TB - subgraph "Application Security" - AUTH[Authentication] - AUTHZ[Authorization] - SESSION[Session Management] - INPUT_VAL[Input Validation] - end - - subgraph "Communication Security" - TLS[TLS 1.2/mTLS] - CERT[Certificate Management] - ENCRYPT[Message Encryption] - end - - subgraph "Data Security" - DATA_ENCRYPT[Data Encryption] - INTEGRITY[Data Integrity] - ACCESS_CTRL[Access Control] - end - - subgraph "System Security" - SECURE_BOOT[Secure Boot V2] - FLASH_ENCRYPT[Flash Encryption] - HARDWARE_SEC[Hardware Security] - end - - AUTH --> TLS - CERT --> TLS - DATA_ENCRYPT --> FLASH_ENCRYPT - INTEGRITY --> HARDWARE_SEC - SECURE_BOOT --> HARDWARE_SEC -``` - -### 7.2 Security Enforcement Points - -| Layer | Security Mechanism | Implementation | -|-------|-------------------|----------------| -| **Hardware** | Secure Boot V2, Flash Encryption | ESP32-S3 hardware features | -| **System** | Certificate validation, Key management | Security Manager component | -| **Communication** | mTLS, Message authentication | Network Stack with TLS | -| **Application** | Session authentication, Access control | Engineering Session Manager | -| **Data** | Encryption at rest, Integrity checks | Persistence component | - -## 8. Error Handling Architecture - -### 8.1 Error Classification Hierarchy - -```mermaid -graph TB - ERROR[System Error] --> SEVERITY{Severity Level} - - SEVERITY --> INFO[INFO
Informational events] - SEVERITY --> WARNING[WARNING
Non-fatal issues] - SEVERITY --> ERROR_LEVEL[ERROR
Recoverable failures] - SEVERITY --> FATAL[FATAL
System-threatening] - - INFO --> LOG_ONLY[Log Only] - WARNING --> DIAG_REPORT[Diagnostic Report] - ERROR_LEVEL --> RECOVERY[Recovery Action] - FATAL --> STATE_TRANSITION[State Transition] - - RECOVERY --> RETRY[Retry Operation] - RECOVERY --> FALLBACK[Fallback Mode] - RECOVERY --> COMPONENT_RESTART[Component Restart] - - STATE_TRANSITION --> WARNING_STATE[WARNING State] - STATE_TRANSITION --> FAULT_STATE[FAULT State] - STATE_TRANSITION --> TEARDOWN[TEARDOWN State] -``` - -### 8.2 Error Propagation Model - -```mermaid -sequenceDiagram - participant COMP as Component - participant ERR as Error Handler - participant DIAG as Diagnostics Task - participant STM as State Manager - participant ES as Event System - - Note over COMP,ES: Error Detection and Handling - - COMP->>COMP: detectError() - COMP->>ERR: reportFault(error_info) - - ERR->>ERR: classifyError(error_info) - ERR->>ERR: determineResponse(classification) - - alt INFO/WARNING Level - ERR->>DIAG: logDiagnostic(error_info) - DIAG->>ES: publish(DIAGNOSTIC_EVENT) - else ERROR Level - ERR->>COMP: initiateRecovery(recovery_action) - ERR->>DIAG: logDiagnostic(error_info) - else FATAL Level - ERR->>STM: requestStateTransition(FAULT) - ERR->>DIAG: logDiagnostic(error_info) - STM->>ES: publish(STATE_CHANGED, FAULT) - end -``` - -## 9. Performance Architecture - -### 9.1 Performance Requirements - -| Subsystem | Requirement | Measurement | Constraint | -|-----------|-------------|-------------|------------| -| **Sensor Acquisition** | 1-second cycle time | End-to-end timing | Hard real-time | -| **Communication** | 5-second response | Request-response time | Soft real-time | -| **State Transitions** | 50ms transition time | State change duration | Hard real-time | -| **Data Access** | 10μs read latency | Data Pool access | Performance critical | -| **Memory Usage** | 80% of available | Static + dynamic usage | Resource constraint | - -### 9.2 Performance Optimization Strategies - -#### 9.2.1 Memory Optimization - -- **Static Allocation:** All data structures use static allocation (no malloc/free) -- **Memory Pools:** Pre-allocated pools for variable-size data -- **Stack Optimization:** Careful stack size allocation per task -- **Data Structure Optimization:** Packed structures, aligned access - -#### 9.2.2 CPU Optimization - -- **Lock-free Algorithms:** Event queues use lock-free implementations -- **Batch Processing:** Group operations to reduce overhead -- **Priority-based Scheduling:** Critical tasks have higher priority -- **Interrupt Optimization:** Minimal processing in interrupt context - -#### 9.2.3 I/O Optimization - -- **Asynchronous Operations:** Non-blocking I/O where possible -- **Batched Storage:** Group storage operations for efficiency -- **DMA Usage:** Hardware DMA for large data transfers -- **Buffer Management:** Efficient buffer allocation and reuse - -## 10. Deployment Architecture - -### 10.1 Memory Layout - -```mermaid -graph TB - subgraph "ESP32-S3 Memory Map" - subgraph "Flash Memory (8MB)" - BOOTLOADER[Bootloader
64KB] - PARTITION_TABLE[Partition Table
4KB] - OTA_0[OTA Partition 0
3MB] - OTA_1[OTA Partition 1
3MB] - NVS[NVS Storage
1MB] - SPIFFS[SPIFFS
1MB] - end - - subgraph "SRAM (512KB)" - CODE_CACHE[Code Cache
128KB] - DATA_HEAP[Data Heap
256KB] - STACK_AREA[Task Stacks
96KB] - SYSTEM_RESERVED[System Reserved
32KB] - end - - subgraph "External Storage" - SD_CARD[SD Card
Variable Size] - end - end -``` - -### 10.2 Component Deployment - -| Component | Memory Region | Size Estimate | Criticality | -|-----------|---------------|---------------|-------------| -| **State Manager** | Code Cache + Heap | 8KB | Critical | -| **Event System** | Code Cache + Heap | 12KB | Critical | -| **Sensor Manager** | Code Cache + Heap | 24KB | Critical | -| **Data Pool** | Heap | 64KB | Critical | -| **Persistence** | Code Cache + Heap | 16KB | Important | -| **Communication** | Code Cache + Heap | 32KB | Important | -| **Diagnostics** | Code Cache + Heap | 8KB | Normal | -| **HMI** | Code Cache + Heap | 4KB | Normal | - -## 11. Quality Attributes - -### 11.1 Reliability - -- **MTBF:** 8760 hours (1 year) under normal conditions -- **Fault Tolerance:** Graceful degradation under component failures -- **Recovery:** Automatic recovery from transient faults within 30 seconds -- **Data Integrity:** Error rate < 1 in 10^6 operations - -### 11.2 Performance - -- **Response Time:** Sensor acquisition within 1 second, communication within 5 seconds -- **Throughput:** Handle 7 sensors simultaneously with 10 samples each per second -- **Resource Usage:** CPU < 80%, Memory < 80% of available -- **Scalability:** Support additional sensor types through driver registration - -### 11.3 Security - -- **Authentication:** Certificate-based mutual authentication for all external communication -- **Encryption:** AES-256 for data at rest, TLS 1.2 for data in transit -- **Access Control:** Role-based access for engineering functions -- **Audit:** Complete audit trail for all security-relevant operations - -### 11.4 Maintainability - -- **Modularity:** Clear component boundaries with well-defined interfaces -- **Testability:** Comprehensive unit, integration, and system test coverage -- **Debuggability:** Extensive logging and diagnostic capabilities -- **Updateability:** Secure over-the-air firmware updates with rollback - -## 12. Architectural Decisions - -### 12.1 Key Architectural Decisions - -| Decision | Rationale | Alternatives Considered | Trade-offs | -|----------|-----------|------------------------|------------| -| **Layered Architecture** | Clear separation of concerns, maintainability | Microkernel, Component-based | Performance vs. Modularity | -| **Event-Driven Communication** | Loose coupling, asynchronous operation | Direct calls, Message queues | Complexity vs. Flexibility | -| **Static Memory Allocation** | Deterministic behavior, no fragmentation | Dynamic allocation | Memory efficiency vs. Predictability | -| **State Machine Control** | Predictable behavior, safety | Ad-hoc state management | Complexity vs. Reliability | -| **Hardware Abstraction** | Portability, testability | Direct hardware access | Performance vs. Portability | - -### 12.2 Design Patterns Used - -| Pattern | Application | Benefit | -|---------|-------------|---------| -| **Layered Architecture** | Overall system structure | Separation of concerns | -| **State Machine** | System lifecycle management | Predictable behavior | -| **Observer** | Event-driven communication | Loose coupling | -| **Singleton** | Data Pool, State Manager | Single source of truth | -| **Strategy** | Filter algorithms, communication protocols | Flexibility | -| **Template Method** | Component initialization | Code reuse | -| **Factory** | Driver instantiation | Extensibility | - -## 13. Compliance and Standards - -### 13.1 Standards Compliance - -- **ISO/IEC/IEEE 42010:2011:** Architecture description standard -- **ISO/IEC/IEEE 29148:2018:** Requirements engineering -- **IEC 61508:** Functional safety (SIL-1 compliance) -- **IEEE 802.11:** WiFi communication standard -- **RFC 5246:** TLS 1.2 security protocol - -### 13.2 Coding Standards - -- **MISRA C:2012:** Safety-critical C coding standard -- **ESP-IDF Style Guide:** Platform-specific coding conventions -- **Doxygen:** Documentation standard for all public APIs -- **Unit Testing:** Minimum 80% code coverage requirement - -## 14. Future Evolution - -### 14.1 Planned Enhancements - -- **Additional Sensor Types:** Framework supports easy extension -- **Advanced Analytics:** Edge computing capabilities for sensor data -- **Cloud Integration:** Direct cloud connectivity option -- **Machine Learning:** Predictive maintenance and anomaly detection - -### 14.2 Scalability Considerations - -- **Multi-Hub Coordination:** Support for coordinated operation -- **Sensor Fusion:** Advanced sensor data fusion algorithms -- **Protocol Extensions:** Support for additional communication protocols -- **Performance Scaling:** Optimization for higher sensor densities - -## 15. Validation and Verification - -### 15.1 Architecture Validation - -- **Requirements Traceability:** All requirements mapped to architectural elements -- **Interface Consistency:** All component interfaces validated -- **Dependency Analysis:** No circular dependencies, proper layering -- **Performance Analysis:** Timing and resource usage validated - -### 15.2 Implementation Verification - -- **Component Testing:** Unit tests for all components -- **Integration Testing:** Interface and interaction testing -- **System Testing:** End-to-end functionality validation -- **Performance Testing:** Real-time constraint verification - ---- - -**Document Status:** Final for Implementation Phase -**Architecture Completeness:** 100% (all components and interfaces defined) -**Requirements Traceability:** Complete (45 SR, 122 SWR, 10 Features) -**Next Review:** After implementation phase completion - -**This document serves as the definitive software architecture specification for the ASF Sensor Hub implementation.** \ No newline at end of file diff --git a/draft- to be removed SW/SRS.md b/draft- to be removed SW/SRS.md deleted file mode 100644 index 01d6d18..0000000 --- a/draft- to be removed SW/SRS.md +++ /dev/null @@ -1,515 +0,0 @@ -# System Requirements Specification (SRS) -# ASF Sensor Hub (Sub-Hub) Embedded System - -**Document Type:** System Requirements Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Platform:** ESP32-S3, ESP-IDF v5.4, C/C++ -**Domain:** Industrial/Agricultural Automation (Smart Poultry Farm) -**Standard:** ISO/IEC/IEEE 29148:2018 - -## 1. Introduction - -### 1.1 Purpose - -This System Requirements Specification (SRS) defines the complete set of system requirements for the ASF Sensor Hub (Sub-Hub) embedded system. The document serves as the authoritative source for all functional and non-functional requirements that the system must satisfy. - -### 1.2 Scope - -The ASF Sensor Hub is a distributed sensing node deployed inside a poultry house for environmental monitoring and data collection. The system is responsible for: - -- Acquisition of multiple environmental sensor data -- Local preprocessing and validation of sensor data -- Persistent storage of data and configuration -- Secure communication with a Main Hub -- Support for diagnostics, maintenance, and OTA updates -- Safe operation under fault conditions - -**Explicitly out of scope:** -- Main Hub processing and control logic -- Cloud analytics and services -- Farm control algorithms -- Actuator management - -### 1.3 Definitions and Acronyms - -| Term | Definition | -|------|------------| -| **Sub-Hub** | The ASF Sensor Hub embedded system (this system) | -| **Main Hub** | Central processing unit that coordinates multiple Sub-Hubs | -| **MC** | Machine Constants - persistent configuration data | -| **DP** | Data Persistence component | -| **STM** | State Manager component | -| **SAL** | Sensor Abstraction Layer | -| **HMI** | Human-Machine Interface (OLED display + buttons) | -| **OTA** | Over-The-Air firmware update | -| **mTLS** | Mutual Transport Layer Security | -| **CBOR** | Concise Binary Object Representation | - -### 1.4 References - -- ISO/IEC/IEEE 29148:2018 - Systems and software engineering — Life cycle processes — Requirements engineering -- IEC 61508 - Functional safety of electrical/electronic/programmable electronic safety-related systems -- ESP-IDF v5.4 Programming Guide -- System_Architecture_Documentation.md -- Cross-Feature Constraints.md - -## 2. Overall Description - -### 2.1 Product Perspective - -The ASF Sensor Hub operates as an autonomous embedded system within a distributed poultry farm automation network. It interfaces with: - -- **Environmental sensors** via I2C, SPI, UART, and analog interfaces -- **Main Hub** via encrypted Wi-Fi communication -- **Peer Sub-Hubs** via ESP-NOW for limited coordination -- **Local operators** via OLED display and button interface -- **SD Card** for persistent data storage - -### 2.2 Product Functions - -The system provides the following major functions: - -1. **Multi-sensor data acquisition** with high-frequency sampling and filtering -2. **Data quality assurance** through calibration and failure detection -3. **Secure communication** with Main Hub using encrypted protocols -4. **Persistent data storage** with wear-aware management -5. **Over-the-air firmware updates** with rollback capability -6. **Comprehensive diagnostics** and health monitoring -7. **Local human-machine interface** for status and diagnostics -8. **System state management** with controlled transitions -9. **Security enforcement** through hardware-based protection -10. **Power and fault handling** with graceful degradation - -### 2.3 User Classes and Characteristics - -| User Class | Characteristics | System Interaction | -|------------|-----------------|-------------------| -| **Farm Operators** | Basic technical knowledge, daily monitoring | Local HMI for status checking | -| **Maintenance Engineers** | Advanced technical knowledge, periodic maintenance | Debug sessions, diagnostic access | -| **System Integrators** | Expert technical knowledge, system configuration | Machine constants management, OTA updates | - -### 2.4 Operating Environment - -- **Hardware Platform:** ESP32-S3 microcontroller -- **Operating System:** FreeRTOS (via ESP-IDF) -- **Development Framework:** ESP-IDF v5.4 -- **Programming Language:** C/C++ -- **Environmental Conditions:** Industrial poultry house (temperature, humidity, dust) -- **Power Supply:** 12V DC with brownout protection -- **Communication:** Wi-Fi 802.11n (2.4 GHz), ESP-NOW - -### 2.5 Design and Implementation Constraints - -- **Memory:** 512KB SRAM, 8MB Flash (ESP32-S3) -- **Real-time:** Deterministic sensor sampling within 1-second cycles -- **Security:** Hardware-enforced Secure Boot V2 and Flash Encryption -- **Reliability:** 99.9% uptime requirement in normal operating conditions -- **Safety:** IEC 61508 SIL-1 compliance for sensor data integrity -- **Environmental:** IP65 enclosure rating, -10°C to +60°C operating range - -## 3. System Requirements - -### 3.1 Functional Requirements - -#### 3.1.1 Sensor Data Acquisition Requirements - -**SR-DAQ-001: Multi-Sensor Support** -The system SHALL support simultaneous data acquisition from the following sensor types: -- Temperature sensors -- Humidity sensors -- Carbon Dioxide (CO₂) sensors -- Ammonia (NH₃) sensors -- Volatile Organic Compounds (VOC) sensors -- Particulate Matter (PM) sensors -- Light Intensity sensors - -**SR-DAQ-002: High-Frequency Sampling** -The system SHALL sample each enabled sensor a minimum of 10 times per acquisition cycle to enable local filtering. - -**SR-DAQ-003: Local Data Filtering** -The system SHALL apply configurable filtering algorithms (median filter, moving average) to raw sensor samples to produce representative values. - -**SR-DAQ-004: Timestamped Data Generation** -The system SHALL associate each processed sensor value with a timestamp accurate to ±1 second of system time. - -**SR-DAQ-005: Sensor State Management** -The system SHALL maintain operational state for each sensor (enabled/disabled, present/absent, healthy/faulty). - -#### 3.1.2 Data Quality & Calibration Requirements - -**SR-DQC-001: Automatic Sensor Detection** -The system SHALL automatically detect the presence of sensors based on hardware detection signals during initialization and runtime. - -**SR-DQC-002: Sensor Type Enforcement** -The system SHALL enforce sensor-slot compatibility to prevent incorrect sensor installation and usage. - -**SR-DQC-003: Sensor Failure Detection** -The system SHALL detect sensor failures including communication errors, out-of-range values, and non-responsive sensors. - -**SR-DQC-004: Machine Constants Management** -The system SHALL maintain persistent Machine Constants (MC) data including: -- Installed sensor type definitions -- Sensor calibration parameters -- Communication configuration parameters -- System identity parameters - -**SR-DQC-005: Calibration Parameter Application** -The system SHALL apply calibration parameters from MC data to raw sensor readings to produce calibrated values. - -#### 3.1.3 Communication Requirements - -**SR-COM-001: Main Hub Communication** -The system SHALL provide bidirectional encrypted communication with a Main Hub to: -- Send sensor data using CBOR encoding -- Send diagnostic information -- Receive configuration updates -- Receive firmware updates - -**SR-COM-002: Secure Communication Protocols** -The system SHALL use mTLS 1.2 with X.509 certificates for all Main Hub communication. - -**SR-COM-003: On-Demand Data Broadcasting** -The system SHALL transmit the most recent sensor dataset upon request from the Main Hub within 5 seconds. - -**SR-COM-004: Peer Communication** -The system SHALL support limited peer-to-peer communication with other Sub-Hubs using ESP-NOW for: -- Connectivity checks -- Time synchronization support -- Basic status exchange - -**SR-COM-005: Communication Fault Tolerance** -The system SHALL continue autonomous operation during Main Hub communication failures for up to 24 hours. - -#### 3.1.4 Persistence & Data Management Requirements - -**SR-DATA-001: Persistent Sensor Data Storage** -The system SHALL store sensor data persistently on SD Card using FAT32 file system with wear-aware batch writing. - -**SR-DATA-002: Data Persistence Abstraction** -The system SHALL provide a unified Data Persistence (DP) component that abstracts storage media access for all persistent data operations. - -**SR-DATA-003: Safe Data Handling During Transitions** -The system SHALL ensure all critical data is safely persisted before: -- Firmware updates -- Configuration updates -- System teardown -- Reset or restart operations - -**SR-DATA-004: Data Integrity Protection** -The system SHALL implement data integrity mechanisms including checksums and atomic write operations to prevent data corruption. - -**SR-DATA-005: Storage Capacity Management** -The system SHALL manage storage capacity by implementing circular logging with configurable retention periods. - -#### 3.1.5 Firmware Update (OTA) Requirements - -**SR-OTA-001: OTA Update Negotiation** -The system SHALL implement an OTA handshake mechanism with the Main Hub to acknowledge update availability and signal readiness. - -**SR-OTA-002: Firmware Reception and Storage** -The system SHALL securely receive firmware images and store them temporarily on SD Card before activation. - -**SR-OTA-003: Firmware Integrity Validation** -The system SHALL validate firmware integrity using SHA-256 checksums before activation. - -**SR-OTA-004: Safe Firmware Activation** -The system SHALL implement A/B partitioning with automatic rollback capability for safe firmware activation. - -**SR-OTA-005: OTA State Management** -The system SHALL coordinate OTA operations with the system state machine to ensure safe transitions and data preservation. - -#### 3.1.6 Security & Safety Requirements - -**SR-SEC-001: Secure Boot** -The system SHALL implement Secure Boot V2 to ensure only authenticated firmware is executed. - -**SR-SEC-002: Flash Encryption** -The system SHALL implement Flash Encryption using AES-256 to protect sensitive data and intellectual property. - -**SR-SEC-003: Certificate Management** -The system SHALL manage X.509 certificates for mTLS communication with secure storage and validation. - -**SR-SEC-004: Security Violation Handling** -The system SHALL detect and respond to security violations including: -- Boot verification failures -- Certificate validation failures -- Unauthorized access attempts - -#### 3.1.7 Diagnostics & Health Monitoring Requirements - -**SR-DIAG-001: Diagnostic Code Management** -The system SHALL implement structured diagnostics with: -- Unique diagnostic codes (format: 0xSCCC) -- Severity levels (INFO, WARNING, ERROR, FATAL) -- Root cause hierarchy -- Timestamp information - -**SR-DIAG-002: Diagnostic Data Storage** -The system SHALL persistently store diagnostic events in a circular log with configurable retention. - -**SR-DIAG-003: Diagnostic Session Support** -The system SHALL provide diagnostic sessions allowing authorized engineers to: -- Retrieve diagnostic data -- Inspect system health status -- Clear diagnostic records - -**SR-DIAG-004: Layered Watchdog System** -The system SHALL implement multiple watchdog levels: -- Task-level watchdogs for critical tasks -- Interrupt watchdog for system responsiveness -- RTC watchdog for ultimate system recovery - -#### 3.1.8 System Management Requirements - -**SR-SYS-001: System State Machine** -The system SHALL implement a finite state machine with the following states: -- INIT, BOOT_FAILURE, RUNNING, WARNING, FAULT -- OTA_PREP, OTA_UPDATE, MC_UPDATE, TEARDOWN -- SERVICE, SD_DEGRADED - -**SR-SYS-002: State-Aware Operation** -The system SHALL restrict feature operations based on current system state according to defined state transition rules. - -**SR-SYS-003: Controlled Teardown** -The system SHALL execute a controlled teardown sequence that: -- Stops sensor acquisition -- Flushes all critical data -- Ensures storage consistency -- Prepares for target state transition - -**SR-SYS-004: Local Human-Machine Interface** -The system SHALL provide local status indication using: -- OLED display (128x64, I2C interface) -- Three-button navigation (Up, Down, Select) -- Menu system for diagnostics and sensor status - -**SR-SYS-005: Engineering Access** -The system SHALL support authenticated engineering sessions for: -- Log inspection -- Machine constants inspection and update -- Controlled debugging operations - -#### 3.1.9 Power & Fault Handling Requirements - -**SR-PWR-001: Brownout Detection** -The system SHALL detect power supply brownout conditions and initiate controlled shutdown procedures. - -**SR-PWR-002: Power-Loss Recovery** -The system SHALL implement power-loss recovery mechanisms to restore operation after power restoration. - -**SR-PWR-003: Fault Classification** -The system SHALL classify faults into categories: -- Sensor faults, Communication faults, Storage faults -- Power faults, Security faults, Software faults, Hardware faults - -**SR-PWR-004: Fault Escalation** -The system SHALL implement fault escalation procedures based on severity and frequency. - -#### 3.1.10 Hardware Abstraction Requirements - -**SR-HW-001: Sensor Abstraction Layer** -The system SHALL implement a Sensor Abstraction Layer (SAL) that provides uniform interfaces for different sensor types. - -**SR-HW-002: Hardware Interface Abstraction** -The system SHALL abstract hardware interfaces (GPIO, I2C, SPI, UART, ADC) through driver layers to enable portability. - -**SR-HW-003: GPIO Discipline** -The system SHALL implement GPIO discipline with defined ownership and access control for hardware resources. - -### 3.2 Non-Functional Requirements - -#### 3.2.1 Performance Requirements - -**SR-PERF-001: Sensor Acquisition Timing** -The system SHALL complete sensor acquisition cycles within 1 second for all enabled sensors. - -**SR-PERF-002: Communication Response Time** -The system SHALL respond to Main Hub requests within 5 seconds under normal operating conditions. - -**SR-PERF-003: Memory Usage** -The system SHALL operate within 80% of available SRAM (409.6KB) and Flash (6.4MB) capacity. - -**SR-PERF-004: Storage Performance** -The system SHALL achieve minimum 10KB/s write performance to SD Card for data logging. - -#### 3.2.2 Reliability Requirements - -**SR-REL-001: System Availability** -The system SHALL achieve 99.9% availability during normal operating conditions. - -**SR-REL-002: Mean Time Between Failures** -The system SHALL achieve MTBF of 8760 hours (1 year) under specified environmental conditions. - -**SR-REL-003: Fault Recovery** -The system SHALL automatically recover from transient faults within 30 seconds. - -**SR-REL-004: Data Integrity** -The system SHALL maintain data integrity with error rate < 1 in 10^6 operations. - -#### 3.2.3 Safety Requirements - -**SR-SAFE-001: Fail-Safe Operation** -The system SHALL fail to a safe state (sensor data marked invalid) upon detection of critical faults. - -**SR-SAFE-002: Sensor Data Validation** -The system SHALL validate sensor data ranges and mark out-of-range values as invalid. - -**SR-SAFE-003: Watchdog Protection** -The system SHALL implement multiple watchdog mechanisms to detect and recover from software failures. - -#### 3.2.4 Security Requirements - -**SR-SEC-005: Authentication** -The system SHALL authenticate all external communication using certificate-based mutual authentication. - -**SR-SEC-006: Data Encryption** -The system SHALL encrypt all sensitive data at rest using AES-256 encryption. - -**SR-SEC-007: Secure Communication** -The system SHALL encrypt all network communication using TLS 1.2 or higher. - -**SR-SEC-008: Access Control** -The system SHALL implement role-based access control for engineering and diagnostic functions. - -#### 3.2.5 Maintainability Requirements - -**SR-MAINT-001: Diagnostic Accessibility** -The system SHALL provide comprehensive diagnostic information accessible through local and remote interfaces. - -**SR-MAINT-002: Configuration Management** -The system SHALL support field configuration updates through authenticated channels. - -**SR-MAINT-003: Firmware Updateability** -The system SHALL support secure over-the-air firmware updates with rollback capability. - -#### 3.2.6 Portability Requirements - -**SR-PORT-001: Hardware Abstraction** -The system SHALL abstract hardware dependencies to enable porting to compatible microcontroller platforms. - -**SR-PORT-002: Standard Interfaces** -The system SHALL use standard communication protocols (I2C, SPI, UART) for sensor interfaces. - -### 3.3 Interface Requirements - -#### 3.3.1 Hardware Interfaces - -**SR-HW-IF-001: Sensor Interfaces** -The system SHALL provide the following sensor interfaces: -- 4x I2C interfaces for digital sensors -- 2x SPI interfaces for high-speed sensors -- 2x UART interfaces for serial sensors -- 4x ADC channels for analog sensors - -**SR-HW-IF-002: Communication Interfaces** -The system SHALL provide: -- Wi-Fi 802.11n (2.4 GHz) interface -- Optional Zigbee/LoRa interface for backup communication - -**SR-HW-IF-003: Storage Interfaces** -The system SHALL provide: -- SD Card interface (SPI-based) -- Internal NVM (encrypted) - -**SR-HW-IF-004: User Interface** -The system SHALL provide: -- OLED display interface (I2C, 128x64 pixels) -- 3x GPIO inputs for buttons (Up, Down, Select) - -#### 3.3.2 Software Interfaces - -**SR-SW-IF-001: Main Hub Protocol** -The system SHALL implement the Main Hub communication protocol using: -- MQTT over TLS 1.2 transport -- CBOR message encoding -- Defined message schemas for sensor data, diagnostics, and control - -**SR-SW-IF-002: Peer Communication Protocol** -The system SHALL implement peer communication using ESP-NOW protocol with defined message formats. - -**SR-SW-IF-003: Diagnostic Interface** -The system SHALL provide diagnostic interface supporting: -- Log retrieval commands -- System status queries -- Configuration inspection commands - -## 4. System Architecture Requirements - -### 4.1 Architectural Constraints - -**SR-ARCH-001: Layered Architecture** -The system SHALL implement a strict layered architecture with dependency flow from Application → Drivers → OSAL → HAL. - -**SR-ARCH-002: Hardware Abstraction** -Application logic SHALL NOT access hardware directly and SHALL use driver abstractions exclusively. - -**SR-ARCH-003: State-Aware Execution** -All system features SHALL be aware of current system state and respect state-based operation restrictions. - -**SR-ARCH-004: Event-Driven Communication** -Internal component communication SHALL use event-driven publish/subscribe mechanisms. - -**SR-ARCH-005: Data Persistence Abstraction** -All persistent data access SHALL be performed through the Data Persistence (DP) component. - -### 4.2 Component Requirements - -**SR-COMP-001: State Manager Component** -The system SHALL implement a State Manager (STM) component responsible for: -- System state machine implementation -- State transition validation and coordination -- Teardown sequence management - -**SR-COMP-002: Event System Component** -The system SHALL implement an Event System component providing: -- Publish/subscribe event bus -- Non-blocking event delivery -- Event type management - -**SR-COMP-003: Sensor Manager Component** -The system SHALL implement a Sensor Manager component responsible for: -- Sensor lifecycle management -- Data acquisition scheduling -- Local filtering and validation - -**SR-COMP-004: Data Persistence Component** -The system SHALL implement a Data Persistence (DP) component providing: -- Storage media abstraction -- Data serialization/deserialization -- Wear-aware storage management - -## 5. Verification Requirements - -### 5.1 Verification Methods - -Each system requirement SHALL be verified using one or more of the following methods: -- **Test (T):** Verification by test execution -- **Analysis (A):** Verification by analysis or calculation -- **Inspection (I):** Verification by inspection or review -- **Demonstration (D):** Verification by demonstration - -### 5.2 Verification Levels - -- **Unit Level:** Individual component verification -- **Integration Level:** Component interaction verification -- **System Level:** End-to-end system verification -- **Acceptance Level:** User acceptance verification - -## 6. Traceability - -This SRS provides the foundation for: -- Software Requirements Specification (SWR-XXX requirements) -- Feature specifications (F-XXX features) -- Component specifications (C-XXX components) -- Test specifications and procedures - -All system requirements SHALL be traceable to: -- Stakeholder needs and use cases -- Feature definitions in Features.md -- Architectural constraints in Cross-Feature Constraints.md - ---- - -**Document Status:** Final for Implementation Phase -**Next Review:** After Software Requirements Specification completion \ No newline at end of file diff --git a/draft- to be removed SW/SW design.md b/draft- to be removed SW/SW design.md deleted file mode 100644 index 4abe7be..0000000 --- a/draft- to be removed SW/SW design.md +++ /dev/null @@ -1,336 +0,0 @@ -## Sub-Hub (Sensor Hub) Firmware Architecture - -## 1\. Document Scope - -This document defines the **static software architecture** of the **Sub-Hub (Sensor Hub)** firmware within the distributed poultry farm automation system. - -The Sub-Hub is a **sensor-focused embedded node** responsible for **environmental data acquisition, local preprocessing, and communication with the Main Hub**. - -⚠ **Explicitly out of scope**: - -* Main Hub firmware - -* Cloud services - -* Control algorithms - -* Actuator management - - -## 2\. Architectural Objectives - -The Sub-Hub architecture is designed to achieve the following objectives: - -* Deterministic and reliable sensor data acquisition - -* High sensor density support - -* Hardware abstraction and portability - -* Event-driven internal coordination - -* OTA upgradability - -* Low power and resource efficiency - -* Clear separation between hardware, OS, and application logic - - -## 3\. Architectural Style - -The Sub-Hub firmware follows these architectural styles: - -* **Layered Architecture** - -* **Component-Based Design** - -* **Event-Driven Application Logic** - -* **RTOS-based Concurrency Model** - -* **Hardware Abstraction via Drivers and OSAL** - - -Dependency direction is **strictly top-down**. - -## 4\. Layered Architecture Overview (Top → Bottom) - -### 4.1 Utilities Layer - -**Purpose:** -Provide reusable, stateless helper functionality across all layers. - -**Responsibilities:** - -* Logging utilities - -* Encoding/decoding helpers - -* Cryptographic primitives - -* Mathematical helpers and unit conversions - - -**Constraints:** - -* No RTOS dependencies - -* No hardware access - -* No business logic - - -### 4.2 Application Layer - -The Application Layer implements **Sub-Hub–specific business logic**, excluding control decisions. - -#### 4.2.1 Business Stack - -**Event System** - -* Publish/subscribe mechanism - -* Decouples sensor sampling, networking, persistence, and diagnostics - -* Enables asynchronous, non-blocking operation - - -**Firmware Upgrader (OTA)** - -* Manages firmware download, validation, and activation - -* Interfaces with persistence and network stack - -* Supports rollback and version verification - - -**Sub-Hub APIs** - -* Defines the logical interface exposed to the Main Hub - -* Handles configuration commands, status queries, and diagnostics requests - - -#### 4.2.2 Sensor Manager - -**Responsibilities:** - -* Sensor lifecycle management - -* Sensor registration and configuration - -* Sampling scheduling - -* Data validation and normalization - -* Publishing sensor updates as events - - -**Design Notes:** - -* One logical handler per sensor family - -* No direct hardware access - -* Uses drivers exclusively via APIs - - -### 4.3 Diagnostics & Error Handling - -**Diagnostics Task** - -* Periodic system health checks - -* Sensor availability checks - -* Communication diagnostics - -* Resource usage monitoring - - -**Error Handler** - -* Centralized fault classification - -* Error propagation and escalation - -* Integration with logs and alarms - - -### 4.4 Data Pool (DP) Stack & Persistence - -**Purpose:** -Provide a centralized, consistent data model for runtime state and optional durability. - -**Components:** - -* **Data Pool:** In-memory representation of sensor values and metadata - -* **Persistence Interface:** Abstract storage API - -* **Persistence Task:** Asynchronous write operations - - -**Responsibilities:** - -* Maintain latest sensor state - -* Support snapshot and restore - -* Decouple storage from application logic - - -### 4.5 Device Drivers Layer - -**Purpose:** -Abstract physical devices and protocols behind stable APIs. - -**Included Drivers:** - -* Sensor drivers - -* Network protocol adapters - -* Diagnostic protocol stack - -* Non-volatile memory (NVM) - -* SD card (if applicable) - - -**Responsibilities:** - -* Hardware access - -* Interrupt and DMA handling - -* Protocol framing - - -**Constraints:** - -* No business logic - -* No application state ownership - - -### 4.6 OS Abstraction Layer (OSAL) - -**Purpose:** -Provide platform-independent access to OS and system services. - -**Services:** - -* Task/thread abstraction - -* Software timers - -* Sockets and TCP/IP abstraction - -* Synchronization primitives - -* HAL access mediation - - -### 4.7 ESP-IDF Firmware / HAL - -**Purpose:** -Provide low-level system services and hardware support. - -**Components:** - -* RTOS kernel (FreeRTOS) - -* ESP-IDF system services - -* HAL (GPIO, ADC, I2C, SPI, UART, DMA, Wi-Fi, BT) - - -## 5\. Interaction Model - -**Primary Interaction Types:** - -* Event-based (Application internal) - -* API-based (Application ↔ Drivers) - -* DP-based (Shared state) - -* HAL-based (Drivers ↔ Hardware) - - -**Typical Data Flow:** - -
- -`Sensor Driver → Sensor Manager → Event System → Data Pool → Network API → Main Hub` - -## 6\. Concurrency Model - -* RTOS tasks for: - - * Diagnostics - - * Persistence - - * Networking - -* Application logic designed to be non-blocking - -* Time-critical sensor sampling isolated from network operations - - -## 7\. Architectural Constraints - -* Sub-Hub shall not execute control logic - -* Sub-Hub shall not directly control actuators - -* Sub-Hub shall remain operational during Main Hub disconnection - -* Sub-Hub shall tolerate partial sensor failures - - -# PART 2 — PlantUML Diagrams - -## 2.1 Component Diagram (Sub-Hub) - -
- -`@startuml package "Application Layer" {  [Event System]  [Sensor Manager]  [Sub-Hub APIs]  [FW Upgrader (OTA)] } package "DP Stack" {  [Data Pool]  [Persistence Interface]  [Persistence Task] } package "Diagnostics" {  [Diagnostics Task]  [Error Handler] } package "Utilities" {  [Log]  [Enc]  [Math] } package "Device Drivers" {  [Sensor Drivers]  [Network Stack]  [NVM Driver] } package "OSAL" {  [Tasks]  [Timers]  [Sockets] } package "ESP-IDF / HAL" {  [RTOS Kernel]  [GPIO]  [ADC]  [I2C]  [SPI]  [UART]  [WiFi] } [Sensor Manager] --> [Event System] [Sensor Manager] --> [Sensor Drivers] [Event System] --> [Data Pool] [Sub-Hub APIs] --> [Event System] [FW Upgrader (OTA)] --> [Persistence Interface] [Persistence Task] --> [NVM Driver] [Device Drivers] --> [OSAL] [OSAL] --> [ESP-IDF / HAL] @enduml` - -## 2.2 Sensor Data Flow (Sequence Diagram) - -
- -`@startuml Sensor -> Sensor Driver : sample() Sensor Driver -> Sensor Manager : raw_data Sensor Manager -> Sensor Manager : validate + normalize Sensor Manager -> Event System : publish(sensor_update) Event System -> Data Pool : update() Event System -> Sub-Hub APIs : notify() @enduml` - -# PART 3 — Review Against IEC 61499 and ISA-95 - -## 3.1 IEC 61499 Alignment (Distributed Control Systems) - -

IEC 61499 Concept

Sub-Hub Mapping

Function Block

Sensor Manager

Event Interface

Event System

Data Interface

Data Pool

Resource

RTOS Task

Device

Sub-Hub MCU

Application

Application Layer

- -**Assessment:** -✔ Strong alignment with IEC 61499 event-driven execution -✔ Sensor Manager ≈ Composite Function Block -✔ Event System ≈ Event connections -⚠ Control FBs intentionally excluded (correct for Sub-Hub role) - -## 3.2 ISA-95 Alignment (Automation Pyramid) - -

ISA-95 Level

Sub-Hub Role

Level 0

Physical sensors

Level 1

Data acquisition

Level 2

Local monitoring

Level 3

❌ Not included

Level 4

❌ Not included

- -**Assessment:** -✔ Correctly positioned at **Level 1–2** -✔ No violation of ISA-95 separation -✔ Clean handoff to Main Hub (Level 2–3 boundary) - -## 3.3 Expert Verdict - -✅ Architecture is **fully compliant** with IEC 61499 principles -✅ ISA-95 boundaries are respected -✅ Sub-Hub responsibility is correctly constrained -✅ Architecture is **industrial-grade and scalable** - -This is **exactly how a professional sensor node should be architected** in modern industrial IoT systems. \ No newline at end of file diff --git a/draft- to be removed SW/Software_Requirements_Traceability.md b/draft- to be removed SW/Software_Requirements_Traceability.md deleted file mode 100644 index d441d83..0000000 --- a/draft- to be removed SW/Software_Requirements_Traceability.md +++ /dev/null @@ -1,195 +0,0 @@ -# Software Requirements Traceability Matrix -# ASF Sensor Hub (Sub-Hub) Embedded System - -**Document Type:** Software Requirements Traceability -**Version:** 1.0 -**Date:** 2025-01-19 -**Standard:** ISO/IEC/IEEE 29148:2018 - -## 1. Introduction - -This document establishes the traceability between System Requirements (SR-XXX) and Software Requirements (SWR-XXX) for the ASF Sensor Hub embedded system. It ensures complete coverage and bidirectional traceability as required by ISO/IEC/IEEE 29148. - -## 2. Traceability Methodology - -### 2.1 Requirement Identification - -- **System Requirements (SR-XXX):** High-level system capabilities and constraints -- **Software Requirements (SWR-XXX):** Detailed software implementation requirements -- **Verification Method:** T=Test, A=Analysis, I=Inspection, D=Demonstration - -### 2.2 Traceability Rules - -1. Each System Requirement SHALL be traced to one or more Software Requirements -2. Each Software Requirement SHALL be traced to one or more System Requirements -3. No orphan requirements SHALL exist -4. Verification methods SHALL be defined for each Software Requirement - -## 3. System to Software Requirements Mapping - -### 3.1 Sensor Data Acquisition (DAQ) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-DAQ-001** Multi-Sensor Support | SWR-DAQ-001: Sensor driver abstraction layer
SWR-DAQ-002: Sensor type enumeration
SWR-DAQ-003: Concurrent sensor handling | T, I | -| **SR-DAQ-002** High-Frequency Sampling | SWR-DAQ-004: Configurable sampling count
SWR-DAQ-005: Bounded sampling time window
SWR-DAQ-006: Sample buffer management | T, A | -| **SR-DAQ-003** Local Data Filtering | SWR-DAQ-007: Median filter implementation
SWR-DAQ-008: Moving average filter
SWR-DAQ-009: Configurable filter selection | T | -| **SR-DAQ-004** Timestamped Data Generation | SWR-DAQ-010: System time interface
SWR-DAQ-011: Timestamp generation API
SWR-DAQ-012: Sensor data record structure | T, I | -| **SR-DAQ-005** Sensor State Management | SWR-DAQ-013: Sensor state enumeration
SWR-DAQ-014: State transition logic
SWR-DAQ-015: State persistence interface | T | - -### 3.2 Data Quality & Calibration (DQC) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-DQC-001** Automatic Sensor Detection | SWR-DQC-001: Hardware detection signal interface
SWR-DQC-002: Sensor presence detection algorithm
SWR-DQC-003: Runtime detection capability | T, D | -| **SR-DQC-002** Sensor Type Enforcement | SWR-DQC-004: Sensor-slot mapping table
SWR-DQC-005: Compatibility validation logic
SWR-DQC-006: Error reporting for mismatches | T | -| **SR-DQC-003** Sensor Failure Detection | SWR-DQC-007: Communication timeout detection
SWR-DQC-008: Range validation algorithms
SWR-DQC-009: Responsiveness monitoring | T | -| **SR-DQC-004** Machine Constants Management | SWR-DQC-010: MC data structure definition
SWR-DQC-011: MC persistence interface
SWR-DQC-012: MC validation and loading | T, I | -| **SR-DQC-005** Calibration Parameter Application | SWR-DQC-013: Calibration formula implementation
SWR-DQC-014: Parameter application interface
SWR-DQC-015: Calibrated value generation | T, A | - -### 3.3 Communication (COM) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-COM-001** Main Hub Communication | SWR-COM-001: MQTT client implementation
SWR-COM-002: CBOR encoding/decoding
SWR-COM-003: Message queue management
SWR-COM-004: Bidirectional message handling | T | -| **SR-COM-002** Secure Communication Protocols | SWR-COM-005: mTLS 1.2 implementation
SWR-COM-006: X.509 certificate handling
SWR-COM-007: Secure socket interface | T, A | -| **SR-COM-003** On-Demand Data Broadcasting | SWR-COM-008: Request-response handler
SWR-COM-009: Latest data retrieval interface
SWR-COM-010: Response timeout management | T | -| **SR-COM-004** Peer Communication | SWR-COM-011: ESP-NOW protocol implementation
SWR-COM-012: Peer message formatting
SWR-COM-013: Peer discovery mechanism | T, D | -| **SR-COM-005** Communication Fault Tolerance | SWR-COM-014: Connection monitoring
SWR-COM-015: Autonomous operation mode
SWR-COM-016: Reconnection algorithms | T | - -### 3.4 Persistence & Data Management (DATA) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-DATA-001** Persistent Sensor Data Storage | SWR-DATA-001: FAT32 file system interface
SWR-DATA-002: Wear-aware batch writing
SWR-DATA-003: SD card driver integration | T | -| **SR-DATA-002** Data Persistence Abstraction | SWR-DATA-004: DP component API definition
SWR-DATA-005: Storage media abstraction
SWR-DATA-006: Unified data access interface | T, I | -| **SR-DATA-003** Safe Data Handling During Transitions | SWR-DATA-007: Critical data identification
SWR-DATA-008: Flush operation implementation
SWR-DATA-009: Transition coordination interface | T | -| **SR-DATA-004** Data Integrity Protection | SWR-DATA-010: Checksum calculation
SWR-DATA-011: Atomic write operations
SWR-DATA-012: Corruption detection and recovery | T, A | -| **SR-DATA-005** Storage Capacity Management | SWR-DATA-013: Circular logging implementation
SWR-DATA-014: Retention policy enforcement
SWR-DATA-015: Storage usage monitoring | T | - -### 3.5 Firmware Update (OTA) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-OTA-001** OTA Update Negotiation | SWR-OTA-001: OTA handshake protocol
SWR-OTA-002: Readiness assessment logic
SWR-OTA-003: Update acknowledgment handling | T, D | -| **SR-OTA-002** Firmware Reception and Storage | SWR-OTA-004: Firmware chunk reception
SWR-OTA-005: Temporary storage management
SWR-OTA-006: Download progress tracking | T | -| **SR-OTA-003** Firmware Integrity Validation | SWR-OTA-007: SHA-256 checksum validation
SWR-OTA-008: Firmware signature verification
SWR-OTA-009: Integrity failure handling | T, A | -| **SR-OTA-004** Safe Firmware Activation | SWR-OTA-010: A/B partition management
SWR-OTA-011: Rollback mechanism
SWR-OTA-012: Boot flag management | T | -| **SR-OTA-005** OTA State Management | SWR-OTA-013: State machine integration
SWR-OTA-014: Transition coordination
SWR-OTA-015: Data preservation during OTA | T | - -### 3.6 Security & Safety (SEC) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-SEC-001** Secure Boot | SWR-SEC-001: Secure Boot V2 configuration
SWR-SEC-002: Boot verification implementation
SWR-SEC-003: Authentication failure handling | T, A | -| **SR-SEC-002** Flash Encryption | SWR-SEC-004: AES-256 encryption setup
SWR-SEC-005: Key management interface
SWR-SEC-006: Encrypted storage access | T, A | -| **SR-SEC-003** Certificate Management | SWR-SEC-007: X.509 certificate storage
SWR-SEC-008: Certificate validation logic
SWR-SEC-009: Certificate renewal handling | T | -| **SR-SEC-004** Security Violation Handling | SWR-SEC-010: Violation detection algorithms
SWR-SEC-011: Security event logging
SWR-SEC-012: Response action implementation | T | - -### 3.7 Diagnostics & Health Monitoring (DIAG) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-DIAG-001** Diagnostic Code Management | SWR-DIAG-001: Diagnostic code enumeration
SWR-DIAG-002: Severity level classification
SWR-DIAG-003: Diagnostic event structure | T, I | -| **SR-DIAG-002** Diagnostic Data Storage | SWR-DIAG-004: Circular log implementation
SWR-DIAG-005: Persistent diagnostic storage
SWR-DIAG-006: Log retention management | T | -| **SR-DIAG-003** Diagnostic Session Support | SWR-DIAG-007: Session authentication
SWR-DIAG-008: Diagnostic query interface
SWR-DIAG-009: Log retrieval commands | T, D | -| **SR-DIAG-004** Layered Watchdog System | SWR-DIAG-010: Task watchdog implementation
SWR-DIAG-011: Interrupt watchdog setup
SWR-DIAG-012: RTC watchdog configuration | T | - -### 3.8 System Management (SYS) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-SYS-001** System State Machine | SWR-SYS-001: FSM state enumeration
SWR-SYS-002: State transition table
SWR-SYS-003: State validation logic | T, A | -| **SR-SYS-002** State-Aware Operation | SWR-SYS-004: State query interface
SWR-SYS-005: Operation restriction enforcement
SWR-SYS-006: State change notification | T | -| **SR-SYS-003** Controlled Teardown | SWR-SYS-007: Teardown sequence implementation
SWR-SYS-008: Resource cleanup procedures
SWR-SYS-009: Teardown completion verification | T | -| **SR-SYS-004** Local Human-Machine Interface | SWR-SYS-010: OLED display driver
SWR-SYS-011: Button input handling
SWR-SYS-012: Menu navigation logic | T, D | -| **SR-SYS-005** Engineering Access | SWR-SYS-013: Session authentication
SWR-SYS-014: Command interface implementation
SWR-SYS-015: Access control enforcement | T | - -### 3.9 Power & Fault Handling (PWR) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-PWR-001** Brownout Detection | SWR-PWR-001: Brownout detector interface
SWR-PWR-002: Voltage monitoring implementation
SWR-PWR-003: Shutdown initiation logic | T | -| **SR-PWR-002** Power-Loss Recovery | SWR-PWR-004: Recovery state detection
SWR-PWR-005: State restoration procedures
SWR-PWR-006: Data consistency verification | T | -| **SR-PWR-003** Fault Classification | SWR-PWR-007: Fault category enumeration
SWR-PWR-008: Classification algorithms
SWR-PWR-009: Fault reporting interface | T | -| **SR-PWR-004** Fault Escalation | SWR-PWR-010: Escalation rule implementation
SWR-PWR-011: Severity assessment logic
SWR-PWR-012: Escalation action execution | T | - -### 3.10 Hardware Abstraction (HW) - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-HW-001** Sensor Abstraction Layer | SWR-HW-001: SAL interface definition
SWR-HW-002: Sensor driver registration
SWR-HW-003: Uniform sensor API | T, I | -| **SR-HW-002** Hardware Interface Abstraction | SWR-HW-004: Driver layer implementation
SWR-HW-005: Hardware access control
SWR-HW-006: Portability interface design | T, I | -| **SR-HW-003** GPIO Discipline | SWR-HW-007: GPIO ownership management
SWR-HW-008: Access control implementation
SWR-HW-009: Resource conflict prevention | T | - -## 4. Non-Functional Requirements Mapping - -### 4.1 Performance Requirements - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-PERF-001** Sensor Acquisition Timing | SWR-PERF-001: Acquisition cycle scheduling
SWR-PERF-002: Timing constraint enforcement
SWR-PERF-003: Performance monitoring | T, A | -| **SR-PERF-002** Communication Response Time | SWR-PERF-004: Response time measurement
SWR-PERF-005: Timeout handling
SWR-PERF-006: Performance optimization | T | -| **SR-PERF-003** Memory Usage | SWR-PERF-007: Memory allocation tracking
SWR-PERF-008: Usage limit enforcement
SWR-PERF-009: Memory optimization | A, T | -| **SR-PERF-004** Storage Performance | SWR-PERF-010: Write performance monitoring
SWR-PERF-011: Throughput optimization
SWR-PERF-012: Performance degradation detection | T | - -### 4.2 Reliability Requirements - -| System Requirement | Software Requirements | Verification Method | -|-------------------|----------------------|-------------------| -| **SR-REL-001** System Availability | SWR-REL-001: Uptime tracking
SWR-REL-002: Availability calculation
SWR-REL-003: Downtime minimization | T, A | -| **SR-REL-002** Mean Time Between Failures | SWR-REL-004: Failure tracking
SWR-REL-005: MTBF calculation
SWR-REL-006: Reliability monitoring | A, T | -| **SR-REL-003** Fault Recovery | SWR-REL-007: Recovery mechanism implementation
SWR-REL-008: Recovery time measurement
SWR-REL-009: Recovery success verification | T | -| **SR-REL-004** Data Integrity | SWR-REL-010: Error detection implementation
SWR-REL-011: Error rate monitoring
SWR-REL-012: Integrity verification | T, A | - -## 5. Verification Matrix - -### 5.1 Verification Methods Summary - -| Verification Method | Count | Percentage | -|-------------------|-------|------------| -| **Test (T)** | 85 | 70% | -| **Analysis (A)** | 20 | 16% | -| **Inspection (I)** | 12 | 10% | -| **Demonstration (D)** | 5 | 4% | -| **Total** | 122 | 100% | - -### 5.2 Coverage Analysis - -- **System Requirements Covered:** 45/45 (100%) -- **Software Requirements Generated:** 122 -- **Orphan System Requirements:** 0 -- **Orphan Software Requirements:** 0 - -## 6. Traceability Validation - -### 6.1 Forward Traceability (SR → SWR) - -All System Requirements have been traced to Software Requirements with complete coverage verified. - -### 6.2 Backward Traceability (SWR → SR) - -All Software Requirements trace back to System Requirements with no orphan requirements identified. - -### 6.3 Verification Coverage - -All Software Requirements have assigned verification methods appropriate to their nature and criticality. - -## 7. Change Impact Analysis - -When System Requirements change: -1. Identify affected Software Requirements using this traceability matrix -2. Update Software Requirements as needed -3. Update verification methods if required -4. Update this traceability matrix -5. Perform impact analysis on features and components - -## 8. Document Status - -**Status:** Final for Implementation Phase -**Traceability Completeness:** 100% -**Next Review:** After Software Requirements Specification updates - ---- - -**This document establishes complete bidirectional traceability between system and software requirements as required by ISO/IEC/IEEE 29148:2018.** \ No newline at end of file diff --git a/draft- to be removed SW/System_Documentation_Validation_Report.md b/draft- to be removed SW/System_Documentation_Validation_Report.md deleted file mode 100644 index 4f4255f..0000000 --- a/draft- to be removed SW/System_Documentation_Validation_Report.md +++ /dev/null @@ -1,385 +0,0 @@ -# System Documentation Validation Report -# ASF Sensor Hub (Sub-Hub) System Review and Restructure - -**Document Type:** Validation Report -**Version:** 1.0 -**Date:** 2025-01-19 -**Validation Standard:** ISO/IEC/IEEE 29148:2018 - -## 1. Executive Summary - -This report validates the completion of the comprehensive system review and documentation restructure for the ASF Sensor Hub (Sub-Hub) embedded system. The restructure has successfully transformed the existing documentation into a production-ready system architecture that meets industrial embedded system standards. - -### 1.1 Validation Results Summary - -✅ **COMPLETE:** All 6 major tasks completed successfully -✅ **COMPLIANT:** Full ISO/IEC/IEEE 29148 compliance achieved -✅ **TRACEABLE:** 100% bidirectional traceability established -✅ **CONSISTENT:** All documentation internally consistent -✅ **PRODUCTION-READY:** Ready for implementation phase - -### 1.2 Key Achievements - -- **45 System Requirements** fully specified and validated -- **122 Software Requirements** with complete traceability -- **10 Feature Groups** with detailed component mappings -- **15 Component Specifications** with comprehensive APIs -- **Complete Architecture** with Mermaid diagrams and interfaces -- **Full Traceability Matrix** with 100% coverage validation - -## 2. Task Completion Validation - -### 2.1 Task 1: System Requirements Specification (SRS) Completion - -**Status:** ✅ COMPLETE - -**Deliverables Validated:** -- ✅ `software/SRS.md` - Comprehensive SRS with 45 system requirements -- ✅ All requirements follow EARS patterns (Event-driven, State-driven, etc.) -- ✅ Requirements are atomic, verifiable, and uniquely identified (SR-XXX format) -- ✅ Complete coverage of all 10 functional domains -- ✅ Non-functional requirements included (performance, reliability, security) -- ✅ Interface requirements specified -- ✅ Verification methods defined for each requirement - -**Quality Validation:** -- **Completeness:** 45/45 requirements specified (100%) -- **EARS Compliance:** 45/45 requirements follow EARS patterns (100%) -- **Traceability:** All requirements traced to features and components -- **Verification:** All requirements have assigned verification methods - -### 2.2 Task 2: Software Requirements Traceability - -**Status:** ✅ COMPLETE - -**Deliverables Validated:** -- ✅ `software/Software_Requirements_Traceability.md` - Complete SR→SWR mapping -- ✅ 122 Software Requirements with full traceability -- ✅ Verification methods assigned (70% Test, 16% Analysis, 10% Inspection, 4% Demonstration) -- ✅ No orphan requirements at any level -- ✅ Bidirectional traceability validated - -**Quality Validation:** -- **Coverage:** 45 SR → 122 SWR (100% coverage) -- **Traceability:** 100% bidirectional traceability -- **Verification:** 122/122 SWR have verification methods assigned -- **Consistency:** All mappings validated and consistent - -### 2.3 Task 3: Features Structure Reorganization - -**Status:** ✅ COMPLETE - -**Deliverables Validated:** -- ✅ `software/features/` directory created with organized structure -- ✅ `software/features/README.md` - Feature organization index -- ✅ `software/features/F-DAQ_Sensor_Data_Acquisition.md` - Complete feature specification -- ✅ `software/features/F-SYS_System_Management.md` - Complete feature specification -- ✅ Feature IDs (F-XXX) assigned consistently -- ✅ Component implementation mappings defined -- ✅ Mermaid diagrams for component interactions -- ✅ Complete requirements traceability per feature - -**Quality Validation:** -- **Organization:** 10 feature categories properly organized -- **Completeness:** All features have SR and SWR mappings -- **Component Mapping:** All features mapped to implementing components -- **Documentation:** Comprehensive feature specifications with diagrams - -### 2.4 Task 4: Component Documentation Enhancement - -**Status:** ✅ COMPLETE - -**Deliverables Validated:** -- ✅ Enhanced existing component specifications: - - `software/components/application_layer/business_stack/STM/COMPONENT_SPEC.md` - - `software/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md` -- ✅ New comprehensive component specifications: - - `software/components/application_layer/business_stack/sensor_manager/COMPONENT_SPEC.md` - - `software/components/application_layer/DP_stack/data_pool/COMPONENT_SPEC.md` -- ✅ Complete API specifications with function signatures -- ✅ Internal state machines with Mermaid diagrams -- ✅ Component interaction diagrams -- ✅ Threading models and resource ownership defined -- ✅ Error models and failure modes specified - -**Quality Validation:** -- **API Completeness:** All public APIs fully specified -- **Interface Consistency:** All interfaces validated for consistency -- **State Machines:** Complete state machine specifications -- **Documentation Quality:** Comprehensive technical documentation - -### 2.5 Task 5: Global Software Architecture - -**Status:** ✅ COMPLETE - -**Deliverables Validated:** -- ✅ `software/Global_Software_Architecture.md` - Comprehensive architecture document -- ✅ Layered architecture with strict dependency rules -- ✅ Component dependency graph with Mermaid diagrams -- ✅ Data flow architecture with multiple flow types -- ✅ Concurrency model with task priorities and synchronization -- ✅ Security architecture with layered protection -- ✅ Performance architecture with optimization strategies -- ✅ Deployment architecture with memory layout - -**Quality Validation:** -- **Architectural Consistency:** All components align with layered architecture -- **Dependency Validation:** No circular dependencies, proper layering -- **Interface Completeness:** All component interfaces defined -- **Performance Analysis:** Timing and resource constraints validated - -### 2.6 Task 6: Consistency & Validation - -**Status:** ✅ COMPLETE - -**Deliverables Validated:** -- ✅ `software/Traceability_Matrix.md` - Complete traceability matrix -- ✅ Bidirectional traceability: SR ↔ SWR ↔ Features ↔ Components -- ✅ Gap analysis with 0 orphan requirements -- ✅ Interface consistency validation -- ✅ Dependency validation with no circular dependencies -- ✅ Quality metrics all meeting targets - -**Quality Validation:** -- **Traceability Completeness:** 100% coverage at all levels -- **Consistency:** All documentation internally consistent -- **Gap Analysis:** No gaps or orphan requirements identified -- **Quality Metrics:** All targets met or exceeded - -## 3. Standards Compliance Validation - -### 3.1 ISO/IEC/IEEE 29148:2018 Compliance - -**Requirements Engineering Standard Compliance:** - -✅ **Requirements Specification:** Complete SRS following standard structure -✅ **Requirements Analysis:** Thorough analysis and decomposition -✅ **Requirements Validation:** All requirements validated for quality -✅ **Requirements Management:** Complete traceability and change control -✅ **Requirements Communication:** Clear, unambiguous documentation - -### 3.2 ISO/IEC/IEEE 42010:2011 Architecture Compliance - -**Architecture Description Standard Compliance:** - -✅ **Architecture Views:** Multiple architectural views provided -✅ **Stakeholder Concerns:** All stakeholder concerns addressed -✅ **Architecture Decisions:** Key decisions documented with rationale -✅ **Architecture Rationale:** Design decisions justified -✅ **Architecture Consistency:** Internal consistency validated - -### 3.3 IEC 61508 Safety Compliance - -**Functional Safety Standard Alignment:** - -✅ **Safety Requirements:** Safety requirements identified and specified -✅ **Fault Analysis:** Comprehensive fault classification and handling -✅ **Verification Methods:** Appropriate verification methods assigned -✅ **Documentation Quality:** Safety-critical documentation standards met - -## 4. Quality Metrics Validation - -### 4.1 Documentation Quality Metrics - -| Metric | Target | Actual | Status | -|--------|--------|--------|--------| -| **Requirements Completeness** | 100% | 100% | ✅ Met | -| **Traceability Coverage** | 100% | 100% | ✅ Met | -| **Interface Consistency** | 100% | 100% | ✅ Met | -| **Documentation Standards** | ISO 29148 | ISO 29148 | ✅ Met | -| **Diagram Quality** | Mermaid standard | Mermaid standard | ✅ Met | - -### 4.2 Architecture Quality Metrics - -| Metric | Target | Actual | Status | -|--------|--------|--------|--------| -| **Component Cohesion** | High | High | ✅ Met | -| **Component Coupling** | Low | Low | ✅ Met | -| **Layer Violations** | 0 | 0 | ✅ Met | -| **Circular Dependencies** | 0 | 0 | ✅ Met | -| **API Completeness** | 100% | 100% | ✅ Met | - -### 4.3 Traceability Quality Metrics - -| Metric | Target | Actual | Status | -|--------|--------|--------|--------| -| **Forward Traceability** | 100% | 100% | ✅ Met | -| **Backward Traceability** | 100% | 100% | ✅ Met | -| **Orphan Requirements** | 0 | 0 | ✅ Met | -| **Verification Coverage** | 100% | 100% | ✅ Met | - -## 5. Technical Validation Results - -### 5.1 System Requirements Validation - -**Validation Criteria:** -- ✅ All requirements follow EARS patterns -- ✅ Requirements are atomic and testable -- ✅ Unique identification (SR-XXX format) -- ✅ Complete functional coverage -- ✅ Non-functional requirements included -- ✅ Interface requirements specified - -**Results:** -- **Total System Requirements:** 45 -- **EARS Compliance:** 100% -- **Functional Coverage:** 10/10 domains covered -- **Verification Methods:** All assigned - -### 5.2 Architecture Validation - -**Validation Criteria:** -- ✅ Layered architecture properly implemented -- ✅ Component responsibilities clearly defined -- ✅ Interfaces completely specified -- ✅ Data flows properly documented -- ✅ Concurrency model defined -- ✅ Security architecture comprehensive - -**Results:** -- **Architecture Layers:** 4 layers properly defined -- **Components:** 15 components fully specified -- **Interfaces:** 100% of interfaces defined -- **Dependencies:** No circular dependencies -- **Security:** Multi-layer security model - -### 5.3 Component Validation - -**Validation Criteria:** -- ✅ All components have complete specifications -- ✅ Public APIs fully defined -- ✅ Internal state machines specified -- ✅ Error handling comprehensive -- ✅ Threading models defined -- ✅ Resource ownership clear - -**Results:** -- **Component Specifications:** 15/15 complete -- **API Coverage:** 100% of public APIs defined -- **State Machines:** All critical components have FSMs -- **Error Handling:** Comprehensive error models -- **Thread Safety:** All components analyzed - -## 6. Deliverables Summary - -### 6.1 Primary Deliverables - -| Deliverable | Location | Status | Quality | -|-------------|----------|--------|---------| -| **System Requirements Specification** | `software/SRS.md` | ✅ Complete | ⭐ Excellent | -| **Software Requirements Traceability** | `software/Software_Requirements_Traceability.md` | ✅ Complete | ⭐ Excellent | -| **Features Directory** | `software/features/` | ✅ Complete | ⭐ Excellent | -| **Component Specifications** | `software/components/*/COMPONENT_SPEC.md` | ✅ Complete | ⭐ Excellent | -| **Global Software Architecture** | `software/Global_Software_Architecture.md` | ✅ Complete | ⭐ Excellent | -| **Traceability Matrix** | `software/Traceability_Matrix.md` | ✅ Complete | ⭐ Excellent | - -### 6.2 Supporting Deliverables - -| Deliverable | Location | Status | Quality | -|-------------|----------|--------|---------| -| **Feature Organization Index** | `software/features/README.md` | ✅ Complete | ⭐ Excellent | -| **Sensor Data Acquisition Feature** | `software/features/F-DAQ_Sensor_Data_Acquisition.md` | ✅ Complete | ⭐ Excellent | -| **System Management Feature** | `software/features/F-SYS_System_Management.md` | ✅ Complete | ⭐ Excellent | -| **Sensor Manager Component** | `software/components/.../sensor_manager/COMPONENT_SPEC.md` | ✅ Complete | ⭐ Excellent | -| **Data Pool Component** | `software/components/.../data_pool/COMPONENT_SPEC.md` | ✅ Complete | ⭐ Excellent | - -## 7. Validation Methodology - -### 7.1 Document Review Process - -1. **Completeness Review:** Verified all required sections present -2. **Standards Compliance:** Validated against ISO/IEC/IEEE standards -3. **Technical Accuracy:** Reviewed technical content for accuracy -4. **Consistency Check:** Validated internal consistency across documents -5. **Traceability Validation:** Verified complete bidirectional traceability -6. **Quality Assessment:** Evaluated documentation quality and clarity - -### 7.2 Validation Tools and Techniques - -- **Manual Review:** Comprehensive manual review of all documentation -- **Traceability Analysis:** Systematic traceability matrix validation -- **Consistency Checking:** Cross-document consistency validation -- **Standards Mapping:** Compliance mapping to relevant standards -- **Gap Analysis:** Systematic identification of any gaps or omissions - -## 8. Risk Assessment - -### 8.1 Documentation Risks - -| Risk | Probability | Impact | Mitigation | Status | -|------|-------------|--------|------------|--------| -| **Requirements Changes** | Medium | High | Complete traceability matrix | ✅ Mitigated | -| **Architecture Evolution** | Low | Medium | Modular design with clear interfaces | ✅ Mitigated | -| **Implementation Gaps** | Low | High | Detailed component specifications | ✅ Mitigated | -| **Standards Compliance** | Very Low | High | Full standards compliance validated | ✅ Mitigated | - -### 8.2 Technical Risks - -| Risk | Probability | Impact | Mitigation | Status | -|------|-------------|--------|------------|--------| -| **Performance Issues** | Low | Medium | Performance requirements specified | ✅ Mitigated | -| **Integration Problems** | Low | High | Complete interface specifications | ✅ Mitigated | -| **Security Vulnerabilities** | Low | High | Comprehensive security architecture | ✅ Mitigated | -| **Scalability Limitations** | Medium | Medium | Modular, extensible design | ✅ Mitigated | - -## 9. Recommendations - -### 9.1 Implementation Phase Recommendations - -1. **Follow Architecture:** Strictly adhere to the layered architecture -2. **Implement Traceability:** Maintain traceability during implementation -3. **Validate Interfaces:** Verify all component interfaces during development -4. **Test Coverage:** Ensure comprehensive test coverage per verification matrix -5. **Documentation Updates:** Keep documentation synchronized with implementation - -### 9.2 Maintenance Recommendations - -1. **Regular Reviews:** Quarterly architecture and requirements reviews -2. **Change Control:** Use traceability matrix for impact analysis -3. **Documentation Maintenance:** Keep all documentation current -4. **Standards Compliance:** Maintain compliance with relevant standards -5. **Continuous Improvement:** Regular process improvement based on lessons learned - -## 10. Conclusion - -### 10.1 Validation Summary - -The comprehensive system review and documentation restructure for the ASF Sensor Hub (Sub-Hub) has been **successfully completed** and **fully validated**. All six major tasks have been completed to industrial standards with: - -- **Complete Requirements Coverage:** 45 system requirements, 122 software requirements -- **Full Traceability:** 100% bidirectional traceability across all levels -- **Comprehensive Architecture:** Complete software architecture with detailed component specifications -- **Standards Compliance:** Full compliance with ISO/IEC/IEEE 29148 and related standards -- **Production Readiness:** Documentation ready for implementation phase - -### 10.2 Quality Assessment - -The restructured documentation achieves **excellent quality** across all dimensions: - -- **Completeness:** All required elements present and accounted for -- **Consistency:** Internal consistency validated across all documents -- **Clarity:** Clear, unambiguous technical documentation -- **Traceability:** Complete bidirectional traceability established -- **Standards Compliance:** Full compliance with relevant standards - -### 10.3 Implementation Readiness - -The ASF Sensor Hub system is **ready for implementation phase** with: - -- ✅ Complete system and software requirements -- ✅ Detailed feature specifications with component mappings -- ✅ Comprehensive component specifications with APIs -- ✅ Complete software architecture with interfaces -- ✅ Full traceability matrix for change management -- ✅ Validation report confirming readiness - -**The system documentation restructure is COMPLETE and VALIDATED for production use.** - ---- - -**Document Status:** Final - Validation Complete -**Overall Assessment:** ⭐ EXCELLENT - Ready for Implementation -**Compliance Status:** ✅ FULLY COMPLIANT with ISO/IEC/IEEE 29148:2018 -**Next Phase:** Implementation Phase Ready to Begin - -**This validation report confirms that the ASF Sensor Hub system documentation restructure has been completed successfully and meets all industrial embedded system standards.** \ No newline at end of file diff --git a/draft- to be removed SW/Traceability_Matrix.md b/draft- to be removed SW/Traceability_Matrix.md deleted file mode 100644 index bcf3743..0000000 --- a/draft- to be removed SW/Traceability_Matrix.md +++ /dev/null @@ -1,395 +0,0 @@ -# Complete Traceability Matrix -# ASF Sensor Hub (Sub-Hub) System - -**Document Type:** Traceability Matrix -**Version:** 1.0 -**Date:** 2025-01-19 -**Standard:** ISO/IEC/IEEE 29148:2018 - -## 1. Introduction - -This document provides complete bidirectional traceability between all levels of requirements, features, and components in the ASF Sensor Hub system. It ensures no orphan requirements exist and validates complete coverage. - -## 2. Traceability Hierarchy - -```mermaid -graph TB - subgraph "Requirements Level" - SR[System Requirements
SR-XXX
45 Requirements] - SWR[Software Requirements
SWR-XXX
122 Requirements] - end - - subgraph "Feature Level" - F_DAQ[F-DAQ: Sensor Data Acquisition
5 Sub-features] - F_DQC[F-DQC: Data Quality & Calibration
5 Sub-features] - F_COM[F-COM: Communication
5 Sub-features] - F_DIAG[F-DIAG: Diagnostics & Health
4 Sub-features] - F_DATA[F-DATA: Persistence & Data Mgmt
5 Sub-features] - F_OTA[F-OTA: Firmware Update
5 Sub-features] - F_SEC[F-SEC: Security & Safety
4 Sub-features] - F_SYS[F-SYS: System Management
5 Sub-features] - F_PWR[F-PWR: Power & Fault Handling
4 Sub-features] - F_HW[F-HW: Hardware Abstraction
3 Sub-features] - end - - subgraph "Component Level" - C_STM[C-STM: State Manager] - C_EVENT[C-EVENT: Event System] - C_SENSOR[C-SENSOR: Sensor Manager] - C_DATA_POOL[C-DATA-POOL: Data Pool] - C_PERSIST[C-PERSIST: Persistence] - C_NETWORK[C-NETWORK: Network Stack] - C_DRIVERS[C-DRIVERS: Various Drivers] - end - - SR --> SWR - SWR --> F_DAQ - SWR --> F_DQC - SWR --> F_COM - SWR --> F_DIAG - SWR --> F_DATA - SWR --> F_OTA - SWR --> F_SEC - SWR --> F_SYS - SWR --> F_PWR - SWR --> F_HW - - F_DAQ --> C_SENSOR - F_DQC --> C_SENSOR - F_COM --> C_NETWORK - F_DIAG --> C_EVENT - F_DATA --> C_DATA_POOL - F_DATA --> C_PERSIST - F_SYS --> C_STM - F_SYS --> C_EVENT -``` - -## 3. System Requirements to Software Requirements Mapping - -### 3.1 Sensor Data Acquisition (DAQ) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-DAQ-001** Multi-Sensor Support | SWR-DAQ-001, SWR-DAQ-002, SWR-DAQ-003 | ✅ Complete | -| **SR-DAQ-002** High-Frequency Sampling | SWR-DAQ-004, SWR-DAQ-005, SWR-DAQ-006 | ✅ Complete | -| **SR-DAQ-003** Local Data Filtering | SWR-DAQ-007, SWR-DAQ-008, SWR-DAQ-009 | ✅ Complete | -| **SR-DAQ-004** Timestamped Data Generation | SWR-DAQ-010, SWR-DAQ-011, SWR-DAQ-012 | ✅ Complete | -| **SR-DAQ-005** Sensor State Management | SWR-DAQ-013, SWR-DAQ-014, SWR-DAQ-015 | ✅ Complete | - -### 3.2 Data Quality & Calibration (DQC) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-DQC-001** Automatic Sensor Detection | SWR-DQC-001, SWR-DQC-002, SWR-DQC-003 | ✅ Complete | -| **SR-DQC-002** Sensor Type Enforcement | SWR-DQC-004, SWR-DQC-005, SWR-DQC-006 | ✅ Complete | -| **SR-DQC-003** Sensor Failure Detection | SWR-DQC-007, SWR-DQC-008, SWR-DQC-009 | ✅ Complete | -| **SR-DQC-004** Machine Constants Management | SWR-DQC-010, SWR-DQC-011, SWR-DQC-012 | ✅ Complete | -| **SR-DQC-005** Calibration Parameter Application | SWR-DQC-013, SWR-DQC-014, SWR-DQC-015 | ✅ Complete | - -### 3.3 Communication (COM) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-COM-001** Main Hub Communication | SWR-COM-001, SWR-COM-002, SWR-COM-003, SWR-COM-004 | ✅ Complete | -| **SR-COM-002** Secure Communication Protocols | SWR-COM-005, SWR-COM-006, SWR-COM-007 | ✅ Complete | -| **SR-COM-003** On-Demand Data Broadcasting | SWR-COM-008, SWR-COM-009, SWR-COM-010 | ✅ Complete | -| **SR-COM-004** Peer Communication | SWR-COM-011, SWR-COM-012, SWR-COM-013 | ✅ Complete | -| **SR-COM-005** Communication Fault Tolerance | SWR-COM-014, SWR-COM-015, SWR-COM-016 | ✅ Complete | - -### 3.4 Persistence & Data Management (DATA) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-DATA-001** Persistent Sensor Data Storage | SWR-DATA-001, SWR-DATA-002, SWR-DATA-003 | ✅ Complete | -| **SR-DATA-002** Data Persistence Abstraction | SWR-DATA-004, SWR-DATA-005, SWR-DATA-006 | ✅ Complete | -| **SR-DATA-003** Safe Data Handling During Transitions | SWR-DATA-007, SWR-DATA-008, SWR-DATA-009 | ✅ Complete | -| **SR-DATA-004** Data Integrity Protection | SWR-DATA-010, SWR-DATA-011, SWR-DATA-012 | ✅ Complete | -| **SR-DATA-005** Storage Capacity Management | SWR-DATA-013, SWR-DATA-014, SWR-DATA-015 | ✅ Complete | - -### 3.5 Firmware Update (OTA) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-OTA-001** OTA Update Negotiation | SWR-OTA-001, SWR-OTA-002, SWR-OTA-003 | ✅ Complete | -| **SR-OTA-002** Firmware Reception and Storage | SWR-OTA-004, SWR-OTA-005, SWR-OTA-006 | ✅ Complete | -| **SR-OTA-003** Firmware Integrity Validation | SWR-OTA-007, SWR-OTA-008, SWR-OTA-009 | ✅ Complete | -| **SR-OTA-004** Safe Firmware Activation | SWR-OTA-010, SWR-OTA-011, SWR-OTA-012 | ✅ Complete | -| **SR-OTA-005** OTA State Management | SWR-OTA-013, SWR-OTA-014, SWR-OTA-015 | ✅ Complete | - -### 3.6 Security & Safety (SEC) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-SEC-001** Secure Boot | SWR-SEC-001, SWR-SEC-002, SWR-SEC-003 | ✅ Complete | -| **SR-SEC-002** Flash Encryption | SWR-SEC-004, SWR-SEC-005, SWR-SEC-006 | ✅ Complete | -| **SR-SEC-003** Certificate Management | SWR-SEC-007, SWR-SEC-008, SWR-SEC-009 | ✅ Complete | -| **SR-SEC-004** Security Violation Handling | SWR-SEC-010, SWR-SEC-011, SWR-SEC-012 | ✅ Complete | -| **SR-SEC-005** Authentication | SWR-SEC-013, SWR-SEC-014, SWR-SEC-015 | ✅ Complete | -| **SR-SEC-006** Data Encryption | SWR-SEC-016, SWR-SEC-017, SWR-SEC-018 | ✅ Complete | -| **SR-SEC-007** Secure Communication | SWR-SEC-019, SWR-SEC-020, SWR-SEC-021 | ✅ Complete | -| **SR-SEC-008** Access Control | SWR-SEC-022, SWR-SEC-023, SWR-SEC-024 | ✅ Complete | - -### 3.7 Diagnostics & Health Monitoring (DIAG) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-DIAG-001** Diagnostic Code Management | SWR-DIAG-001, SWR-DIAG-002, SWR-DIAG-003 | ✅ Complete | -| **SR-DIAG-002** Diagnostic Data Storage | SWR-DIAG-004, SWR-DIAG-005, SWR-DIAG-006 | ✅ Complete | -| **SR-DIAG-003** Diagnostic Session Support | SWR-DIAG-007, SWR-DIAG-008, SWR-DIAG-009 | ✅ Complete | -| **SR-DIAG-004** Layered Watchdog System | SWR-DIAG-010, SWR-DIAG-011, SWR-DIAG-012 | ✅ Complete | - -### 3.8 System Management (SYS) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-SYS-001** System State Machine | SWR-SYS-001, SWR-SYS-002, SWR-SYS-003 | ✅ Complete | -| **SR-SYS-002** State-Aware Operation | SWR-SYS-004, SWR-SYS-005, SWR-SYS-006 | ✅ Complete | -| **SR-SYS-003** Controlled Teardown | SWR-SYS-007, SWR-SYS-008, SWR-SYS-009 | ✅ Complete | -| **SR-SYS-004** Local Human-Machine Interface | SWR-SYS-010, SWR-SYS-011, SWR-SYS-012 | ✅ Complete | -| **SR-SYS-005** Engineering Access | SWR-SYS-013, SWR-SYS-014, SWR-SYS-015 | ✅ Complete | - -### 3.9 Power & Fault Handling (PWR) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-PWR-001** Brownout Detection | SWR-PWR-001, SWR-PWR-002, SWR-PWR-003 | ✅ Complete | -| **SR-PWR-002** Power-Loss Recovery | SWR-PWR-004, SWR-PWR-005, SWR-PWR-006 | ✅ Complete | -| **SR-PWR-003** Fault Classification | SWR-PWR-007, SWR-PWR-008, SWR-PWR-009 | ✅ Complete | -| **SR-PWR-004** Fault Escalation | SWR-PWR-010, SWR-PWR-011, SWR-PWR-012 | ✅ Complete | - -### 3.10 Hardware Abstraction (HW) - -| System Requirement | Software Requirements | Coverage | -|-------------------|----------------------|----------| -| **SR-HW-001** Sensor Abstraction Layer | SWR-HW-001, SWR-HW-002, SWR-HW-003 | ✅ Complete | -| **SR-HW-002** Hardware Interface Abstraction | SWR-HW-004, SWR-HW-005, SWR-HW-006 | ✅ Complete | -| **SR-HW-003** GPIO Discipline | SWR-HW-007, SWR-HW-008, SWR-HW-009 | ✅ Complete | - -## 4. Software Requirements to Features Mapping - -### 4.1 Feature Coverage Matrix - -| Feature | Software Requirements Covered | Total SWR | Coverage % | -|---------|------------------------------|-----------|------------| -| **F-DAQ** | SWR-DAQ-001 to SWR-DAQ-015 | 15 | 100% | -| **F-DQC** | SWR-DQC-001 to SWR-DQC-015 | 15 | 100% | -| **F-COM** | SWR-COM-001 to SWR-COM-016 | 16 | 100% | -| **F-DIAG** | SWR-DIAG-001 to SWR-DIAG-012 | 12 | 100% | -| **F-DATA** | SWR-DATA-001 to SWR-DATA-015 | 15 | 100% | -| **F-OTA** | SWR-OTA-001 to SWR-OTA-015 | 15 | 100% | -| **F-SEC** | SWR-SEC-001 to SWR-SEC-024 | 24 | 100% | -| **F-SYS** | SWR-SYS-001 to SWR-SYS-015 | 15 | 100% | -| **F-PWR** | SWR-PWR-001 to SWR-PWR-012 | 12 | 100% | -| **F-HW** | SWR-HW-001 to SWR-HW-009 | 9 | 100% | - -## 5. Features to Components Mapping - -### 5.1 Component Responsibility Matrix - -| Component | Primary Features | Supporting Features | Total Features | -|-----------|------------------|-------------------|----------------| -| **State Manager (STM)** | F-SYS-001, F-SYS-002 | F-OTA-005, F-PWR-004 | 4 | -| **Event System** | F-SYS-001 | F-DAQ-004, F-DIAG-001, F-COM-001 | 4 | -| **Sensor Manager** | F-DAQ-001 to F-DAQ-005 | F-DQC-001 to F-DQC-005 | 10 | -| **Data Pool** | F-DATA-002 | F-DAQ-004, F-DIAG-002, F-SYS-004 | 4 | -| **Persistence** | F-DATA-001, F-DATA-003, F-DATA-004, F-DATA-005 | F-DIAG-002, F-OTA-002 | 6 | -| **Network Stack** | F-COM-001, F-COM-002, F-COM-004 | F-OTA-002, F-DIAG-003 | 5 | -| **OTA Manager** | F-OTA-001 to F-OTA-005 | F-SYS-002 | 6 | -| **HMI Controller** | F-SYS-003, F-SYS-004 | F-DIAG-003 | 3 | -| **Diagnostics Task** | F-DIAG-001, F-DIAG-002, F-DIAG-003 | F-PWR-003, F-PWR-004 | 5 | -| **Error Handler** | F-PWR-003, F-PWR-004 | F-DIAG-001, F-SEC-004 | 4 | - -### 5.2 Component Interface Dependencies - -```mermaid -graph TB - subgraph "Application Layer Components" - STM[State Manager
F-SYS-001, F-SYS-002] - ES[Event System
F-SYS-001] - SM[Sensor Manager
F-DAQ-001 to F-DAQ-005
F-DQC-001 to F-DQC-005] - DP[Data Pool
F-DATA-002] - PERS[Persistence
F-DATA-001, F-DATA-003
F-DATA-004, F-DATA-005] - OTA[OTA Manager
F-OTA-001 to F-OTA-005] - HMI[HMI Controller
F-SYS-003, F-SYS-004] - DIAG[Diagnostics Task
F-DIAG-001 to F-DIAG-003] - ERR[Error Handler
F-PWR-003, F-PWR-004] - end - - subgraph "Driver Layer Components" - SD[Sensor Drivers
F-HW-001, F-HW-002] - NS[Network Stack
F-COM-001, F-COM-002, F-COM-004] - STOR[Storage Drivers
F-HW-002] - end - - STM <--> ES - SM --> ES - SM --> SD - ES --> DP - DP --> PERS - PERS --> STOR - OTA --> NS - OTA --> PERS - HMI --> DP - DIAG --> PERS - ERR --> STM - ERR --> DIAG -``` - -## 6. Verification Methods Mapping - -### 6.1 Verification Coverage by Method - -| Verification Method | Software Requirements | Percentage | -|-------------------|----------------------|------------| -| **Test (T)** | 85 | 70% | -| **Analysis (A)** | 20 | 16% | -| **Inspection (I)** | 12 | 10% | -| **Demonstration (D)** | 5 | 4% | -| **Total** | 122 | 100% | - -### 6.2 Critical Requirements Verification - -| Criticality | Requirements Count | Verification Methods | Coverage | -|-------------|-------------------|-------------------|----------| -| **Safety Critical** | 15 | Test + Analysis | 100% | -| **Security Critical** | 12 | Test + Analysis + Inspection | 100% | -| **Performance Critical** | 8 | Test + Analysis | 100% | -| **Functional** | 87 | Test + Demonstration | 100% | - -## 7. Gap Analysis - -### 7.1 Coverage Analysis Results - -| Level | Total Items | Covered Items | Coverage % | Status | -|-------|-------------|---------------|------------|--------| -| **System Requirements** | 45 | 45 | 100% | ✅ Complete | -| **Software Requirements** | 122 | 122 | 100% | ✅ Complete | -| **Features** | 45 | 45 | 100% | ✅ Complete | -| **Components** | 15 | 15 | 100% | ✅ Complete | - -### 7.2 Orphan Analysis - -#### 7.2.1 Forward Traceability (Requirements → Implementation) - -- **Orphan System Requirements:** 0 -- **Orphan Software Requirements:** 0 -- **Orphan Features:** 0 - -#### 7.2.2 Backward Traceability (Implementation → Requirements) - -- **Orphan Components:** 0 -- **Orphan Features:** 0 -- **Orphan Software Requirements:** 0 - -### 7.3 Consistency Validation - -#### 7.3.1 Interface Consistency - -| Interface Type | Defined | Implemented | Consistent | -|----------------|---------|-------------|------------| -| **Component APIs** | 15 | 15 | ✅ Yes | -| **Event Interfaces** | 12 | 12 | ✅ Yes | -| **Data Structures** | 25 | 25 | ✅ Yes | -| **State Machine** | 11 states | 11 states | ✅ Yes | - -#### 7.3.2 Dependency Validation - -- **Circular Dependencies:** 0 (validated) -- **Layer Violations:** 0 (validated) -- **Missing Dependencies:** 0 (validated) - -## 8. Quality Metrics - -### 8.1 Traceability Quality Metrics - -| Metric | Target | Actual | Status | -|--------|--------|--------|--------| -| **Requirements Coverage** | 100% | 100% | ✅ Met | -| **Bidirectional Traceability** | 100% | 100% | ✅ Met | -| **Orphan Requirements** | 0 | 0 | ✅ Met | -| **Interface Consistency** | 100% | 100% | ✅ Met | -| **Verification Coverage** | 100% | 100% | ✅ Met | - -### 8.2 Architecture Quality Metrics - -| Metric | Target | Actual | Status | -|--------|--------|--------|--------| -| **Component Cohesion** | High | High | ✅ Met | -| **Component Coupling** | Low | Low | ✅ Met | -| **Layer Violations** | 0 | 0 | ✅ Met | -| **Circular Dependencies** | 0 | 0 | ✅ Met | -| **Interface Completeness** | 100% | 100% | ✅ Met | - -## 9. Change Impact Analysis - -### 9.1 Impact Assessment Framework - -When requirements change, use this matrix to assess impact: - -| Change Type | Affected Levels | Impact Assessment | Update Required | -|-------------|----------------|-------------------|-----------------| -| **System Requirement Change** | SWR → Features → Components | High | Full traceability update | -| **Software Requirement Change** | Features → Components | Medium | Partial traceability update | -| **Feature Change** | Components only | Low | Component specifications only | -| **Component Interface Change** | Dependent components | Medium | Interface documentation update | - -### 9.2 Change Control Process - -1. **Identify Change:** Determine what level of requirement is changing -2. **Impact Analysis:** Use traceability matrix to identify affected items -3. **Update Documentation:** Update all affected specifications -4. **Validate Traceability:** Ensure traceability remains complete -5. **Review and Approve:** Stakeholder review of changes - -## 10. Validation Results - -### 10.1 Traceability Validation - -✅ **PASSED:** All system requirements traced to software requirements -✅ **PASSED:** All software requirements traced to features -✅ **PASSED:** All features traced to components -✅ **PASSED:** All components have defined interfaces -✅ **PASSED:** No orphan requirements at any level -✅ **PASSED:** No circular dependencies detected -✅ **PASSED:** All verification methods assigned - -### 10.2 Completeness Validation - -✅ **PASSED:** All 45 system requirements covered -✅ **PASSED:** All 122 software requirements covered -✅ **PASSED:** All 45 features implemented -✅ **PASSED:** All 15 components specified -✅ **PASSED:** All interfaces defined and consistent - -### 10.3 Consistency Validation - -✅ **PASSED:** Component interfaces match specifications -✅ **PASSED:** Data structures consistent across components -✅ **PASSED:** State machine consistent across components -✅ **PASSED:** Event definitions consistent across components -✅ **PASSED:** Error handling consistent across components - -## 11. Recommendations - -### 11.1 Maintenance Recommendations - -1. **Regular Traceability Reviews:** Quarterly validation of traceability completeness -2. **Change Impact Assessment:** Use this matrix for all requirement changes -3. **Tool Support:** Consider requirements management tools for large-scale changes -4. **Automated Validation:** Implement automated checks for traceability consistency - -### 11.2 Process Improvements - -1. **Early Validation:** Validate traceability during requirements development -2. **Stakeholder Reviews:** Include traceability in all design reviews -3. **Documentation Standards:** Maintain consistent traceability documentation format -4. **Training:** Ensure all team members understand traceability importance - ---- - -**Document Status:** Final - Traceability Complete -**Validation Results:** All checks passed -**Coverage:** 100% at all levels -**Next Review:** After any requirement changes - -**This traceability matrix demonstrates complete coverage and consistency across all levels of the ASF Sensor Hub system specification.** \ No newline at end of file diff --git a/draft- to be removed SW/components/ARCHITECTURE.md b/draft- to be removed SW/components/ARCHITECTURE.md deleted file mode 100644 index 7943147..0000000 --- a/draft- to be removed SW/components/ARCHITECTURE.md +++ /dev/null @@ -1,548 +0,0 @@ -# Sensor Hub Static Architecture - -**Document Type:** Architecture Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Traceability:** SRS Section 3.2, Annex B - -## 1. Purpose and Scope - -This document defines the static architecture of the Sensor Hub firmware, including component structure, interfaces, data flows, and concurrency model. This architecture enforces separation of concerns, hardware abstraction, and state-aware operation as defined in the SRS and cross-feature constraints. - -**Audience:** Software architects, developers, reviewers, and test engineers. - -## 2. Architectural Principles - -### 2.1 Layered Architecture - -The Sensor Hub follows a **strict layered architecture** with the following principles: - -1. **Dependency Direction:** Dependencies flow downward only (Application → Drivers → OSAL → HAL) -2. **Hardware Abstraction:** Application layer SHALL NOT access hardware directly (CFC-ARCH-01) -3. **Persistence Abstraction:** All persistence access SHALL go through DP component (CFC-ARCH-01, CFC-DATA-01) -4. **State Awareness:** All features SHALL respect system state restrictions (CFC-ARCH-02) - -### 2.2 Component Responsibilities - -- **Single Responsibility:** Each component has one well-defined purpose -- **Clear Interfaces:** Public APIs are minimal and well-documented -- **Event-Driven Communication:** Cross-component communication via Event System -- **State-Dependent Behavior:** Components adapt behavior based on system state - -## 3. Architecture Views - -### 3.1 Context View - -The Context View shows the Sensor Hub and its external actors. - -```mermaid -graph TB - subgraph External["External Actors"] - MainHub[Main Hub] - PeerHub[Peer Sensor Hub] - Sensors[Environmental Sensors] - SDCard[SD Card] - OLED[OLED Display] - Buttons[Buttons] - end - - subgraph SensorHub["Sensor Hub System"] - AppLayer[Application Layer] - Drivers[Drivers Layer] - OSAL[OSAL Layer] - HAL[HAL/ESP-IDF] - end - - MainHub <-->|"Encrypted Communication"| AppLayer - PeerHub <-->|"Peer Communication"| AppLayer - Sensors -->|"I2C/SPI/UART/Analog"| Drivers - SDCard <-->|"SPI/SD Protocol"| Drivers - OLED <-->|"I2C"| Drivers - Buttons -->|"GPIO"| Drivers - - AppLayer --> Drivers - Drivers --> OSAL - OSAL --> HAL -``` - -**External Interfaces:** -- **Main Hub:** Bidirectional encrypted communication (Wi-Fi/Zigbee/LoRa) -- **Peer Sensor Hub:** Limited peer-to-peer communication -- **Sensors:** I2C, SPI, UART, Analog interfaces -- **SD Card:** SPI/SD protocol for persistent storage -- **OLED Display:** I2C for local HMI -- **Buttons:** GPIO inputs for user interaction - -### 3.2 Component View - -The Component View shows the major software components and their relationships. - -```mermaid -graph TB - subgraph AppLayer["Application Layer"] - subgraph BusinessStack["Business Stack"] - STM[State Manager
STM] - EventSys[Event System] - SensorMgr[Sensor Manager] - MCMgr[Machine Constant
Manager] - OTAMgr[OTA Manager] - MainHubAPI[Main Hub APIs] - end - - subgraph DPStack["DP Stack"] - DataPool[Data Pool] - Persistence[Persistence] - end - - DiagTask[Diagnostics Task] - ErrorHandler[Error Handler] - end - - subgraph Drivers["Drivers Layer"] - SensorDrivers[Sensor Drivers
I2C/SPI/UART/ADC] - NetworkStack[Network Stack
Wi-Fi/Zigbee/LoRa] - DiagProtocol[Diagnostic Protocol
Stack] - SDDriver[SD Card Driver] - NVMDriver[NVM Driver] - OLEDDriver[OLED Driver] - ButtonDriver[Button Driver] - end - - subgraph OSAL["OSAL Layer"] - TaskOS[Task Abstraction] - TimerOS[Software Timer] - SocketOS[Socket Abstraction] - end - - subgraph Utils["Utilities"] - Logger[Logger] - TimeUtils[Time Utils] - end - - STM --> EventSys - SensorMgr --> EventSys - SensorMgr --> SensorDrivers - MCMgr --> Persistence - OTAMgr --> NetworkStack - OTAMgr --> Persistence - MainHubAPI --> NetworkStack - MainHubAPI --> DataPool - EventSys --> DataPool - DataPool --> Persistence - Persistence --> SDDriver - Persistence --> NVMDriver - DiagTask --> Persistence - DiagTask --> EventSys - ErrorHandler --> STM - ErrorHandler --> DiagTask - - SensorMgr --> Logger - OTAMgr --> Logger - MainHubAPI --> Logger - DiagTask --> Logger - - SensorMgr --> TimeUtils - - SensorDrivers --> TaskOS - NetworkStack --> SocketOS - NetworkStack --> TaskOS - Persistence --> TaskOS - - SensorDrivers --> OSAL - NetworkStack --> OSAL - SDDriver --> OSAL - OLEDDriver --> OSAL - ButtonDriver --> OSAL -``` - -**Component Responsibilities:** - -| Component | Responsibility | Non-Responsibility | -|-----------|----------------|-------------------| -| **State Manager (STM)** | System state machine, state transitions, teardown coordination | Feature logic, hardware access | -| **Event System** | Publish/subscribe event bus, cross-component communication | Business logic, state management | -| **Sensor Manager** | Sensor lifecycle, acquisition scheduling, data filtering | Hardware access, persistence, communication | -| **Machine Constant Manager** | MC loading, validation, update coordination | Sensor initialization, hardware access | -| **OTA Manager** | OTA negotiation, firmware reception, validation, activation | Network stack implementation, secure boot | -| **Main Hub APIs** | Main Hub communication protocol, message handling | Network stack implementation, sensor data generation | -| **Data Pool** | Runtime data storage, latest sensor values, system state | Persistence, communication | -| **Persistence** | Persistent storage abstraction, serialization, wear management | Business logic, hardware access | -| **Diagnostics Task** | Diagnostic event collection, storage, query interface | Fault detection, state management | -| **Error Handler** | Fault classification, escalation, state transition triggers | Diagnostic storage, feature logic | - -### 3.3 Data Flow View - -The Data Flow View shows how data flows through the system. - -#### 3.3.1 Sensor Data Acquisition Flow - -```mermaid -sequenceDiagram - participant Sensor as Sensor Hardware - participant Driver as Sensor Driver - participant SMgr as Sensor Manager - participant EventSys as Event System - participant DP as Data Pool - participant Persist as Persistence - participant MainHub as Main Hub APIs - - Note over Sensor,MainHub: Normal Acquisition Cycle - - SMgr->>Driver: readSensor(sensor_id) - Driver->>Sensor: I2C/SPI/UART read - Sensor-->>Driver: raw_sample - Driver-->>SMgr: raw_sample - - loop 10 samples - SMgr->>Driver: readSensor(sensor_id) - Driver-->>SMgr: raw_sample - end - - SMgr->>SMgr: filter(raw_samples) - SMgr->>SMgr: generateTimestamp() - SMgr->>EventSys: publish(SENSOR_DATA_UPDATE, record) - EventSys->>DP: update(sensor_id, record) - EventSys->>Persist: async_persist(record) - EventSys->>MainHub: notify(SENSOR_DATA_UPDATE) - - MainHub->>MainHub: queueForTransmission(record) -``` - -#### 3.3.2 Diagnostic Event Flow - -```mermaid -sequenceDiagram - participant Component as Any Component - participant ErrorHandler as Error Handler - participant DiagTask as Diagnostics Task - participant EventSys as Event System - participant STM as State Manager - participant Persist as Persistence - - Component->>ErrorHandler: reportFault(diagnostic_code, severity) - ErrorHandler->>ErrorHandler: classifyFault() - ErrorHandler->>ErrorHandler: checkEscalation() - - alt Severity == FATAL - ErrorHandler->>STM: triggerStateTransition(FAULT) - STM->>EventSys: publish(STATE_CHANGED, FAULT) - else Severity == WARNING - ErrorHandler->>STM: triggerStateTransition(WARNING) - end - - ErrorHandler->>DiagTask: logDiagnostic(event) - DiagTask->>Persist: persistDiagnostic(event) - DiagTask->>EventSys: publish(DIAGNOSTIC_EVENT, event) -``` - -#### 3.3.3 OTA Update Flow - -```mermaid -sequenceDiagram - participant MainHub as Main Hub - participant MainHubAPI as Main Hub APIs - participant OTAMgr as OTA Manager - participant STM as State Manager - participant Persist as Persistence - participant NetworkStack as Network Stack - participant Security as Security - - MainHub->>MainHubAPI: OTA_REQUEST(message) - MainHubAPI->>OTAMgr: otaRequestReceived() - OTAMgr->>OTAMgr: validateReadiness() - OTAMgr->>STM: requestStateTransition(OTA_PREP) - STM->>STM: validateTransition() - STM->>EventSys: publish(STATE_CHANGED, OTA_PREP) - - OTAMgr->>MainHubAPI: otaAcknowledge(ACCEPT) - MainHubAPI->>MainHub: OTA_ACK(ACCEPT) - - OTAMgr->>STM: requestStateTransition(TEARDOWN) - STM->>Persist: flushCriticalData() - Persist-->>STM: flushComplete() - STM->>EventSys: publish(STATE_CHANGED, TEARDOWN) - STM->>STM: transitionTo(OTA_UPDATE) - - loop Firmware Chunks - MainHub->>NetworkStack: firmwareChunk(data) - NetworkStack->>OTAMgr: firmwareChunkReceived(data) - OTAMgr->>Persist: storeFirmwareChunk(data) - end - - OTAMgr->>Security: validateFirmwareIntegrity() - Security-->>OTAMgr: validationResult - - alt Validation Success - OTAMgr->>OTAMgr: flashFirmware() - OTAMgr->>STM: reboot() - else Validation Failure - OTAMgr->>STM: requestStateTransition(FAULT) - OTAMgr->>MainHubAPI: otaStatus(FAILED) - end -``` - -### 3.4 Concurrency View - -The Concurrency View shows the task model, priorities, and resource ownership. - -```mermaid -graph TB - subgraph Tasks["RTOS Tasks"] - SensorTask["Sensor Acquisition Task
Priority: HIGH
Stack: 8KB
Period: 1s"] - CommTask["Communication Task
Priority: MEDIUM
Stack: 12KB
Event-driven"] - PersistTask["Persistence Task
Priority: MEDIUM
Stack: 6KB
Event-driven"] - DiagTask["Diagnostics Task
Priority: LOW
Stack: 4KB
Period: 10s"] - HMITask["HMI Task
Priority: LOW
Stack: 4KB
Event-driven"] - OTATask["OTA Task
Priority: HIGH
Stack: 16KB
Event-driven"] - SystemTask["System Management Task
Priority: HIGH
Stack: 6KB
Event-driven"] - end - - subgraph Components["Components"] - SensorMgr[Sensor Manager] - MainHubAPI[Main Hub APIs] - Persistence[Persistence] - DiagTaskComp[Diagnostics Task] - HMI[HMI] - OTAMgr[OTA Manager] - STM[State Manager] - end - - SensorTask --> SensorMgr - CommTask --> MainHubAPI - PersistTask --> Persistence - DiagTask --> DiagTaskComp - HMITask --> HMI - OTATask --> OTAMgr - SystemTask --> STM -``` - -**Task Priorities and Responsibilities:** - -| Task | Priority | Stack Size | Responsibility | Blocking Operations | -|------|----------|------------|---------------|---------------------| -| **Sensor Acquisition** | HIGH | 8KB | Sensor sampling, filtering | Sensor I/O (bounded) | -| **Communication** | MEDIUM | 12KB | Main Hub communication | Network I/O (bounded) | -| **Persistence** | MEDIUM | 6KB | Data persistence | Storage I/O (bounded) | -| **Diagnostics** | LOW | 4KB | Diagnostic collection | None (non-blocking) | -| **HMI** | LOW | 4KB | Display updates, button handling | Display I/O (bounded) | -| **OTA** | HIGH | 16KB | Firmware update operations | Network I/O, flash I/O | -| **System Management** | HIGH | 6KB | State machine, teardown | None (coordination only) | - -**Resource Ownership:** - -| Resource | Owner | Access Method | Concurrency Control | -|----------|-------|--------------|---------------------| -| **Sensor Drivers** | Sensor Acquisition Task | Direct (exclusive) | Task-level ownership | -| **Network Stack** | Communication Task | Direct (exclusive) | Task-level ownership | -| **SD Card** | Persistence Task | Direct (exclusive) | Mutex (if shared) | -| **NVM** | Persistence Task | Direct (exclusive) | Mutex (if shared) | -| **Data Pool** | All Tasks | Event System | Lock-free (atomic operations) | -| **Event System** | All Tasks | Publish/Subscribe | Lock-free queue | -| **State Machine** | System Management Task | Direct (exclusive) | Task-level ownership | - -## 4. Component Specifications - -### 4.1 State Manager (STM) - -**Location:** `application_layer/business_stack/STM/` - -**Responsibilities:** -- Implement system FSM as defined in System State Machine Specification -- Enforce valid state transitions -- Coordinate teardown sequences -- Notify components of state changes - -**Public API:** -```c -// State query -system_state_t stm_getCurrentState(void); -bool stm_isStateValid(system_state_t state); - -// State transition -bool stm_requestTransition(system_state_t target_state, transition_reason_t reason); -bool stm_validateTransition(system_state_t from, system_state_t to); - -// Teardown coordination -bool stm_initiateTeardown(teardown_reason_t reason); -bool stm_isTeardownComplete(void); - -// Component registration -bool stm_registerStateListener(state_listener_t listener); -``` - -**State Dependencies:** -- SHALL be initialized first (during INIT state) -- SHALL coordinate with Error Handler for fault-triggered transitions -- SHALL coordinate with OTA Manager for OTA-triggered transitions - -### 4.2 Event System - -**Location:** `application_layer/business_stack/event_system/` - -**Responsibilities:** -- Provide publish/subscribe event bus -- Decouple components via events -- Ensure non-blocking event delivery - -**Public API:** -```c -// Event types -typedef enum { - EVENT_SENSOR_DATA_UPDATE, - EVENT_DIAGNOSTIC_EVENT, - EVENT_STATE_CHANGED, - EVENT_OTA_REQUEST, - // ... other event types -} event_type_t; - -// Publish event -bool event_publish(event_type_t type, void* payload, size_t payload_size); - -// Subscribe to events -bool event_subscribe(event_type_t type, event_handler_t handler); -bool event_unsubscribe(event_type_t type, event_handler_t handler); -``` - -**Constraints:** -- SHALL be non-blocking (lock-free queue) -- SHALL support multiple subscribers per event type -- SHALL NOT perform blocking operations in event handlers - -### 4.3 Sensor Manager - -**Location:** `application_layer/business_stack/sensor_manager/` - -**Responsibilities:** -- Sensor lifecycle management (detection, initialization, sampling) -- High-frequency sampling and filtering -- Timestamp generation -- Sensor failure detection - -**Public API:** -```c -// Sensor lifecycle -bool sensorMgr_initialize(void); -bool sensorMgr_detectSensors(void); -bool sensorMgr_startAcquisition(void); -bool sensorMgr_stopAcquisition(void); - -// Sensor data access -bool sensorMgr_getLatestData(uint8_t sensor_id, sensor_data_record_t* record); -bool sensorMgr_getAllSensorData(sensor_data_record_t* records, size_t* count); - -// Sensor status -bool sensorMgr_isSensorPresent(uint8_t sensor_id); -bool sensorMgr_isSensorEnabled(uint8_t sensor_id); -``` - -**State Dependencies:** -- SHALL NOT perform acquisition during OTA_UPDATE, MC_UPDATE, TEARDOWN states -- SHALL pause acquisition during SERVICE state (optional) -- SHALL continue acquisition during SD_DEGRADED state (without persistence) - -### 4.4 Data Persistence (DP Component) - -**Location:** `application_layer/DP_stack/persistence/` - -**Responsibilities:** -- Abstract storage media (SD card, NVM) -- Serialize/deserialize structured data -- Manage wear-aware storage -- Ensure data integrity - -**Public API:** -```c -// Data persistence -bool persistence_writeSensorData(const sensor_data_record_t* record); -bool persistence_writeDiagnostic(const diagnostic_event_t* event); -bool persistence_writeMachineConstants(const machine_constants_t* mc); - -// Data retrieval -bool persistence_readSensorData(sensor_data_record_t* records, size_t* count); -bool persistence_readDiagnostics(diagnostic_event_t* events, size_t* count); -bool persistence_readMachineConstants(machine_constants_t* mc); - -// Flush operations -bool persistence_flushCriticalData(void); -bool persistence_isFlushComplete(void); -``` - -**Constraints:** -- SHALL be the sole interface for persistent storage access (CFC-ARCH-01) -- SHALL NOT allow direct hardware access from application layer -- SHALL verify persistence completion before state transitions (CFC-DATA-02) - -### 4.5 OTA Manager - -**Location:** `application_layer/business_stack/fw_upgrader/` - -**Responsibilities:** -- OTA negotiation with Main Hub -- Firmware reception and storage -- Firmware integrity validation -- Controlled firmware activation - -**Public API:** -```c -// OTA operations -bool ota_handleRequest(const ota_request_t* request); -bool ota_receiveFirmwareChunk(const uint8_t* chunk, size_t chunk_size); -bool ota_validateFirmware(void); -bool ota_activateFirmware(void); - -// OTA status -ota_status_t ota_getStatus(void); -bool ota_isReady(void); -``` - -**State Dependencies:** -- SHALL NOT operate during WARNING, FAULT, SERVICE, SD_DEGRADED states -- SHALL coordinate with STM for state transitions -- SHALL coordinate with Persistence for data flush before activation - -## 5. Architectural Constraints Mapping - -| Constraint | Architectural Mechanism | Enforcement | -|------------|-------------------------|-------------| -| **CFC-ARCH-01** (Hardware Abstraction) | Driver layer abstraction, OSAL layer | Compile-time (no direct HAL includes in application) | -| **CFC-ARCH-02** (State-Aware Execution) | STM state queries, per-state execution rules | Runtime (state checks in components) | -| **CFC-TIME-01** (Non-Blocking) | Event System, async operations | Design-time (no blocking calls in critical paths) | -| **CFC-TIME-02** (Deterministic) | Static memory allocation, bounded operations | Design-time (no dynamic allocation in acquisition) | -| **CFC-DATA-01** (Single Source of Truth) | DP component as sole persistence interface | Compile-time (no direct storage access) | -| **CFC-DATA-02** (Data Consistency) | Persistence flush before state transitions | Runtime (STM coordination) | -| **CFC-SEC-01** (Security First) | Secure boot before application start | Boot-time (hardware-enforced) | -| **CFC-SEC-02** (Encrypted Channels) | TLS/DTLS in Network Stack | Runtime (mandatory encryption) | -| **CFC-DBG-01** (Debug Isolation) | Debug session authentication, state restrictions | Runtime (authentication checks) | - -## 6. Repository Structure Mapping - -| Architecture Layer | Repository Path | Components | -|-------------------|-----------------|------------| -| **Application Layer** | `application_layer/business_stack/` | STM, Event System, Sensor Manager, MC Manager, OTA Manager, Main Hub APIs | -| **DP Stack** | `application_layer/DP_stack/` | Data Pool, Persistence | -| **Diagnostics** | `application_layer/diag_task/`, `application_layer/error_handler/` | Diagnostics Task, Error Handler | -| **Drivers** | `drivers/` | Network Stack, Diagnostic Protocol, SD Card, NVM, Sensors | -| **ESP-IDF Wrappers** | `ESP_IDF_FW_wrappers/` | GPIO, I2C, SPI, UART, ADC, DMA, Wi-Fi | -| **OSAL** | `os/` | Task, Software Timer | -| **Utilities** | `utils/` | Logger, Time Utils | - -## 7. Traceability - -- **SRS Section 3.2:** Interface Requirements -- **SRS Section 3.4:** Design Constraints -- **Cross-Feature Constraints:** All architectural constraints mapped -- **System State Machine Specification:** State-aware component behavior - -## 8. Diagrams Summary - -- **Context View:** External interfaces and actors -- **Component View:** Major components and relationships -- **Data Flow View:** Sensor data, diagnostic, and OTA flows -- **Concurrency View:** Task model, priorities, resource ownership - ---- - -**Next Steps:** -- Component-level specifications (detailed APIs per component) -- Sequence diagrams for additional flows (MC update, diagnostic session) -- Interface Control Documents (ICD) for external interfaces diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/README.md deleted file mode 100644 index 64653fe..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/README.md +++ /dev/null @@ -1,346 +0,0 @@ -# ESP-IDF Firmware Wrappers - -## Overview - -This directory contains C++ object-oriented wrappers for ESP-IDF peripheral drivers. Each wrapper provides a clean, easy-to-use interface that encapsulates the ESP-IDF C APIs while maintaining full functionality and performance. - -## Architecture - -The wrapper architecture follows these principles: - -- **Object-Oriented Design**: Each peripheral is wrapped in a C++ class -- **RAII Pattern**: Resources are automatically managed through constructors/destructors -- **Error Handling**: Comprehensive error checking with ESP-IDF error code logging -- **Type Safety**: Strong typing with enumerations instead of magic numbers -- **Documentation**: Full Doxygen documentation for all public APIs -- **Naming Convention**: Follows project coding guidelines (snake_case files, PascalCase classes) - -## Implemented Modules - -### ✅ GPIO Wrapper (`gpio/`) -- **Status**: Complete -- **Features**: Pin configuration, digital I/O, interrupt handling, pin validation -- **Key Classes**: `Gpio` -- **Dependencies**: `driver/gpio.h`, `esp_err.h`, `esp_log.h` - -### ✅ UART Wrapper (`uart/`) -- **Status**: Complete -- **Features**: Multi-port support, configurable parameters, timeout support, flow control -- **Key Classes**: `Uart` -- **Dependencies**: `driver/uart.h`, `esp_err.h`, `esp_log.h`, `freertos/FreeRTOS.h` - -### ✅ I2C Wrapper (`i2c/`) -- **Status**: Complete -- **Features**: Master/slave modes, register operations, bus scanning, timeout support -- **Key Classes**: `I2c` -- **Dependencies**: `driver/i2c.h`, `esp_err.h`, `esp_log.h`, `freertos/FreeRTOS.h` - -### ✅ SPI Wrapper (`spi/`) -- **Status**: Complete -- **Features**: Multi-host support, device management, DMA support, command/address phases -- **Key Classes**: `Spi` -- **Dependencies**: `driver/spi_master.h`, `esp_err.h`, `esp_log.h` - -### ✅ ADC Wrapper (`adc/`) -- **Status**: Complete -- **Features**: Multi-unit/channel support, automatic calibration, averaging, multiple resolutions -- **Key Classes**: `Adc` -- **Dependencies**: `esp_adc/adc_oneshot.h`, `esp_adc/adc_cali.h`, `esp_err.h`, `esp_log.h` - -### ✅ WiFi Wrapper (`wifi/`) -- **Status**: Complete -- **Features**: STA/AP/APSTA modes, network scanning, event handling, security support -- **Key Classes**: `Wifi` -- **Dependencies**: `esp_wifi.h`, `esp_netif.h`, `esp_event.h`, `nvs_flash.h` - -### ✅ DMA Wrapper (`dma/`) -- **Status**: Complete -- **Features**: GDMA channel management, memory transfers, descriptor management, DMA-capable memory allocation -- **Key Classes**: `Dma` -- **Dependencies**: `driver/gdma.h`, `esp_dma_utils.h`, `esp_hw_support`, `esp_heap_caps.h` - -### ✅ Bluetooth Wrapper (`bt/`) -- **Status**: Complete -- **Features**: BLE/Classic/Dual modes, GATT server/client, advertising, scanning, pairing -- **Key Classes**: `Bluetooth` -- **Dependencies**: `esp_bt.h`, `esp_gap_ble_api.h`, `esp_gatts_api.h`, `esp_gattc_api.h`, `nvs_flash.h` - -## Directory Structure - -``` -ESP_IDF_FW_wrappers/ -├── README.md # This overview document -├── gpio/ -│ ├── com/ -│ │ ├── gpio.hpp # GPIO wrapper header -│ │ └── gpio.cpp # GPIO wrapper implementation -│ ├── test/ # Unit tests (empty) -│ ├── CMakeLists.txt # Build configuration -│ └── README.md # GPIO module documentation -├── uart/ -│ ├── com/ -│ │ ├── uart.hpp # UART wrapper header -│ │ └── uart.cpp # UART wrapper implementation -│ ├── test/ # Unit tests (empty) -│ ├── CMakeLists.txt # Build configuration -│ └── README.md # UART module documentation -├── i2c/ -│ ├── com/ -│ │ ├── i2c.hpp # I2C wrapper header -│ │ └── i2c.cpp # I2C wrapper implementation -│ ├── test/ # Unit tests (empty) -│ ├── CMakeLists.txt # Build configuration -│ └── README.md # I2C module documentation -├── spi/ -│ ├── com/ -│ │ ├── spi.hpp # SPI wrapper header -│ │ └── spi.cpp # SPI wrapper implementation -│ ├── test/ # Unit tests (empty) -│ ├── CMakeLists.txt # Build configuration -│ └── README.md # SPI module documentation -├── adc/ -│ ├── com/ -│ │ ├── adc.hpp # ADC wrapper header -│ │ └── adc.cpp # ADC wrapper implementation -│ ├── test/ # Unit tests (empty) -│ ├── CMakeLists.txt # Build configuration -│ └── README.md # ADC module documentation -├── wifi/ -│ ├── com/ -│ │ ├── wifi.hpp # WiFi wrapper header -│ │ └── wifi.cpp # WiFi wrapper implementation -│ ├── test/ # Unit tests (empty) -│ ├── CMakeLists.txt # Build configuration -│ └── README.md # WiFi module documentation -├── bt/ # Bluetooth wrapper (✅ Complete) -│ ├── com/ -│ │ ├── bt.hpp # Bluetooth wrapper header -│ │ └── bt.cpp # Bluetooth wrapper implementation -│ ├── test/ # Unit tests (empty) -│ ├── CMakeLists.txt # Build configuration -│ └── README.md # Bluetooth module documentation -└── dma/ # DMA wrapper (✅ Complete) - ├── com/ - │ ├── dma.hpp # DMA wrapper header - │ └── dma.cpp # DMA wrapper implementation - ├── test/ # Unit tests (empty) - ├── CMakeLists.txt # Build configuration - └── README.md # DMA module documentation -``` - -## Usage Examples - -### Basic GPIO Usage -```cpp -#include "gpio.hpp" - -Gpio gpio; -gpio.configure(2, GpioMode::OUTPUT); -gpio.setLevel(2, 1); // Set pin high -``` - -### UART Communication -```cpp -#include "uart.hpp" - -Uart uart; -UartConfig config = Uart::getDefaultConfig(); -config.baudrate = UartBaudrate::BAUD_115200; -config.txPin = 1; -config.rxPin = 3; - -uart.initialize(UartPort::PORT_0, config); -uart.transmit(UartPort::PORT_0, (uint8_t*)"Hello", 5); -``` - -### I2C Device Communication -```cpp -#include "i2c.hpp" - -I2c i2c; -I2cConfig config = I2c::getDefaultConfig(); -i2c.initialize(I2cPort::PORT_0, config); - -uint8_t data[] = {0x01, 0x02}; -i2c.write(I2cPort::PORT_0, 0x48, data, sizeof(data)); -``` - -### SPI Device Communication -```cpp -#include "spi.hpp" - -Spi spi; -SpiBusConfig busConfig = Spi::getDefaultBusConfig(); -spi.initializeBus(SpiHost::SPI2_HOST, busConfig); - -SpiDeviceConfig deviceConfig = Spi::getDefaultDeviceConfig(); -spi_device_handle_t device; -spi.addDevice(SpiHost::SPI2_HOST, deviceConfig, &device); - -uint8_t txData[] = {0xAA, 0x55}; -uint8_t rxData[2]; -spi.transmit(device, txData, rxData, 2); -``` - -### ADC Reading -```cpp -#include "adc.hpp" - -Adc adc; -adc.initializeUnit(AdcUnit::UNIT_1, AdcBitwidth::WIDTH_12BIT); - -AdcChannelConfig config = Adc::getDefaultChannelConfig(); -adc.configureChannel(config); - -int32_t voltage = adc.readVoltage(AdcUnit::UNIT_1, AdcChannel::CHANNEL_0); -``` - -### WiFi Connection -```cpp -#include "wifi.hpp" - -Wifi wifi; -WifiConfig config = {}; -config.mode = WifiMode::STA; -config.staConfig = Wifi::getDefaultStaConfig(); -strcpy(config.staConfig.ssid, "MyNetwork"); -strcpy(config.staConfig.password, "MyPassword"); - -wifi.initialize(config); -wifi.start(); -wifi.connect(); -``` - -## Build Integration - -Each wrapper is a separate ESP-IDF component with its own `CMakeLists.txt`. To use a wrapper in your application: - -1. Add the wrapper component to your project's `CMakeLists.txt`: -```cmake -set(EXTRA_COMPONENT_DIRS "components/ESP_IDF_FW_wrappers/gpio") -``` - -2. Include the wrapper in your component's dependencies: -```cmake -idf_component_register( - SRCS "main.cpp" - INCLUDE_DIRS "." - REQUIRES gpio_wrapper -) -``` - -3. Include the header in your code: -```cpp -#include "gpio.hpp" -``` - -## Design Patterns - -### RAII (Resource Acquisition Is Initialization) -All wrappers follow RAII principles: -- Resources are acquired in constructors -- Resources are released in destructors -- Exception safety through automatic cleanup - -### Error Handling -Consistent error handling across all wrappers: -- Boolean return values for success/failure -- Negative return values for error conditions -- ESP-IDF error codes logged with descriptive messages -- Input parameter validation - -### Configuration Structures -Each wrapper provides configuration structures: -- Default configuration functions -- Type-safe enumerations -- Clear parameter documentation - -## Testing - -Each wrapper includes a `test/` directory for unit tests (currently empty). Future development should include: -- Unit tests for all public APIs -- Integration tests with real hardware -- Performance benchmarks -- Memory usage tests - -## Future Development - -### All Core Modules Implemented - -All 8 core ESP-IDF peripheral wrapper modules have been successfully implemented: -- GPIO, UART, I2C, SPI, ADC, WiFi, DMA, and Bluetooth wrappers are complete -- Each module includes full functionality, documentation, and usage examples - -### Enhancements for Existing Modules - -1. **GPIO** - - Matrix keyboard support - - PWM integration - - Capacitive touch support - -2. **UART** - - RS485 support - - Pattern detection - - DMA integration - -3. **I2C** - - Multi-master support - - Clock stretching - - 10-bit addressing - -4. **SPI** - - Slave mode support - - Quad SPI support - - LCD interface support - -5. **ADC** - - Continuous mode - - DMA integration - - Multi-channel simultaneous sampling - -6. **WiFi** - - WPS support - - Mesh networking - - Enterprise security - -## Contributing - -When contributing to the wrapper modules: - -1. Follow the established coding guidelines in `6 Guidelines.md` -2. Maintain consistent API design across modules -3. Include comprehensive documentation -4. Add unit tests for new functionality -5. Update the module's README.md file -6. Ensure thread safety where applicable - -## Performance Considerations - -- All wrappers provide minimal overhead over direct ESP-IDF calls -- RAII pattern ensures efficient resource management -- Inline functions used where appropriate -- No dynamic memory allocation in critical paths -- Direct ESP-IDF function calls for optimal performance - -## Memory Usage - -- Fixed memory footprint per wrapper instance -- No hidden dynamic allocations -- Resource handles managed efficiently -- Stack-based configuration structures - -## Thread Safety - -- GPIO: Not thread-safe, requires external synchronization -- UART: Thread-safe (ESP-IDF driver is thread-safe) -- I2C: Thread-safe for different ports, synchronize access to same port -- SPI: Thread-safe (ESP-IDF driver is thread-safe) -- ADC: Thread-safe (ESP-IDF driver is thread-safe) -- WiFi: Thread-safe (ESP-IDF driver is thread-safe) - -## Compatibility - -- **ESP-IDF Version**: v5.x -- **ESP32 Variants**: ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 -- **Compiler**: GCC with C++11 or later -- **Build System**: CMake-based ESP-IDF build system \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/CMakeLists.txt deleted file mode 100644 index 49e9585..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/adc.cpp" - INCLUDE_DIRS "com" - REQUIRES driver esp_adc logger -) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/README.md deleted file mode 100644 index 2bed53f..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/README.md +++ /dev/null @@ -1,276 +0,0 @@ -# ADC Wrapper Module - -## Overview - -The ADC wrapper module provides a C++ object-oriented interface for ESP-IDF ADC functionality. This module encapsulates the ESP-IDF ADC oneshot driver functions and provides a clean, easy-to-use API for analog-to-digital conversion with automatic calibration support. - -## Features - -- **Multi-Unit Support**: Support for ADC1 and ADC2 units -- **Multi-Channel Support**: Support for up to 10 channels per unit -- **Automatic Calibration**: Built-in calibration for accurate voltage readings -- **Multiple Resolutions**: Support for 9-13 bit ADC resolution -- **Attenuation Control**: Configurable input voltage ranges -- **Averaging**: Built-in sample averaging for noise reduction -- **Error Handling**: Comprehensive error checking and logging - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ Adc │ -├─────────────────────────────────────┤ -│ - m_adcHandle_[2]: handle_t │ -│ - m_caliHandle_[2][10]: handle_t │ -│ - m_unitInitialized_[2]: bool │ -│ - m_channelConfigured_[2][10]: bool │ -│ - m_unitBitwidth_[2]: AdcBitwidth │ -├─────────────────────────────────────┤ -│ + Adc() │ -│ + ~Adc() │ -│ + initializeUnit(unit, width): bool │ -│ + deinitializeUnit(unit): bool │ -│ + configureChannel(config): bool │ -│ + readVoltage(unit, ch): int32_t │ -│ + readRaw(unit, ch): int32_t │ -│ + readVoltageAverage(...): int32_t │ -│ + readRawAverage(...): int32_t │ -│ + isUnitInitialized(unit): bool │ -│ + isChannelConfigured(...): bool │ -│ + getMaxRawValue(width): uint32_t │ -│ + getDefaultChannelConfig(): Config │ -│ - convertUnit(unit): adc_unit_t │ -│ - convertChannel(ch): adc_channel_t │ -│ - convertAttenuation(...): adc_att │ -│ - convertBitwidth(...): adc_bit_t │ -│ - initializeCalibration(...): bool │ -│ - deinitializeCalibration(...): bool│ -│ - getUnitIndex(unit): uint8_t │ -│ - getChannelIndex(ch): uint8_t │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### AdcUnit -- `UNIT_1`: ADC unit 1 -- `UNIT_2`: ADC unit 2 - -#### AdcChannel -- `CHANNEL_0` to `CHANNEL_9`: ADC channels 0-9 - -#### AdcAttenuation -- `ATTEN_0dB`: 0dB attenuation (0-950mV range) -- `ATTEN_2_5dB`: 2.5dB attenuation (0-1250mV range) -- `ATTEN_6dB`: 6dB attenuation (0-1750mV range) -- `ATTEN_11dB`: 11dB attenuation (0-3100mV range) - -#### AdcBitwidth -- `WIDTH_9BIT`: 9-bit resolution (0-511) -- `WIDTH_10BIT`: 10-bit resolution (0-1023) -- `WIDTH_11BIT`: 11-bit resolution (0-2047) -- `WIDTH_12BIT`: 12-bit resolution (0-4095) -- `WIDTH_13BIT`: 13-bit resolution (0-8191) - -### Configuration Structure - -```cpp -struct AdcChannelConfig { - AdcUnit unit; // ADC unit - AdcChannel channel; // ADC channel - AdcAttenuation atten; // Attenuation level - AdcBitwidth bitwidth; // ADC resolution -}; -``` - -## Usage Examples - -### Basic ADC Reading - -```cpp -#include "adc.hpp" - -// Create ADC instance -Adc adc; - -// Initialize ADC unit 1 with 12-bit resolution -adc.initializeUnit(AdcUnit::UNIT_1, AdcBitwidth::WIDTH_12BIT); - -// Configure channel 0 -AdcChannelConfig config = Adc::getDefaultChannelConfig(); -config.unit = AdcUnit::UNIT_1; -config.channel = AdcChannel::CHANNEL_0; -config.atten = AdcAttenuation::ATTEN_11dB; // 0-3.1V range -config.bitwidth = AdcBitwidth::WIDTH_12BIT; - -adc.configureChannel(config); - -// Read voltage in millivolts -int32_t voltage = adc.readVoltage(AdcUnit::UNIT_1, AdcChannel::CHANNEL_0); -printf("Voltage: %ld mV\n", voltage); - -// Read raw ADC value -int32_t raw = adc.readRaw(AdcUnit::UNIT_1, AdcChannel::CHANNEL_0); -printf("Raw value: %ld\n", raw); -``` - -### Multiple Channels - -```cpp -// Configure multiple channels -AdcChannelConfig configs[] = { - {AdcUnit::UNIT_1, AdcChannel::CHANNEL_0, AdcAttenuation::ATTEN_11dB, AdcBitwidth::WIDTH_12BIT}, - {AdcUnit::UNIT_1, AdcChannel::CHANNEL_1, AdcAttenuation::ATTEN_6dB, AdcBitwidth::WIDTH_12BIT}, - {AdcUnit::UNIT_2, AdcChannel::CHANNEL_0, AdcAttenuation::ATTEN_11dB, AdcBitwidth::WIDTH_12BIT} -}; - -// Initialize units -adc.initializeUnit(AdcUnit::UNIT_1, AdcBitwidth::WIDTH_12BIT); -adc.initializeUnit(AdcUnit::UNIT_2, AdcBitwidth::WIDTH_12BIT); - -// Configure all channels -for (const auto& config : configs) { - adc.configureChannel(config); -} - -// Read from all channels -for (const auto& config : configs) { - int32_t voltage = adc.readVoltage(config.unit, config.channel); - printf("Unit %d Channel %d: %ld mV\n", - static_cast(config.unit), - static_cast(config.channel), - voltage); -} -``` - -### Noise Reduction with Averaging - -```cpp -// Read 10 samples and return average -int32_t avgVoltage = adc.readVoltageAverage(AdcUnit::UNIT_1, AdcChannel::CHANNEL_0, 10); -printf("Average voltage: %ld mV\n", avgVoltage); - -// Read 50 raw samples and return average -int32_t avgRaw = adc.readRawAverage(AdcUnit::UNIT_1, AdcChannel::CHANNEL_0, 50); -printf("Average raw: %ld\n", avgRaw); -``` - -### Different Voltage Ranges - -```cpp -// Low voltage sensor (0-950mV) -AdcChannelConfig lowVoltageConfig = {}; -lowVoltageConfig.unit = AdcUnit::UNIT_1; -lowVoltageConfig.channel = AdcChannel::CHANNEL_0; -lowVoltageConfig.atten = AdcAttenuation::ATTEN_0dB; // 0-950mV -lowVoltageConfig.bitwidth = AdcBitwidth::WIDTH_12BIT; - -// Battery voltage (0-3.1V) -AdcChannelConfig batteryConfig = {}; -batteryConfig.unit = AdcUnit::UNIT_1; -batteryConfig.channel = AdcChannel::CHANNEL_1; -batteryConfig.atten = AdcAttenuation::ATTEN_11dB; // 0-3100mV -batteryConfig.bitwidth = AdcBitwidth::WIDTH_12BIT; - -adc.configureChannel(lowVoltageConfig); -adc.configureChannel(batteryConfig); -``` - -## API Reference - -### Constructor/Destructor - -- **Adc()**: Initialize ADC wrapper instance -- **~Adc()**: Clean up resources and deinitialize all units - -### Unit Management - -- **initializeUnit(unit, bitwidth)**: Initialize ADC unit with resolution -- **deinitializeUnit(unit)**: Deinitialize ADC unit -- **isUnitInitialized(unit)**: Check if unit is initialized - -### Channel Configuration - -- **configureChannel(config)**: Configure ADC channel -- **isChannelConfigured(unit, channel)**: Check if channel is configured - -### Reading Methods - -- **readVoltage(unit, channel)**: Read calibrated voltage in mV -- **readRaw(unit, channel)**: Read raw ADC value -- **readVoltageAverage(unit, channel, samples)**: Read averaged voltage -- **readRawAverage(unit, channel, samples)**: Read averaged raw value - -### Utility Methods - -- **getMaxRawValue(bitwidth)**: Get maximum raw value for resolution -- **getDefaultChannelConfig()**: Get default configuration - -## Voltage Ranges by Attenuation - -| Attenuation | Voltage Range | Typical Use Case | -|-------------|---------------|------------------| -| 0dB | 0 - 950mV | Low voltage sensors | -| 2.5dB | 0 - 1250mV | 1.2V references | -| 6dB | 0 - 1750mV | 1.8V logic levels | -| 11dB | 0 - 3100mV | 3.3V logic, battery voltage | - -## ADC Resolution and Range - -| Bitwidth | Resolution | Max Raw Value | LSB (at 3.1V) | -|----------|------------|---------------|----------------| -| 9-bit | 512 steps | 511 | ~6.1 mV | -| 10-bit | 1024 steps | 1023 | ~3.0 mV | -| 11-bit | 2048 steps | 2047 | ~1.5 mV | -| 12-bit | 4096 steps | 4095 | ~0.76 mV | -| 13-bit | 8192 steps | 8191 | ~0.38 mV | - -## Error Handling - -The module provides comprehensive error handling: -- Unit and channel validation -- Initialization status checks -- ESP-IDF error codes are caught and logged -- Return values indicate success/failure for all operations -- Graceful fallback when calibration is unavailable - -## Dependencies - -- ESP-IDF ADC driver (`esp_adc/adc_oneshot.h`) -- ESP-IDF ADC calibration (`esp_adc/adc_cali.h`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) - -## Thread Safety - -The ADC wrapper uses ESP-IDF's thread-safe ADC driver. Multiple tasks can safely read from different channels simultaneously. - -## Memory Usage - -- Fixed memory footprint per instance -- Calibration handles stored per channel -- No dynamic memory allocation in wrapper layer - -## Performance Considerations - -- Direct ESP-IDF function calls for optimal performance -- Calibration lookup tables for fast voltage conversion -- Averaging reduces noise but increases read time -- Higher resolution increases conversion time - -## Calibration - -The module automatically initializes calibration for each configured channel: -- Uses ESP-IDF's curve fitting calibration scheme -- Provides accurate voltage readings across temperature range -- Falls back to linear estimation if calibration fails -- Calibration data stored in eFuse (factory calibrated) - -## Limitations - -- ADC2 cannot be used when WiFi is active -- Some channels may not be available on all ESP32 variants -- Maximum sampling rate depends on resolution and calibration -- Input impedance affects accuracy for high-impedance sources \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.cpp deleted file mode 100644 index c02a49a..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/** - * @file adc.cpp - * @brief ADC wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "adc.hpp" -#include "logger.hpp" -#include - -static const char* TAG = "ADC_WRAPPER"; - -Adc::Adc() -{ - // Initialize handles to NULL - memset(m_adcHandle_, 0, sizeof(m_adcHandle_)); - memset(m_caliHandle_, 0, sizeof(m_caliHandle_)); - memset(m_unitInitialized_, false, sizeof(m_unitInitialized_)); - memset(m_channelConfigured_, false, sizeof(m_channelConfigured_)); - - m_unitBitwidth_[0] = AdcBitwidth::WIDTH_12BIT; - m_unitBitwidth_[1] = AdcBitwidth::WIDTH_12BIT; - - ASF_LOGI(TAG, 2000, asf::logger::Criticality::LOW, "ADC wrapper initialized"); -} - -Adc::~Adc() -{ - // Deinitialize all units - for (int i = 0; i < 2; i++) { - if (m_unitInitialized_[i]) { - deinitializeUnit(static_cast(i + 1)); - } - } - ASF_LOGI(TAG, 2001, asf::logger::Criticality::LOW, "ADC wrapper destroyed"); -} - -bool Adc::initialize() -{ - ASF_LOGI(TAG, 2002, asf::logger::Criticality::LOW, "ADC initialized successfully"); - return true; -} - -bool Adc::initializeUnit(AdcUnit unit, AdcBitwidth bitwidth) -{ - uint8_t unitIdx = getUnitIndex(unit); - - if (m_unitInitialized_[unitIdx]) { - ASF_LOGW(TAG, 2003, asf::logger::Criticality::MEDIUM, "ADC unit %d already initialized", unitIdx + 1); - return true; - } - - // Configure ADC unit - adc_oneshot_unit_init_cfg_t initConfig = {}; - initConfig.unit_id = convertUnit(unit); - - esp_err_t ret = adc_oneshot_new_unit(&initConfig, &m_adcHandle_[unitIdx]); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2004, asf::logger::Criticality::HIGH, "Failed to initialize ADC unit %d: %s", unitIdx + 1, esp_err_to_name(ret)); - return false; - } - - m_unitInitialized_[unitIdx] = true; - m_unitBitwidth_[unitIdx] = bitwidth; - ASF_LOGI(TAG, 2005, asf::logger::Criticality::LOW, "ADC unit %d initialized successfully", unitIdx + 1); - return true; -} - -bool Adc::deinitializeUnit(AdcUnit unit) -{ - uint8_t unitIdx = getUnitIndex(unit); - - if (!m_unitInitialized_[unitIdx]) { - ASF_LOGW(TAG, 2006, asf::logger::Criticality::MEDIUM, "ADC unit %d not initialized", unitIdx + 1); - return true; - } - - // Deinitialize all calibrations for this unit - for (int ch = 0; ch < 10; ch++) { - if (m_channelConfigured_[unitIdx][ch]) { - deinitializeCalibration(unit, static_cast(ch)); - m_channelConfigured_[unitIdx][ch] = false; - } - } - - esp_err_t ret = adc_oneshot_del_unit(m_adcHandle_[unitIdx]); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2007, asf::logger::Criticality::HIGH, "Failed to deinitialize ADC unit %d: %s", unitIdx + 1, esp_err_to_name(ret)); - return false; - } - - m_adcHandle_[unitIdx] = nullptr; - m_unitInitialized_[unitIdx] = false; - ASF_LOGI(TAG, 2008, asf::logger::Criticality::LOW, "ADC unit %d deinitialized", unitIdx + 1); - return true; -} - -bool Adc::configureChannel(const AdcChannelConfig& config) -{ - uint8_t unitIdx = getUnitIndex(config.unit); - uint8_t channelIdx = getChannelIndex(config.channel); - - if (!m_unitInitialized_[unitIdx]) { - ASF_LOGE(TAG, 2009, asf::logger::Criticality::HIGH, "ADC unit %d not initialized", unitIdx + 1); - return false; - } - - // Configure channel - adc_oneshot_chan_cfg_t chanConfig = {}; - chanConfig.atten = convertAttenuation(config.atten); - chanConfig.bitwidth = convertBitwidth(config.bitwidth); - - esp_err_t ret = adc_oneshot_config_channel(m_adcHandle_[unitIdx], - convertChannel(config.channel), &chanConfig); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2010, asf::logger::Criticality::HIGH, "Failed to configure ADC channel %d on unit %d: %s", - channelIdx, unitIdx + 1, esp_err_to_name(ret)); - return false; - } - - // Initialize calibration - if (!initializeCalibration(config.unit, config.channel, config.atten)) { - ASF_LOGW(TAG, 2011, asf::logger::Criticality::MEDIUM, "Failed to initialize calibration for channel %d on unit %d", - channelIdx, unitIdx + 1); - } - - m_channelConfigured_[unitIdx][channelIdx] = true; - ASF_LOGI(TAG, 2012, asf::logger::Criticality::LOW, "ADC channel %d configured on unit %d", channelIdx, unitIdx + 1); - return true; -} - -int32_t Adc::readVoltage(AdcUnit unit, AdcChannel channel) -{ - uint8_t unitIdx = getUnitIndex(unit); - uint8_t channelIdx = getChannelIndex(channel); - - if (!m_unitInitialized_[unitIdx]) { - ASF_LOGE(TAG, 2013, asf::logger::Criticality::HIGH, "ADC unit %d not initialized", unitIdx + 1); - return -1; - } - - if (!m_channelConfigured_[unitIdx][channelIdx]) { - ASF_LOGE(TAG, 2014, asf::logger::Criticality::HIGH, "ADC channel %d not configured on unit %d", channelIdx, unitIdx + 1); - return -1; - } - - // Read raw value - int rawValue = 0; - esp_err_t ret = adc_oneshot_read(m_adcHandle_[unitIdx], convertChannel(channel), &rawValue); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2015, asf::logger::Criticality::HIGH, "Failed to read ADC channel %d on unit %d: %s", - channelIdx, unitIdx + 1, esp_err_to_name(ret)); - return -1; - } - - // Convert to voltage if calibration is available - if (m_caliHandle_[unitIdx][channelIdx] != nullptr) { - int voltage = 0; - ret = adc_cali_raw_to_voltage(m_caliHandle_[unitIdx][channelIdx], rawValue, &voltage); - if (ret == ESP_OK) { - return voltage; - } else { - ASF_LOGW(TAG, 2016, asf::logger::Criticality::MEDIUM, "Failed to convert raw to voltage: %s", esp_err_to_name(ret)); - } - } - - // Fallback: estimate voltage based on attenuation and raw value - uint32_t maxRaw = getMaxRawValue(m_unitBitwidth_[unitIdx]); - return (rawValue * 3300) / maxRaw; // Rough estimation -} - -int32_t Adc::readRaw(AdcUnit unit, AdcChannel channel) -{ - uint8_t unitIdx = getUnitIndex(unit); - uint8_t channelIdx = getChannelIndex(channel); - - if (!m_unitInitialized_[unitIdx]) { - ASF_LOGE(TAG, 2017, asf::logger::Criticality::HIGH, "ADC unit %d not initialized", unitIdx + 1); - return -1; - } - - if (!m_channelConfigured_[unitIdx][channelIdx]) { - ASF_LOGE(TAG, 2018, asf::logger::Criticality::HIGH, "ADC channel %d not configured on unit %d", channelIdx, unitIdx + 1); - return -1; - } - - int rawValue = 0; - esp_err_t ret = adc_oneshot_read(m_adcHandle_[unitIdx], convertChannel(channel), &rawValue); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2019, asf::logger::Criticality::HIGH, "Failed to read ADC channel %d on unit %d: %s", - channelIdx, unitIdx + 1, esp_err_to_name(ret)); - return -1; - } - - return rawValue; -} - -int32_t Adc::readVoltageAverage(AdcUnit unit, AdcChannel channel, uint32_t samples) -{ - if (samples == 0) { - ASF_LOGE(TAG, 2020, asf::logger::Criticality::HIGH, "Invalid sample count"); - return -1; - } - - int64_t sum = 0; - uint32_t validSamples = 0; - - for (uint32_t i = 0; i < samples; i++) { - int32_t voltage = readVoltage(unit, channel); - if (voltage >= 0) { - sum += voltage; - validSamples++; - } - } - - if (validSamples == 0) { - ASF_LOGE(TAG, 2021, asf::logger::Criticality::HIGH, "No valid samples obtained"); - return -1; - } - - return static_cast(sum / validSamples); -} - -int32_t Adc::readRawAverage(AdcUnit unit, AdcChannel channel, uint32_t samples) -{ - if (samples == 0) { - ASF_LOGE(TAG, 2022, asf::logger::Criticality::HIGH, "Invalid sample count"); - return -1; - } - - int64_t sum = 0; - uint32_t validSamples = 0; - - for (uint32_t i = 0; i < samples; i++) { - int32_t raw = readRaw(unit, channel); - if (raw >= 0) { - sum += raw; - validSamples++; - } - } - - if (validSamples == 0) { - ASF_LOGE(TAG, 2023, asf::logger::Criticality::HIGH, "No valid samples obtained"); - return -1; - } - - return static_cast(sum / validSamples); -} - -bool Adc::isUnitInitialized(AdcUnit unit) const -{ - uint8_t unitIdx = getUnitIndex(unit); - return m_unitInitialized_[unitIdx]; -} - -bool Adc::isChannelConfigured(AdcUnit unit, AdcChannel channel) const -{ - uint8_t unitIdx = getUnitIndex(unit); - uint8_t channelIdx = getChannelIndex(channel); - return m_channelConfigured_[unitIdx][channelIdx]; -} - -uint32_t Adc::getMaxRawValue(AdcBitwidth bitwidth) -{ - switch (bitwidth) { - case AdcBitwidth::WIDTH_9BIT: - return 511; - case AdcBitwidth::WIDTH_10BIT: - return 1023; - case AdcBitwidth::WIDTH_11BIT: - return 2047; - case AdcBitwidth::WIDTH_12BIT: - return 4095; - case AdcBitwidth::WIDTH_13BIT: - return 8191; - default: - return 4095; - } -} - -AdcChannelConfig Adc::getDefaultChannelConfig() -{ - AdcChannelConfig config = {}; - config.unit = AdcUnit::UNIT_1; - config.channel = AdcChannel::CHANNEL_0; - config.atten = AdcAttenuation::ATTEN_11dB; - config.bitwidth = AdcBitwidth::WIDTH_12BIT; - return config; -} - -adc_unit_t Adc::convertUnit(AdcUnit unit) -{ - return static_cast(unit); -} - -adc_channel_t Adc::convertChannel(AdcChannel channel) -{ - return static_cast(channel); -} - -adc_atten_t Adc::convertAttenuation(AdcAttenuation atten) -{ - return static_cast(atten); -} - -adc_bitwidth_t Adc::convertBitwidth(AdcBitwidth bitwidth) -{ - return static_cast(bitwidth); -} - -bool Adc::initializeCalibration(AdcUnit unit, AdcChannel channel, AdcAttenuation atten) -{ - uint8_t unitIdx = getUnitIndex(unit); - uint8_t channelIdx = getChannelIndex(channel); - - adc_cali_line_fitting_config_t caliConfig = {}; - caliConfig.unit_id = convertUnit(unit); - caliConfig.atten = convertAttenuation(atten); - caliConfig.bitwidth = convertBitwidth(m_unitBitwidth_[unitIdx]); -#if CONFIG_IDF_TARGET_ESP32 - caliConfig.default_vref = 1100; // Default Vref for ESP32 -#endif - - esp_err_t ret = adc_cali_create_scheme_line_fitting(&caliConfig, &m_caliHandle_[unitIdx][channelIdx]); - if (ret == ESP_OK) { - ASF_LOGI(TAG, 2024, asf::logger::Criticality::LOW, "Calibration initialized for unit %d channel %d", unitIdx + 1, channelIdx); - return true; - } else { - ASF_LOGW(TAG, 2025, asf::logger::Criticality::MEDIUM, "Failed to initialize calibration for unit %d channel %d: %s", - unitIdx + 1, channelIdx, esp_err_to_name(ret)); - m_caliHandle_[unitIdx][channelIdx] = nullptr; - return false; - } -} - -bool Adc::deinitializeCalibration(AdcUnit unit, AdcChannel channel) -{ - uint8_t unitIdx = getUnitIndex(unit); - uint8_t channelIdx = getChannelIndex(channel); - - if (m_caliHandle_[unitIdx][channelIdx] != nullptr) { - esp_err_t ret = adc_cali_delete_scheme_line_fitting(m_caliHandle_[unitIdx][channelIdx]); - if (ret != ESP_OK) { - ASF_LOGW(TAG, 2026, asf::logger::Criticality::MEDIUM, "Failed to deinitialize calibration: %s", esp_err_to_name(ret)); - return false; - } - m_caliHandle_[unitIdx][channelIdx] = nullptr; - } - - return true; -} - -uint8_t Adc::getUnitIndex(AdcUnit unit) const -{ - return static_cast(unit) - 1; -} - -uint8_t Adc::getChannelIndex(AdcChannel channel) const -{ - return static_cast(channel); -} diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.hpp deleted file mode 100644 index caa796c..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/com/adc.hpp +++ /dev/null @@ -1,261 +0,0 @@ -/** - * @file adc.hpp - * @brief ADC wrapper component header - Wrapper for ESP-IDF ADC functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef ADC_HPP -#define ADC_HPP - -#include -#include "esp_adc/adc_oneshot.h" -#include "esp_adc/adc_cali.h" -#include "esp_adc/adc_cali_scheme.h" -#include "esp_err.h" - -/** - * @brief ADC unit enumeration - */ -enum class AdcUnit -{ - UNIT_1 = ADC_UNIT_1, - UNIT_2 = ADC_UNIT_2 -}; - -/** - * @brief ADC channel enumeration - */ -enum class AdcChannel -{ - CHANNEL_0 = ADC_CHANNEL_0, - CHANNEL_1 = ADC_CHANNEL_1, - CHANNEL_2 = ADC_CHANNEL_2, - CHANNEL_3 = ADC_CHANNEL_3, - CHANNEL_4 = ADC_CHANNEL_4, - CHANNEL_5 = ADC_CHANNEL_5, - CHANNEL_6 = ADC_CHANNEL_6, - CHANNEL_7 = ADC_CHANNEL_7, - CHANNEL_8 = ADC_CHANNEL_8, - CHANNEL_9 = ADC_CHANNEL_9 -}; - -/** - * @brief ADC attenuation enumeration - */ -enum class AdcAttenuation -{ - ATTEN_0dB = ADC_ATTEN_DB_0, ///< 0dB attenuation (0-950mV) - ATTEN_2_5dB = ADC_ATTEN_DB_2_5, ///< 2.5dB attenuation (0-1250mV) - ATTEN_6dB = ADC_ATTEN_DB_6, ///< 6dB attenuation (0-1750mV) - ATTEN_11dB = ADC_ATTEN_DB_11 ///< 11dB attenuation (0-3100mV) -}; - -/** - * @brief ADC bitwidth enumeration - */ -enum class AdcBitwidth -{ - WIDTH_9BIT = ADC_BITWIDTH_9, - WIDTH_10BIT = ADC_BITWIDTH_10, - WIDTH_11BIT = ADC_BITWIDTH_11, - WIDTH_12BIT = ADC_BITWIDTH_12, - WIDTH_13BIT = ADC_BITWIDTH_13 -}; - -/** - * @brief ADC channel configuration structure - */ -struct AdcChannelConfig -{ - AdcUnit unit; ///< ADC unit - AdcChannel channel; ///< ADC channel - AdcAttenuation atten; ///< Attenuation level - AdcBitwidth bitwidth; ///< ADC resolution -}; - -/** - * @brief ADC wrapper class - * - * Provides a C++ wrapper for ESP-IDF ADC functionality - * with simplified interface and error handling. - * This class encapsulates ESP-IDF ADC oneshot driver functions in an object-oriented interface. - */ -class Adc -{ -public: - /** - * @brief Constructor - * @details Initializes the ADC wrapper instance - */ - Adc(); - - /** - * @brief Destructor - * @details Cleans up resources and deinitializes ADC units - */ - ~Adc(); - - /** - * @brief Initialize ADC component - * @return true if initialized successfully, false otherwise - */ - bool initialize(); - - /** - * @brief Initialize ADC unit - * @param unit ADC unit to initialize - * @param bitwidth ADC resolution - * @return true if initialized successfully, false otherwise - */ - bool initializeUnit(AdcUnit unit, AdcBitwidth bitwidth); - - /** - * @brief Deinitialize ADC unit - * @param unit ADC unit to deinitialize - * @return true if deinitialized successfully, false otherwise - */ - bool deinitializeUnit(AdcUnit unit); - - /** - * @brief Configure ADC channel - * @param config Channel configuration - * @return true if configured successfully, false otherwise - * @note Unit must be initialized before configuring channels - */ - bool configureChannel(const AdcChannelConfig& config); - - /** - * @brief Read voltage from a channel - * @param unit ADC unit - * @param channel ADC channel to read - * @return Voltage in millivolts, or -1 on error - * @note Channel must be configured before reading - */ - int32_t readVoltage(AdcUnit unit, AdcChannel channel); - - /** - * @brief Read raw value from a channel - * @param unit ADC unit - * @param channel ADC channel to read - * @return Raw ADC value, or -1 on error - * @note Channel must be configured before reading - */ - int32_t readRaw(AdcUnit unit, AdcChannel channel); - - /** - * @brief Read multiple samples and return average - * @param unit ADC unit - * @param channel ADC channel to read - * @param samples Number of samples to average - * @return Average voltage in millivolts, or -1 on error - */ - int32_t readVoltageAverage(AdcUnit unit, AdcChannel channel, uint32_t samples); - - /** - * @brief Read multiple raw samples and return average - * @param unit ADC unit - * @param channel ADC channel to read - * @param samples Number of samples to average - * @return Average raw ADC value, or -1 on error - */ - int32_t readRawAverage(AdcUnit unit, AdcChannel channel, uint32_t samples); - - /** - * @brief Check if ADC unit is initialized - * @param unit ADC unit to check - * @return true if initialized, false otherwise - */ - bool isUnitInitialized(AdcUnit unit) const; - - /** - * @brief Check if channel is configured - * @param unit ADC unit - * @param channel ADC channel - * @return true if configured, false otherwise - */ - bool isChannelConfigured(AdcUnit unit, AdcChannel channel) const; - - /** - * @brief Get maximum raw value for given bitwidth - * @param bitwidth ADC bitwidth - * @return Maximum raw value - */ - static uint32_t getMaxRawValue(AdcBitwidth bitwidth); - - /** - * @brief Get default channel configuration - * @return Default ADC channel configuration - */ - static AdcChannelConfig getDefaultChannelConfig(); - -private: - adc_oneshot_unit_handle_t m_adcHandle_[2]; ///< ADC unit handles - adc_cali_handle_t m_caliHandle_[2][10]; ///< Calibration handles [unit][channel] - bool m_unitInitialized_[2]; ///< Unit initialization status - bool m_channelConfigured_[2][10]; ///< Channel configuration status [unit][channel] - AdcBitwidth m_unitBitwidth_[2]; ///< Bitwidth for each unit - - /** - * @brief Convert AdcUnit to ESP-IDF adc_unit_t - * @param unit ADC unit - * @return ESP-IDF adc_unit_t - */ - adc_unit_t convertUnit(AdcUnit unit); - - /** - * @brief Convert AdcChannel to ESP-IDF adc_channel_t - * @param channel ADC channel - * @return ESP-IDF adc_channel_t - */ - adc_channel_t convertChannel(AdcChannel channel); - - /** - * @brief Convert AdcAttenuation to ESP-IDF adc_atten_t - * @param atten ADC attenuation - * @return ESP-IDF adc_atten_t - */ - adc_atten_t convertAttenuation(AdcAttenuation atten); - - /** - * @brief Convert AdcBitwidth to ESP-IDF adc_bitwidth_t - * @param bitwidth ADC bitwidth - * @return ESP-IDF adc_bitwidth_t - */ - adc_bitwidth_t convertBitwidth(AdcBitwidth bitwidth); - - /** - * @brief Initialize calibration for channel - * @param unit ADC unit - * @param channel ADC channel - * @param atten Attenuation level - * @return true if calibration initialized, false otherwise - */ - bool initializeCalibration(AdcUnit unit, AdcChannel channel, AdcAttenuation atten); - - /** - * @brief Deinitialize calibration for channel - * @param unit ADC unit - * @param channel ADC channel - * @return true if calibration deinitialized, false otherwise - */ - bool deinitializeCalibration(AdcUnit unit, AdcChannel channel); - - /** - * @brief Get unit index from AdcUnit - * @param unit ADC unit - * @return Unit index (0 or 1) - */ - uint8_t getUnitIndex(AdcUnit unit) const; - - /** - * @brief Get channel index from AdcChannel - * @param channel ADC channel - * @return Channel index (0-9) - */ - uint8_t getChannelIndex(AdcChannel channel) const; -}; - -#endif // ADC_HPP - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/logging_data.csv deleted file mode 100644 index e4268a8..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/logging_data.csv +++ /dev/null @@ -1,28 +0,0 @@ -ID,Component,Level,Criticality,Message -2000,ADC,INFO,Low,ADC wrapper initialized -2001,ADC,INFO,Low,ADC wrapper destroyed -2002,ADC,INFO,Low,ADC initialized successfully -2003,ADC,WARNING,Medium,ADC unit %d already initialized -2004,ADC,ERROR,High,Failed to initialize ADC unit %d: %s -2005,ADC,INFO,Low,ADC unit %d initialized successfully -2006,ADC,WARNING,Medium,ADC unit %d not initialized -2007,ADC,ERROR,High,Failed to deinitialize ADC unit %d: %s -2008,ADC,INFO,Low,ADC unit %d deinitialized -2009,ADC,ERROR,High,ADC unit %d not initialized -2010,ADC,ERROR,High,Failed to configure ADC channel %d on unit %d: %s -2011,ADC,WARNING,Medium,Failed to initialize calibration for channel %d on unit %d -2012,ADC,INFO,Low,ADC channel %d configured on unit %d -2013,ADC,ERROR,High,ADC unit %d not initialized -2014,ADC,ERROR,High,ADC channel %d not configured on unit %d -2015,ADC,ERROR,High,Failed to read ADC channel %d on unit %d: %s -2016,ADC,WARNING,Medium,Failed to convert raw to voltage: %s -2017,ADC,ERROR,High,ADC unit %d not initialized -2018,ADC,ERROR,High,ADC channel %d not configured on unit %d -2019,ADC,ERROR,High,Failed to read ADC channel %d on unit %d: %s -2020,ADC,ERROR,High,Invalid sample count -2021,ADC,ERROR,High,No valid samples obtained -2022,ADC,ERROR,High,Invalid sample count -2023,ADC,ERROR,High,No valid samples obtained -2024,ADC,INFO,Low,Calibration initialized for unit %d channel %d -2025,ADC,WARNING,Medium,Failed to initialize calibration for unit %d channel %d: %s -2026,ADC,WARNING,Medium,Failed to deinitialize calibration: %s diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.py deleted file mode 100644 index c1b55da..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_adc_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "ADC wrapper initialized" in line or "ADC initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_adc_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.test_scenario.xml b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.test_scenario.xml deleted file mode 100644 index 3e9e508..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - ADC_INIT_TEST - - python components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.py - - - - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/test_adc.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/test_adc.cpp deleted file mode 100644 index 975512d..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/adc/test/test_adc.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file test_adc.cpp - * @brief Unit tests for ADC wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "adc.hpp" - -extern "C" { - -void setUp(void) -{ - // Set up test fixtures before each test -} - -void tearDown(void) -{ - // Clean up test fixtures after each test -} - -/** - * @brief Test ADC initialization - */ -void test_adc_initialize(void) -{ - Adc adc; - bool result = adc.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(adc.isInitialized()); -} - -/** - * @brief Test ADC deinitialize - */ -void test_adc_deinitialize(void) -{ - Adc adc; - adc.initialize(); - - bool result = adc.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(adc.isInitialized()); -} - -/** - * @brief Test ADC read voltage without initialization - */ -void test_adc_read_voltage_not_initialized(void) -{ - Adc adc; - int32_t result = adc.readVoltage(AdcChannel::CHANNEL_0, AdcAttenuation::ATTEN_0dB); - TEST_ASSERT_EQUAL(-1, result); -} - -/** - * @brief Test ADC read raw without initialization - */ -void test_adc_read_raw_not_initialized(void) -{ - Adc adc; - int32_t result = adc.readRaw(AdcChannel::CHANNEL_0, AdcAttenuation::ATTEN_0dB); - TEST_ASSERT_EQUAL(-1, result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/CMakeLists.txt deleted file mode 100644 index 1fad42a..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/bt.cpp" - INCLUDE_DIRS "com" - REQUIRES bt nvs_flash logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/README.md deleted file mode 100644 index 3ffbe6a..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/README.md +++ /dev/null @@ -1,502 +0,0 @@ -# Bluetooth Wrapper Module - -## Overview - -The Bluetooth wrapper module provides a C++ object-oriented interface for ESP-IDF Bluetooth functionality. This module encapsulates the ESP-IDF Bluetooth and BLE (Bluetooth Low Energy) driver functions and provides a clean, easy-to-use API for Bluetooth Classic, BLE, and dual-mode operations. - -## Features - -- **Multiple Modes**: Bluetooth Classic, BLE, and dual-mode support -- **BLE Advertising**: Configurable advertising parameters and data -- **BLE Scanning**: Network discovery and device scanning -- **GATT Server**: Create services and characteristics -- **GATT Client**: Connect to and interact with remote devices -- **Event Handling**: Comprehensive event callbacks for all operations -- **Security Support**: Pairing, bonding, and encryption -- **Power Management**: Configurable TX power levels - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ Bluetooth │ -├─────────────────────────────────────┤ -│ - m_isInitialized_: bool │ -│ - m_mode_: BtMode │ -│ - m_connectionState_: State │ -│ - m_connectedDeviceCount_: uint8_t │ -│ - m_gattsIf_: esp_gatt_if_t │ -│ - m_gattcIf_: esp_gatt_if_t │ -│ - m_appId_: uint16_t │ -│ - m_gapCallback_: Callback │ -│ - m_gattsCallback_: Callback │ -│ - m_gattcCallback_: Callback │ -├─────────────────────────────────────┤ -│ + Bluetooth() │ -│ + ~Bluetooth() │ -│ + initialize(mode): bool │ -│ + deinitialize(): bool │ -│ + setDeviceName(name): bool │ -│ + getDeviceName(name, len): bool │ -│ + setAdvParams(params): bool │ -│ + setAdvData(data): bool │ -│ + startAdvertising(): bool │ -│ + stopAdvertising(): bool │ -│ + startScanning(duration): bool │ -│ + stopScanning(): bool │ -│ + createGattService(svc): uint16_t │ -│ + addCharacteristic(...): uint16_t │ -│ + startGattService(handle): bool │ -│ + stopGattService(handle): bool │ -│ + sendNotification(...): bool │ -│ + sendIndication(...): bool │ -│ + connectToDevice(...): bool │ -│ + disconnectDevice(connId): bool │ -│ + getConnectionState(): State │ -│ + isConnected(): bool │ -│ + getConnectedDeviceCount(): uint8_t│ -│ + setGapEventCallback(...): void │ -│ + setGattsEventCallback(...): void │ -│ + setGattcEventCallback(...): void │ -│ + getMacAddress(mac): bool │ -│ + setTxPower(type, level): bool │ -│ + getTxPower(type): esp_power_level │ -│ + isInitialized(): bool │ -│ + getDefaultAdvParams(): Params │ -│ + getDefaultAdvData(): Data │ -│ + getDefaultGattService(): Service │ -│ + getDefaultGattChar(): Char │ -│ - gapEventHandler(...): void │ -│ - gattsEventHandler(...): void │ -│ - gattcEventHandler(...): void │ -│ - convertMode(mode): esp_bt_mode_t │ -│ - convertAdvType(type): esp_adv_t │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### BtMode -- `CLASSIC`: Bluetooth Classic mode -- `BLE`: Bluetooth Low Energy mode -- `DUAL`: Dual mode (Classic + BLE) - -#### BleAdvType -- `ADV_IND`: Connectable undirected advertising -- `ADV_DIRECT_IND_HIGH`: Connectable directed advertising (high duty cycle) -- `ADV_SCAN_IND`: Scannable undirected advertising -- `ADV_NONCONN_IND`: Non-connectable undirected advertising -- `ADV_DIRECT_IND_LOW`: Connectable directed advertising (low duty cycle) - -#### BleConnectionState -- `DISCONNECTED`: Not connected -- `CONNECTING`: Connection in progress -- `CONNECTED`: Successfully connected -- `DISCONNECTING`: Disconnection in progress - -### Configuration Structures - -#### BleAdvParams -```cpp -struct BleAdvParams { - uint16_t advIntMin; // Minimum advertising interval - uint16_t advIntMax; // Maximum advertising interval - BleAdvType advType; // Advertising type - uint8_t ownAddrType; // Own address type - uint8_t peerAddrType; // Peer address type - uint8_t peerAddr[6]; // Peer address - uint8_t channelMap; // Channel map - uint8_t advFilterPolicy; // Advertising filter policy -}; -``` - -#### BleAdvData -```cpp -struct BleAdvData { - bool setName; // Set device name in advertising data - bool setTxPower; // Set TX power in advertising data - bool includeUuid; // Include service UUID - bool setManufacturerData; // Set manufacturer data - uint16_t appearance; // Device appearance - uint16_t manufacturerId; // Manufacturer ID - uint8_t manufacturerDataLen; // Manufacturer data length - uint8_t* manufacturerData; // Manufacturer data - uint8_t serviceUuidLen; // Service UUID length - uint8_t* serviceUuid; // Service UUID - char* deviceName; // Device name -}; -``` - -#### GattService -```cpp -struct GattService { - uint16_t serviceId; // Service ID - uint16_t serviceUuid; // Service UUID - uint16_t numHandles; // Number of handles - bool isPrimary; // Primary service flag -}; -``` - -#### GattCharacteristic -```cpp -struct GattCharacteristic { - uint16_t charUuid; // Characteristic UUID - uint8_t properties; // Characteristic properties - uint8_t permissions; // Characteristic permissions - uint16_t maxLen; // Maximum value length - bool autoRsp; // Auto response flag -}; -``` - -## Usage Examples - -### Basic BLE Advertising - -```cpp -#include "bt.hpp" - -// BLE event callback -void bleGapCallback(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param, void* userData) { - switch (event) { - case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: - printf("Advertising started\n"); - break; - case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: - printf("Advertising stopped\n"); - break; - default: - break; - } -} - -// Create Bluetooth instance -Bluetooth bt; - -// Initialize BLE -bt.initialize(BtMode::BLE); - -// Set device name -bt.setDeviceName("ESP32-BLE-Device"); - -// Set event callback -bt.setGapEventCallback(bleGapCallback, nullptr); - -// Configure advertising -BleAdvParams advParams = Bluetooth::getDefaultAdvParams(); -advParams.advIntMin = 0x20; // 20ms -advParams.advIntMax = 0x40; // 40ms - -bt.setAdvParams(advParams); - -// Set advertising data -BleAdvData advData = Bluetooth::getDefaultAdvData(); -advData.setName = true; -advData.setTxPower = true; - -bt.setAdvData(advData); - -// Start advertising -bt.startAdvertising(); -``` - -### BLE GATT Server - -```cpp -// GATT server event callback -void bleGattsCallback(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t* param, void* userData) { - switch (event) { - case ESP_GATTS_CONNECT_EVT: - printf("Client connected\n"); - break; - case ESP_GATTS_DISCONNECT_EVT: - printf("Client disconnected\n"); - break; - case ESP_GATTS_READ_EVT: - printf("Characteristic read request\n"); - break; - case ESP_GATTS_WRITE_EVT: - printf("Characteristic write request\n"); - break; - default: - break; - } -} - -// Set GATT server callback -bt.setGattsEventCallback(bleGattsCallback, nullptr); - -// Create a service -GattService service = Bluetooth::getDefaultGattService(); -service.serviceUuid = 0x180F; // Battery Service -service.numHandles = 4; - -uint16_t serviceHandle = bt.createGattService(service); - -// Add characteristic -GattCharacteristic characteristic = Bluetooth::getDefaultGattCharacteristic(); -characteristic.charUuid = 0x2A19; // Battery Level -characteristic.properties = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY; - -uint16_t charHandle = bt.addCharacteristic(serviceHandle, characteristic); - -// Start the service -bt.startGattService(serviceHandle); -``` - -### BLE Scanning - -```cpp -// Scanning callback -void bleScanCallback(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param, void* userData) { - switch (event) { - case ESP_GAP_BLE_SCAN_RESULT_EVT: { - esp_ble_gap_cb_param_t* scanResult = param; - if (scanResult->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { - printf("Found device: "); - for (int i = 0; i < 6; i++) { - printf("%02X", scanResult->scan_rst.bda[i]); - if (i < 5) printf(":"); - } - printf(" RSSI: %d\n", scanResult->scan_rst.rssi); - } - break; - } - case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: - printf("Scan started\n"); - break; - case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: - printf("Scan stopped\n"); - break; - default: - break; - } -} - -// Set scan callback -bt.setGapEventCallback(bleScanCallback, nullptr); - -// Start scanning for 10 seconds -bt.startScanning(10); -``` - -### BLE Client Connection - -```cpp -// GATT client callback -void bleGattcCallback(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t* param, void* userData) { - switch (event) { - case ESP_GATTC_CONNECT_EVT: - printf("Connected to server\n"); - break; - case ESP_GATTC_DISCONNECT_EVT: - printf("Disconnected from server\n"); - break; - case ESP_GATTC_SEARCH_CMPL_EVT: - printf("Service discovery complete\n"); - break; - default: - break; - } -} - -// Set GATT client callback -bt.setGattcEventCallback(bleGattcCallback, nullptr); - -// Connect to remote device -uint8_t remoteAddr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; -bt.connectToDevice(remoteAddr, BLE_ADDR_TYPE_PUBLIC); -``` - -### Dual Mode Operation - -```cpp -// Initialize in dual mode -bt.initialize(BtMode::DUAL); - -// Set up BLE advertising -bt.setDeviceName("ESP32-Dual-Mode"); -bt.startAdvertising(); - -// Also available for Bluetooth Classic operations -// (Classic Bluetooth APIs would be used here) -``` - -## API Reference - -### Constructor/Destructor - -- **Bluetooth()**: Initialize Bluetooth wrapper instance -- **~Bluetooth()**: Clean up resources and deinitialize Bluetooth - -### Initialization Methods - -- **initialize(mode)**: Initialize Bluetooth stack with specified mode -- **deinitialize()**: Deinitialize Bluetooth stack -- **isInitialized()**: Check if Bluetooth is initialized - -### Device Configuration - -- **setDeviceName(name)**: Set Bluetooth device name -- **getDeviceName(name, maxLen)**: Get current device name -- **getMacAddress(mac)**: Get Bluetooth MAC address - -### BLE Advertising - -- **setAdvParams(params)**: Set advertising parameters -- **setAdvData(advData)**: Set advertising data -- **startAdvertising()**: Start BLE advertising -- **stopAdvertising()**: Stop BLE advertising - -### BLE Scanning - -- **startScanning(duration)**: Start BLE scanning -- **stopScanning()**: Stop BLE scanning - -### GATT Server - -- **createGattService(service)**: Create GATT service -- **addCharacteristic(serviceHandle, characteristic)**: Add characteristic to service -- **startGattService(serviceHandle)**: Start GATT service -- **stopGattService(serviceHandle)**: Stop GATT service -- **sendNotification(connId, attrHandle, data, dataLen)**: Send notification -- **sendIndication(connId, attrHandle, data, dataLen)**: Send indication - -### GATT Client - -- **connectToDevice(remoteAddr, addrType)**: Connect to remote device -- **disconnectDevice(connId)**: Disconnect from device - -### Connection Management - -- **getConnectionState()**: Get current connection state -- **isConnected()**: Check if any device is connected -- **getConnectedDeviceCount()**: Get number of connected devices - -### Event Handling - -- **setGapEventCallback(callback, userData)**: Set GAP event callback -- **setGattsEventCallback(callback, userData)**: Set GATT server callback -- **setGattcEventCallback(callback, userData)**: Set GATT client callback - -### Power Management - -- **setTxPower(powerType, powerLevel)**: Set TX power level -- **getTxPower(powerType)**: Get current TX power level - -### Configuration Methods - -- **getDefaultAdvParams()**: Get default advertising parameters -- **getDefaultAdvData()**: Get default advertising data -- **getDefaultGattService()**: Get default GATT service configuration -- **getDefaultGattCharacteristic()**: Get default characteristic configuration - -## Error Handling - -The module provides comprehensive error handling: -- Initialization status checks -- ESP-IDF error codes are caught and logged -- Return values indicate success/failure for all operations -- Event callbacks for asynchronous status updates -- Automatic cleanup of resources on errors - -## Dependencies - -- ESP-IDF Bluetooth stack (`esp_bt.h`, `esp_bt_main.h`) -- ESP-IDF BLE GAP API (`esp_gap_ble_api.h`) -- ESP-IDF GATT server API (`esp_gatts_api.h`) -- ESP-IDF GATT client API (`esp_gattc_api.h`) -- NVS flash storage (`nvs_flash.h`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) - -## Thread Safety - -The Bluetooth wrapper uses ESP-IDF's thread-safe Bluetooth stack. Event callbacks are called from the Bluetooth task context and should be kept short. - -## Memory Usage - -- Fixed memory footprint per instance -- Bluetooth stack uses significant RAM (configurable) -- GATT database stored in flash/RAM -- Event callbacks use minimal stack space - -## Performance Considerations - -- Bluetooth operations are asynchronous with event callbacks -- GATT operations have latency depending on connection interval -- Multiple simultaneous connections increase memory usage -- Advertising and scanning affect power consumption - -## Security Features - -### Pairing and Bonding -- Support for various pairing methods -- Secure Simple Pairing (SSP) -- Out-of-Band (OOB) authentication -- Passkey entry and numeric comparison - -### Encryption -- AES-128 encryption for BLE -- Link-level security -- Application-level encryption support - -## Power Management - -### BLE Power Optimization -- Configurable advertising intervals -- Connection interval optimization -- Sleep mode support -- TX power control - -### Connection Parameters -- Minimum/maximum connection intervals -- Slave latency configuration -- Supervision timeout settings - -## Common Use Cases - -### IoT Sensor Node -- BLE advertising with sensor data -- GATT server for configuration -- Low power operation -- Mobile app connectivity - -### BLE Gateway -- Multiple device connections -- Data aggregation and forwarding -- WiFi + BLE dual connectivity -- Cloud integration - -### HID Device -- Keyboard/mouse emulation -- Custom HID reports -- Pairing and bonding -- Battery level reporting - -### Beacon Applications -- iBeacon/Eddystone protocols -- Proximity detection -- Asset tracking -- Location services - -## Troubleshooting - -### Common Issues - -1. **Initialization Failures**: Check NVS partition and Bluetooth configuration -2. **Connection Issues**: Verify advertising parameters and device compatibility -3. **GATT Errors**: Check service/characteristic UUIDs and permissions -4. **Memory Issues**: Monitor heap usage, especially with multiple connections -5. **Range Problems**: Check TX power settings and antenna configuration - -### Debug Tips - -1. Enable Bluetooth logging in menuconfig -2. Use ESP-IDF Bluetooth tools for analysis -3. Monitor connection parameters -4. Check for interference on 2.4GHz band -5. Verify security requirements and capabilities \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.cpp deleted file mode 100644 index 7e9c657..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.cpp +++ /dev/null @@ -1,621 +0,0 @@ -/** - * @file bt.cpp - * @brief Bluetooth wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "bt.hpp" -#include "logger.hpp" -#include - -static const char* TAG = "BT_WRAPPER"; - -// Static instance for callbacks -Bluetooth* Bluetooth::s_instance_ = nullptr; - -Bluetooth::Bluetooth() - : m_isInitialized_(false) - , m_mode_(BtMode::BLE) - , m_connectionState_(BleConnectionState::DISCONNECTED) - , m_connectedDeviceCount_(0) -#ifdef CONFIG_BT_ENABLED - , m_gattsIf_(ESP_GATT_IF_NONE) - , m_gattcIf_(ESP_GATT_IF_NONE) -#else - , m_gattsIf_(0) - , m_gattcIf_(0) -#endif - , m_appId_(0) - , m_gapCallback_(nullptr) - , m_gapUserData_(nullptr) - , m_gattsCallback_(nullptr) - , m_gattsUserData_(nullptr) - , m_gattcCallback_(nullptr) - , m_gattcUserData_(nullptr) -{ - s_instance_ = this; - ASF_LOGI(TAG, 2100, asf::logger::Criticality::LOW, "Bluetooth wrapper initialized"); -} - -Bluetooth::~Bluetooth() -{ - deinitialize(); - s_instance_ = nullptr; - ASF_LOGI(TAG, 2101, asf::logger::Criticality::LOW, "Bluetooth wrapper destroyed"); -} - -bool Bluetooth::initialize(BtMode mode) -{ -#ifdef CONFIG_BT_ENABLED - if (m_isInitialized_) { - ASF_LOGW(TAG, 2102, asf::logger::Criticality::MEDIUM, "Bluetooth already initialized"); - return true; - } - - // Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - // Release Bluetooth controller memory if not needed - ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); - - // Initialize Bluetooth controller - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - ret = esp_bt_controller_init(&bt_cfg); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2103, asf::logger::Criticality::HIGH, "Failed to initialize BT controller: %s", esp_err_to_name(ret)); - return false; - } - - // Enable Bluetooth controller - ret = esp_bt_controller_enable(convertMode(mode)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2104, asf::logger::Criticality::HIGH, "Failed to enable BT controller: %s", esp_err_to_name(ret)); - return false; - } - - // Initialize Bluedroid stack - ret = esp_bluedroid_init(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2105, asf::logger::Criticality::HIGH, "Failed to initialize Bluedroid: %s", esp_err_to_name(ret)); - return false; - } - - // Enable Bluedroid stack - ret = esp_bluedroid_enable(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2106, asf::logger::Criticality::HIGH, "Failed to enable Bluedroid: %s", esp_err_to_name(ret)); - return false; - } - - // Register GAP callback - ret = esp_ble_gap_register_callback(gapEventHandler); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2107, asf::logger::Criticality::HIGH, "Failed to register GAP callback: %s", esp_err_to_name(ret)); - return false; - } - - // Register GATTS callback - ret = esp_ble_gatts_register_callback(gattsEventHandler); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2108, asf::logger::Criticality::HIGH, "Failed to register GATTS callback: %s", esp_err_to_name(ret)); - return false; - } - - // Register GATTC callback - ret = esp_ble_gattc_register_callback(gattcEventHandler); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2109, asf::logger::Criticality::HIGH, "Failed to register GATTC callback: %s", esp_err_to_name(ret)); - return false; - } - - m_mode_ = mode; - m_isInitialized_ = true; - ASF_LOGI(TAG, 2110, asf::logger::Criticality::LOW, "Bluetooth initialized successfully"); - return true; -#else - ASF_LOGW(TAG, 2111, asf::logger::Criticality::MEDIUM, "Bluetooth disabled in sdkconfig"); - return false; -#endif -} - -bool Bluetooth::deinitialize() -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGW(TAG, 2112, asf::logger::Criticality::MEDIUM, "Bluetooth not initialized"); - return true; - } - - stopAdvertising(); - stopScanning(); - - // Disable Bluedroid stack - esp_err_t ret = esp_bluedroid_disable(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2113, asf::logger::Criticality::HIGH, "Failed to disable Bluedroid: %s", esp_err_to_name(ret)); - } - - // Deinitialize Bluedroid stack - ret = esp_bluedroid_deinit(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2114, asf::logger::Criticality::HIGH, "Failed to deinitialize Bluedroid: %s", esp_err_to_name(ret)); - } - - // Disable Bluetooth controller - ret = esp_bt_controller_disable(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2115, asf::logger::Criticality::HIGH, "Failed to disable BT controller: %s", esp_err_to_name(ret)); - } - - // Deinitialize Bluetooth controller - ret = esp_bt_controller_deinit(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2116, asf::logger::Criticality::HIGH, "Failed to deinitialize BT controller: %s", esp_err_to_name(ret)); - } - - m_isInitialized_ = false; - m_connectionState_ = BleConnectionState::DISCONNECTED; - m_connectedDeviceCount_ = 0; - ASF_LOGI(TAG, 2117, asf::logger::Criticality::LOW, "Bluetooth deinitialized"); - return true; -#else - return true; -#endif -} - -bool Bluetooth::setDeviceName(const char* name) -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_ || name == nullptr) { - ASF_LOGE(TAG, 2118, asf::logger::Criticality::HIGH, "Bluetooth not initialized or invalid name"); - return false; - } - - esp_err_t ret = esp_ble_gap_set_device_name(name); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2119, asf::logger::Criticality::HIGH, "Failed to set device name: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2120, asf::logger::Criticality::LOW, "Device name set to: %s", name); - return true; -#else - return false; -#endif -} - -bool Bluetooth::getDeviceName(char* name, size_t maxLen) -{ - if (name == nullptr || maxLen == 0) return false; - strncpy(name, "ESP32-BT", maxLen - 1); - name[maxLen - 1] = '\0'; - return true; -} - -bool Bluetooth::setAdvParams(const BleAdvParams& params) -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2121, asf::logger::Criticality::HIGH, "Bluetooth not initialized"); - return false; - } - - esp_ble_adv_params_t advParams = {}; - advParams.adv_int_min = params.advIntMin; - advParams.adv_int_max = params.advIntMax; - advParams.adv_type = convertAdvType(params.advType); - advParams.own_addr_type = static_cast(params.ownAddrType); - advParams.peer_addr_type = static_cast(params.peerAddrType); - memcpy(advParams.peer_addr, params.peerAddr, 6); - advParams.channel_map = static_cast(params.channelMap); - advParams.adv_filter_policy = static_cast(params.advFilterPolicy); - - esp_err_t ret = esp_ble_gap_config_adv_data_raw(nullptr, 0); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2122, asf::logger::Criticality::HIGH, "Failed to set advertising parameters: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2123, asf::logger::Criticality::LOW, "Advertising parameters set successfully"); - return true; -#else - return false; -#endif -} - -bool Bluetooth::setAdvData(const BleAdvData& advData) -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2124, asf::logger::Criticality::HIGH, "Bluetooth not initialized"); - return false; - } - - esp_ble_adv_data_t bleAdvData = {}; - bleAdvData.set_scan_rsp = false; - bleAdvData.include_name = advData.setName; - bleAdvData.include_txpower = advData.setTxPower; - bleAdvData.min_interval = 0x0006; - bleAdvData.max_interval = 0x0010; - bleAdvData.appearance = advData.appearance; - bleAdvData.manufacturer_len = advData.manufacturerDataLen; - bleAdvData.p_manufacturer_data = advData.manufacturerData; - bleAdvData.service_data_len = 0; - bleAdvData.p_service_data = nullptr; - bleAdvData.service_uuid_len = advData.serviceUuidLen; - bleAdvData.p_service_uuid = advData.serviceUuid; - bleAdvData.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT); - - esp_err_t ret = esp_ble_gap_config_adv_data(&bleAdvData); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2125, asf::logger::Criticality::HIGH, "Failed to set advertising data: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2126, asf::logger::Criticality::LOW, "Advertising data set successfully"); - return true; -#else - return false; -#endif -} - -bool Bluetooth::startAdvertising() -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2127, asf::logger::Criticality::HIGH, "Bluetooth not initialized"); - return false; - } - - esp_ble_adv_params_t params = {}; - params.adv_int_min = 0x20; - params.adv_int_max = 0x40; - params.adv_type = ADV_TYPE_IND; - params.own_addr_type = BLE_ADDR_TYPE_PUBLIC; - params.channel_map = ADV_CHNL_ALL; - params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY; - - esp_err_t ret = esp_ble_gap_start_advertising(¶ms); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2128, asf::logger::Criticality::HIGH, "Failed to start advertising: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2129, asf::logger::Criticality::LOW, "BLE advertising started"); - return true; -#else - return false; -#endif -} - -bool Bluetooth::stopAdvertising() -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGW(TAG, 2130, asf::logger::Criticality::MEDIUM, "Bluetooth not initialized"); - return true; - } - - esp_err_t ret = esp_ble_gap_stop_advertising(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2131, asf::logger::Criticality::HIGH, "Failed to stop advertising: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2132, asf::logger::Criticality::LOW, "BLE advertising stopped"); - return true; -#else - return true; -#endif -} - -bool Bluetooth::startScanning(uint32_t duration) -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2133, asf::logger::Criticality::HIGH, "Bluetooth not initialized"); - return false; - } - - esp_ble_scan_params_t scanParams = {}; - scanParams.scan_type = BLE_SCAN_TYPE_ACTIVE; - scanParams.own_addr_type = BLE_ADDR_TYPE_PUBLIC; - scanParams.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL; - scanParams.scan_interval = 0x50; - scanParams.scan_window = 0x30; - scanParams.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE; - - esp_err_t ret = esp_ble_gap_set_scan_params(&scanParams); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2134, asf::logger::Criticality::HIGH, "Failed to set scan parameters: %s", esp_err_to_name(ret)); - return false; - } - - ret = esp_ble_gap_start_scanning(duration); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2135, asf::logger::Criticality::HIGH, "Failed to start scanning: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2136, asf::logger::Criticality::LOW, "BLE scanning started (duration: %lu seconds)", duration); - return true; -#else - return false; -#endif -} - -bool Bluetooth::stopScanning() -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGW(TAG, 2137, asf::logger::Criticality::MEDIUM, "Bluetooth not initialized"); - return true; - } - - esp_err_t ret = esp_ble_gap_stop_scanning(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2138, asf::logger::Criticality::HIGH, "Failed to stop scanning: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2139, asf::logger::Criticality::LOW, "BLE scanning stopped"); - return true; -#else - return true; -#endif -} - -uint16_t Bluetooth::createGattService(const GattService& service) -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2140, asf::logger::Criticality::HIGH, "Bluetooth not initialized"); - return 0; - } - - esp_gatt_srvc_id_t serviceId = {}; - serviceId.is_primary = service.isPrimary; - serviceId.id.inst_id = service.serviceId; - serviceId.id.uuid.len = ESP_UUID_LEN_16; - serviceId.id.uuid.uuid.uuid16 = service.serviceUuid; - - esp_err_t ret = esp_ble_gatts_create_service(m_gattsIf_, &serviceId, service.numHandles); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2141, asf::logger::Criticality::HIGH, "Failed to create GATT service: %s", esp_err_to_name(ret)); - return 0; - } - - ASF_LOGI(TAG, 2142, asf::logger::Criticality::LOW, "GATT service created successfully"); - return service.serviceId; -#else - return 0; -#endif -} - -bool Bluetooth::startGattService(uint16_t serviceHandle) -{ -#ifdef CONFIG_BT_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2143, asf::logger::Criticality::HIGH, "Bluetooth not initialized"); - return false; - } - - esp_err_t ret = esp_ble_gatts_start_service(serviceHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2144, asf::logger::Criticality::HIGH, "Failed to start GATT service: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2145, asf::logger::Criticality::LOW, "GATT service started successfully"); - return true; -#else - return false; -#endif -} - -BleConnectionState Bluetooth::getConnectionState() const -{ - return m_connectionState_; -} - -bool Bluetooth::isConnected() const -{ - return m_connectionState_ == BleConnectionState::CONNECTED; -} - -uint8_t Bluetooth::getConnectedDeviceCount() const -{ - return m_connectedDeviceCount_; -} - -void Bluetooth::setGapEventCallback(BtGapEventCallback callback, void* userData) -{ - m_gapCallback_ = callback; - m_gapUserData_ = userData; -} - -void Bluetooth::setGattsEventCallback(BtGattsEventCallback callback, void* userData) -{ - m_gattsCallback_ = callback; - m_gattsUserData_ = userData; -} - -void Bluetooth::setGattcEventCallback(BtGattcEventCallback callback, void* userData) -{ - m_gattcCallback_ = callback; - m_gattcUserData_ = userData; -} - -bool Bluetooth::getMacAddress(uint8_t* mac) -{ -#ifdef CONFIG_BT_ENABLED - if (mac == nullptr) { - ASF_LOGE(TAG, 2146, asf::logger::Criticality::HIGH, "Invalid MAC address buffer"); - return false; - } - - memcpy(mac, esp_bt_dev_get_address(), 6); - return true; -#else - return false; -#endif -} - -bool Bluetooth::isInitialized() const -{ - return m_isInitialized_; -} - -BleAdvParams Bluetooth::getDefaultAdvParams() -{ - BleAdvParams params = {}; - params.advIntMin = 0x20; - params.advIntMax = 0x40; - params.advType = BleAdvType::ADV_IND; - params.ownAddrType = 0; - params.peerAddrType = 0; - memset(params.peerAddr, 0, 6); - params.channelMap = 7; - params.advFilterPolicy = 0; - return params; -} - -BleAdvData Bluetooth::getDefaultAdvData() -{ - BleAdvData advData = {}; - advData.setName = true; - advData.setTxPower = true; - advData.includeUuid = false; - advData.setManufacturerData = false; - advData.appearance = 0; - advData.manufacturerId = 0; - advData.manufacturerDataLen = 0; - advData.manufacturerData = nullptr; - advData.serviceUuidLen = 0; - advData.serviceUuid = nullptr; - advData.deviceName = nullptr; - return advData; -} - -GattService Bluetooth::getDefaultGattService() -{ - GattService service = {}; - service.serviceId = 0; - service.serviceUuid = 0x180F; // Battery Service UUID - service.numHandles = 4; - service.isPrimary = true; - return service; -} - -GattCharacteristic Bluetooth::getDefaultGattCharacteristic() -{ - GattCharacteristic characteristic = {}; - characteristic.charUuid = 0x2A19; // Battery Level Characteristic UUID - characteristic.properties = 0x12; // Read | Notify - characteristic.permissions = 0x01; // Read - characteristic.maxLen = 1; - characteristic.autoRsp = true; - return characteristic; -} - -#ifdef CONFIG_BT_ENABLED -void Bluetooth::gapEventHandler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) -{ - if (s_instance_ && s_instance_->m_gapCallback_) { - s_instance_->m_gapCallback_(event, param, s_instance_->m_gapUserData_); - } - - switch (event) { - case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: - ASF_LOGI(TAG, 2147, asf::logger::Criticality::LOW, "GAP: Advertising data set complete"); - break; - case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: - ASF_LOGI(TAG, 2148, asf::logger::Criticality::LOW, "GAP: Advertising start complete"); - break; - case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: - ASF_LOGI(TAG, 2149, asf::logger::Criticality::LOW, "GAP: Advertising stop complete"); - break; - default: - break; - } -} - -void Bluetooth::gattsEventHandler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param) -{ - if (s_instance_ && s_instance_->m_gattsCallback_) { - s_instance_->m_gattsCallback_(event, gatts_if, param, s_instance_->m_gattsUserData_); - } - - switch (event) { - case ESP_GATTS_REG_EVT: - ASF_LOGI(TAG, 2150, asf::logger::Criticality::LOW, "GATTS: Register complete"); - if (s_instance_) { - s_instance_->m_gattsIf_ = gatts_if; - } - break; - case ESP_GATTS_CONNECT_EVT: - ASF_LOGI(TAG, 2151, asf::logger::Criticality::LOW, "GATTS: Device connected"); - if (s_instance_) { - s_instance_->m_connectionState_ = BleConnectionState::CONNECTED; - s_instance_->m_connectedDeviceCount_++; - } - break; - case ESP_GATTS_DISCONNECT_EVT: - ASF_LOGI(TAG, 2152, asf::logger::Criticality::LOW, "GATTS: Device disconnected"); - if (s_instance_) { - s_instance_->m_connectionState_ = BleConnectionState::DISCONNECTED; - if (s_instance_->m_connectedDeviceCount_ > 0) { - s_instance_->m_connectedDeviceCount_--; - } - } - break; - default: - break; - } -} - -void Bluetooth::gattcEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param) -{ - if (s_instance_ && s_instance_->m_gattcCallback_) { - s_instance_->m_gattcCallback_(event, gattc_if, param, s_instance_->m_gattcUserData_); - } - - switch (event) { - case ESP_GATTC_REG_EVT: - ASF_LOGI(TAG, 2153, asf::logger::Criticality::LOW, "GATTC: Register complete"); - if (s_instance_) { - s_instance_->m_gattcIf_ = gattc_if; - } - break; - default: - break; - } -} - -esp_bt_mode_t Bluetooth::convertMode(BtMode mode) -{ - return static_cast(mode); -} - -esp_ble_adv_type_t Bluetooth::convertAdvType(BleAdvType advType) -{ - return static_cast(advType); -} -#endif - -bool Bluetooth::stopGattService(uint16_t serviceHandle) { return true; } -bool Bluetooth::sendNotification(uint16_t connId, uint16_t attrHandle, const uint8_t* data, size_t dataLen) { return true; } -bool Bluetooth::sendIndication(uint16_t connId, uint16_t attrHandle, const uint8_t* data, size_t dataLen) { return true; } -bool Bluetooth::connectToDevice(const uint8_t* remoteAddr, uint8_t addrType) { return true; } -bool Bluetooth::disconnectDevice(uint16_t connId) { return true; } -#ifdef CONFIG_BT_ENABLED -bool Bluetooth::setTxPower(esp_ble_power_type_t powerType, esp_power_level_t powerLevel) { return true; } -esp_power_level_t Bluetooth::getTxPower(esp_ble_power_type_t powerType) { return ESP_PWR_LVL_N0; } -#endif diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.hpp deleted file mode 100644 index 5c0daaa..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/com/bt.hpp +++ /dev/null @@ -1,457 +0,0 @@ -/** - * @file bt.hpp - * @brief Bluetooth wrapper component header - Wrapper for ESP-IDF Bluetooth functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef BT_HPP -#define BT_HPP - -#include -#include -#include "esp_err.h" -#include "nvs_flash.h" - -#ifdef CONFIG_BT_ENABLED -#include "esp_bt.h" -#include "esp_bt_main.h" -#include "esp_gap_ble_api.h" -#include "esp_gatts_api.h" -#include "esp_gattc_api.h" -#include "esp_bt_defs.h" -#endif - -/** - * @brief Bluetooth mode enumeration - */ -enum class BtMode -{ -#ifdef CONFIG_BT_ENABLED - CLASSIC = ESP_BT_MODE_CLASSIC_BT, - BLE = ESP_BT_MODE_BLE, - DUAL = ESP_BT_MODE_BTDM -#else - CLASSIC, - BLE, - DUAL -#endif -}; - -/** - * @brief BLE advertising type enumeration - */ -enum class BleAdvType -{ -#ifdef CONFIG_BT_ENABLED - ADV_IND = ADV_TYPE_IND, - ADV_DIRECT_IND_HIGH = ADV_TYPE_DIRECT_IND_HIGH, - ADV_SCAN_IND = ADV_TYPE_SCAN_IND, - ADV_NONCONN_IND = ADV_TYPE_NONCONN_IND, - ADV_DIRECT_IND_LOW = ADV_TYPE_DIRECT_IND_LOW -#else - ADV_IND, - ADV_DIRECT_IND_HIGH, - ADV_SCAN_IND, - ADV_NONCONN_IND, - ADV_DIRECT_IND_LOW -#endif -}; - -/** - * @brief BLE connection state enumeration - */ -enum class BleConnectionState -{ - DISCONNECTED, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -/** - * @brief BLE advertising parameters structure - */ -struct BleAdvParams -{ - uint16_t advIntMin; ///< Minimum advertising interval - uint16_t advIntMax; ///< Maximum advertising interval - BleAdvType advType; ///< Advertising type - uint8_t ownAddrType; ///< Own address type - uint8_t peerAddrType; ///< Peer address type - uint8_t peerAddr[6]; ///< Peer address - uint8_t channelMap; ///< Channel map - uint8_t advFilterPolicy; ///< Advertising filter policy -}; - -/** - * @brief BLE advertising data structure - */ -struct BleAdvData -{ - bool setName; ///< Set device name in advertising data - bool setTxPower; ///< Set TX power in advertising data - bool includeUuid; ///< Include service UUID - bool setManufacturerData; ///< Set manufacturer data - uint16_t appearance; ///< Device appearance - uint16_t manufacturerId; ///< Manufacturer ID - uint8_t manufacturerDataLen; ///< Manufacturer data length - uint8_t* manufacturerData; ///< Manufacturer data - uint8_t serviceUuidLen; ///< Service UUID length - uint8_t* serviceUuid; ///< Service UUID - char* deviceName; ///< Device name -}; - -/** - * @brief GATT service structure - */ -struct GattService -{ - uint16_t serviceId; ///< Service ID - uint16_t serviceUuid; ///< Service UUID - uint16_t numHandles; ///< Number of handles - bool isPrimary; ///< Primary service flag -}; - -/** - * @brief GATT characteristic structure - */ -struct GattCharacteristic -{ - uint16_t charUuid; ///< Characteristic UUID - uint8_t properties; ///< Characteristic properties - uint8_t permissions; ///< Characteristic permissions - uint16_t maxLen; ///< Maximum value length - bool autoRsp; ///< Auto response flag -}; - -/** - * @brief Bluetooth event callback function types - */ -#ifdef CONFIG_BT_ENABLED -using BtGapEventCallback = void (*)(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param, void* userData); -using BtGattsEventCallback = void (*)(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param, void* userData); -using BtGattcEventCallback = void (*)(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param, void* userData); -#else -using BtGapEventCallback = void (*)(int event, void* param, void* userData); -using BtGattsEventCallback = void (*)(int event, int gatts_if, void* param, void* userData); -using BtGattcEventCallback = void (*)(int event, int gattc_if, void* param, void* userData); -#endif - -/** - * @brief Bluetooth wrapper class - * - * Provides a C++ wrapper for ESP-IDF Bluetooth functionality. - * This class encapsulates ESP-IDF Bluetooth and BLE driver functions in an object-oriented interface. - */ -class Bluetooth -{ -public: - /** - * @brief Constructor - * @details Initializes the Bluetooth wrapper instance - */ - Bluetooth(); - - /** - * @brief Destructor - * @details Cleans up resources and deinitializes Bluetooth - */ - ~Bluetooth(); - - /** - * @brief Initialize Bluetooth stack - * @param mode Bluetooth mode (Classic, BLE, or Dual) - * @return true if initialized successfully, false otherwise - */ - bool initialize(BtMode mode); - - /** - * @brief Deinitialize Bluetooth stack - * @return true if deinitialized successfully, false otherwise - */ - bool deinitialize(); - - /** - * @brief Set device name - * @param name Device name (max 248 characters) - * @return true if set successfully, false otherwise - */ - bool setDeviceName(const char* name); - - /** - * @brief Get device name - * @param name Buffer to store device name - * @param maxLen Maximum length of name buffer - * @return true if retrieved successfully, false otherwise - */ - bool getDeviceName(char* name, size_t maxLen); - - /** - * @brief Set advertising parameters - * @param params Advertising parameters - * @return true if set successfully, false otherwise - */ - bool setAdvParams(const BleAdvParams& params); - - /** - * @brief Set advertising data - * @param advData Advertising data - * @return true if set successfully, false otherwise - */ - bool setAdvData(const BleAdvData& advData); - - /** - * @brief Start BLE advertising - * @return true if started successfully, false otherwise - */ - bool startAdvertising(); - - /** - * @brief Stop BLE advertising - * @return true if stopped successfully, false otherwise - */ - bool stopAdvertising(); - - /** - * @brief Start BLE scanning - * @param duration Scan duration in seconds (0 = continuous) - * @return true if started successfully, false otherwise - */ - bool startScanning(uint32_t duration = 0); - - /** - * @brief Stop BLE scanning - * @return true if stopped successfully, false otherwise - */ - bool stopScanning(); - - /** - * @brief Create GATT service - * @param service Service configuration - * @return Service handle, or 0 on failure - */ - uint16_t createGattService(const GattService& service); - - /** - * @brief Add characteristic to service - * @param serviceHandle Service handle - * @param characteristic Characteristic configuration - * @return Characteristic handle, or 0 on failure - */ - uint16_t addCharacteristic(uint16_t serviceHandle, const GattCharacteristic& characteristic); - - /** - * @brief Start GATT service - * @param serviceHandle Service handle - * @return true if started successfully, false otherwise - */ - bool startGattService(uint16_t serviceHandle); - - /** - * @brief Stop GATT service - * @param serviceHandle Service handle - * @return true if stopped successfully, false otherwise - */ - bool stopGattService(uint16_t serviceHandle); - - /** - * @brief Send notification to connected client - * @param connId Connection ID - * @param attrHandle Attribute handle - * @param data Data to send - * @param dataLen Length of data - * @return true if sent successfully, false otherwise - */ - bool sendNotification(uint16_t connId, uint16_t attrHandle, const uint8_t* data, size_t dataLen); - - /** - * @brief Send indication to connected client - * @param connId Connection ID - * @param attrHandle Attribute handle - * @param data Data to send - * @param dataLen Length of data - * @return true if sent successfully, false otherwise - */ - bool sendIndication(uint16_t connId, uint16_t attrHandle, const uint8_t* data, size_t dataLen); - - /** - * @brief Connect to remote device - * @param remoteAddr Remote device address - * @param addrType Address type - * @return true if connection initiated successfully, false otherwise - */ - bool connectToDevice(const uint8_t* remoteAddr, uint8_t addrType); - - /** - * @brief Disconnect from remote device - * @param connId Connection ID - * @return true if disconnection initiated successfully, false otherwise - */ - bool disconnectDevice(uint16_t connId); - - /** - * @brief Get connection state - * @return Current connection state - */ - BleConnectionState getConnectionState() const; - - /** - * @brief Check if device is connected - * @return true if connected, false otherwise - */ - bool isConnected() const; - - /** - * @brief Get number of connected devices - * @return Number of connected devices - */ - uint8_t getConnectedDeviceCount() const; - - /** - * @brief Set GAP event callback - * @param callback Callback function - * @param userData User data passed to callback - */ - void setGapEventCallback(BtGapEventCallback callback, void* userData); - - /** - * @brief Set GATTS event callback - * @param callback Callback function - * @param userData User data passed to callback - */ - void setGattsEventCallback(BtGattsEventCallback callback, void* userData); - - /** - * @brief Set GATTC event callback - * @param callback Callback function - * @param userData User data passed to callback - */ - void setGattcEventCallback(BtGattcEventCallback callback, void* userData); - - /** - * @brief Get MAC address - * @param mac Buffer to store MAC address (6 bytes) - * @return true if retrieved successfully, false otherwise - */ - bool getMacAddress(uint8_t* mac); - - /** - * @brief Set TX power - * @param powerType Power type - * @param powerLevel Power level - * @return true if set successfully, false otherwise - */ -#ifdef CONFIG_BT_ENABLED - bool setTxPower(esp_ble_power_type_t powerType, esp_power_level_t powerLevel); -#endif - - /** - * @brief Get TX power - * @param powerType Power type - * @return Current power level, or ESP_PWR_LVL_INVALID on error - */ -#ifdef CONFIG_BT_ENABLED - esp_power_level_t getTxPower(esp_ble_power_type_t powerType); -#endif - - /** - * @brief Check if Bluetooth is initialized - * @return true if initialized, false otherwise - */ - bool isInitialized() const; - - /** - * @brief Get default advertising parameters - * @return Default BLE advertising parameters - */ - static BleAdvParams getDefaultAdvParams(); - - /** - * @brief Get default advertising data - * @return Default BLE advertising data - */ - static BleAdvData getDefaultAdvData(); - - /** - * @brief Get default GATT service configuration - * @return Default GATT service configuration - */ - static GattService getDefaultGattService(); - - /** - * @brief Get default GATT characteristic configuration - * @return Default GATT characteristic configuration - */ - static GattCharacteristic getDefaultGattCharacteristic(); - -private: - bool m_isInitialized_; ///< Initialization status - BtMode m_mode_; ///< Bluetooth mode - BleConnectionState m_connectionState_; ///< Current connection state - uint8_t m_connectedDeviceCount_; ///< Number of connected devices -#ifdef CONFIG_BT_ENABLED - esp_gatt_if_t m_gattsIf_; ///< GATTS interface - esp_gatt_if_t m_gattcIf_; ///< GATTC interface -#else - int m_gattsIf_; - int m_gattcIf_; -#endif - uint16_t m_appId_; ///< Application ID - - // Callback functions and user data - BtGapEventCallback m_gapCallback_; ///< GAP event callback - void* m_gapUserData_; ///< GAP callback user data - BtGattsEventCallback m_gattsCallback_; ///< GATTS event callback - void* m_gattsUserData_; ///< GATTS callback user data - BtGattcEventCallback m_gattcCallback_; ///< GATTC event callback - void* m_gattcUserData_; ///< GATTC callback user data - -#ifdef CONFIG_BT_ENABLED - /** - * @brief GAP event handler - * @param event GAP event - * @param param Event parameters - */ - static void gapEventHandler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); - - /** - * @brief GATTS event handler - * @param event GATTS event - * @param gatts_if GATTS interface - * @param param Event parameters - */ - static void gattsEventHandler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param); - - /** - * @brief GATTC event handler - * @param event GATTC event - * @param gattc_if GATTC interface - * @param param Event parameters - */ - static void gattcEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param); -#endif - - /** - * @brief Convert BtMode to ESP-IDF esp_bt_mode_t - * @param mode Bluetooth mode - * @return ESP-IDF bluetooth mode - */ -#ifdef CONFIG_BT_ENABLED - esp_bt_mode_t convertMode(BtMode mode); -#endif - - /** - * @brief Convert BleAdvType to ESP-IDF esp_ble_adv_type_t - * @param advType Advertising type - * @return ESP-IDF advertising type - */ -#ifdef CONFIG_BT_ENABLED - esp_ble_adv_type_t convertAdvType(BleAdvType advType); -#endif - - static Bluetooth* s_instance_; ///< Static instance for callbacks -}; - -#endif // BT_HPP diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/logging_data.csv deleted file mode 100644 index e6f6148..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/logging_data.csv +++ /dev/null @@ -1,55 +0,0 @@ -ID,Component,Level,Criticality,Message -2100,BT,INFO,Low,Bluetooth wrapper initialized -2101,BT,INFO,Low,Bluetooth wrapper destroyed -2102,BT,WARNING,Medium,Bluetooth already initialized -2103,BT,ERROR,High,Failed to initialize BT controller: %s -2104,BT,ERROR,High,Failed to enable BT controller: %s -2105,BT,ERROR,High,Failed to initialize Bluedroid: %s -2106,BT,ERROR,High,Failed to enable Bluedroid: %s -2107,BT,ERROR,High,Failed to register GAP callback: %s -2108,BT,ERROR,High,Failed to register GATTS callback: %s -2109,BT,ERROR,High,Failed to register GATTC callback: %s -2110,BT,INFO,Low,Bluetooth initialized successfully -2111,BT,WARNING,Medium,Bluetooth disabled in sdkconfig -2112,BT,WARNING,Medium,Bluetooth not initialized -2113,BT,ERROR,High,Failed to disable Bluedroid: %s -2114,BT,ERROR,High,Failed to deinitialize Bluedroid: %s -2115,BT,ERROR,High,Failed to disable BT controller: %s -2116,BT,ERROR,High,Failed to deinitialize BT controller: %s -2117,BT,INFO,Low,Bluetooth deinitialized -2118,BT,ERROR,High,Bluetooth not initialized or invalid name -2119,BT,ERROR,High,Failed to set device name: %s -2120,BT,INFO,Low,Device name set to: %s -2121,BT,ERROR,High,Bluetooth not initialized -2122,BT,ERROR,High,Failed to set advertising parameters: %s -2123,BT,INFO,Low,Advertising parameters set successfully -2124,BT,ERROR,High,Bluetooth not initialized -2125,BT,ERROR,High,Failed to set advertising data: %s -2126,BT,INFO,Low,Advertising data set successfully -2127,BT,ERROR,High,Bluetooth not initialized -2128,BT,ERROR,High,Failed to start advertising: %s -2129,BT,INFO,Low,BLE advertising started -2130,BT,WARNING,Medium,Bluetooth not initialized -2131,BT,ERROR,High,Failed to stop advertising: %s -2132,BT,INFO,Low,BLE advertising stopped -2133,BT,ERROR,High,Bluetooth not initialized -2134,BT,ERROR,High,Failed to set scan parameters: %s -2135,BT,ERROR,High,Failed to start scanning: %s -2136,BT,INFO,Low,BLE scanning started (duration: %lu seconds) -2137,BT,WARNING,Medium,Bluetooth not initialized -2138,BT,ERROR,High,Failed to stop scanning: %s -2139,BT,INFO,Low,BLE scanning stopped -2140,BT,ERROR,High,Bluetooth not initialized -2141,BT,ERROR,High,Failed to create GATT service: %s -2142,BT,INFO,Low,GATT service created successfully -2143,BT,ERROR,High,Bluetooth not initialized -2144,BT,ERROR,High,Failed to start GATT service: %s -2145,BT,INFO,Low,GATT service started successfully -2146,BT,ERROR,High,Invalid MAC address buffer -2147,BT,INFO,Low,GAP: Advertising data set complete -2148,BT,INFO,Low,GAP: Advertising start complete -2149,BT,INFO,Low,GAP: Advertising stop complete -2150,BT,INFO,Low,GATTS: Register complete -2151,BT,INFO,Low,GATTS: Device connected -2152,BT,INFO,Low,GATTS: Device disconnected -2153,BT,INFO,Low,GATTC: Register complete diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/bt_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/bt_init_test.py deleted file mode 100644 index d7e6d55..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/bt_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_bt_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Bluetooth initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_bt_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/test_bt.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/test_bt.cpp deleted file mode 100644 index 3d01cd7..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/bt/test/test_bt.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file test_bt.cpp - * @brief Unit tests for Bluetooth wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "bt.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_bt_initialize(void) -{ - Bluetooth bt; - bool result = bt.initialize(BtMode::BLE); - TEST_ASSERT_TRUE(result); -} - -void test_bt_start_advertising(void) -{ - Bluetooth bt; - bt.initialize(BtMode::BLE); - - bool result = bt.startAdvertising(); - TEST_ASSERT_TRUE(result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/CMakeLists.txt deleted file mode 100644 index 5ce5272..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/dma.cpp" - INCLUDE_DIRS "com" - REQUIRES driver esp_hw_support logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/README.md deleted file mode 100644 index 8e194c2..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/README.md +++ /dev/null @@ -1,396 +0,0 @@ -# DMA Wrapper Module - -## Overview - -The DMA wrapper module provides a C++ object-oriented interface for ESP-IDF GDMA (General DMA) functionality. This module encapsulates the ESP-IDF GDMA driver functions and provides a clean, easy-to-use API for high-performance data transfers between memory and peripherals. - -## Features - -- **Channel Management**: Dynamic allocation and deallocation of DMA channels -- **Memory Management**: DMA-capable memory allocation and management -- **Descriptor Management**: Creation and linking of DMA descriptors -- **Transfer Control**: Start, stop, and reset DMA transfers -- **Callback Support**: Event-driven callbacks for transfer completion -- **Memory Copy**: High-performance DMA-based memory copy operations -- **Error Handling**: Comprehensive error checking and logging - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ Dma │ -├─────────────────────────────────────┤ -│ - m_channels_[8]: gdma_handle_t │ -│ - m_channelAllocated_[8]: bool │ -├─────────────────────────────────────┤ -│ + Dma() │ -│ + ~Dma() │ -│ + allocateChannel(cfg, hdl): bool │ -│ + deallocateChannel(hdl): bool │ -│ + configureTransfer(hdl, cfg): bool │ -│ + startTransfer(hdl): bool │ -│ + stopTransfer(hdl): bool │ -│ + resetChannel(hdl): bool │ -│ + allocateDmaMemory(size): void* │ -│ + freeDmaMemory(ptr): void │ -│ + createDescriptor(...): Desc* │ -│ + linkDescriptors(d1, d2): bool │ -│ + freeDescriptor(desc): void │ -│ + setCallback(hdl, cb, arg): bool │ -│ + enableChannel(hdl): bool │ -│ + disableChannel(hdl): bool │ -│ + getChannelState(hdl): State │ -│ + memcpy(dst, src, size): bool │ -│ + getDefaultChannelConfig(): Config │ -│ + getDefaultTransferConfig(): Config│ -│ + isDmaCapable(addr): bool │ -│ - findFreeChannelSlot(): int │ -│ - findChannelSlot(hdl): int │ -│ - convertDirection(dir): gdma_dir │ -│ - convertPriority(pri): int │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### DmaDirection -- `MEM_TO_MEM`: Memory to memory transfer -- `MEM_TO_PERIPH`: Memory to peripheral transfer -- `PERIPH_TO_MEM`: Peripheral to memory transfer -- `PERIPH_TO_PERIPH`: Peripheral to peripheral transfer - -#### DmaTransferType -- `SINGLE`: Single transfer -- `BLOCK`: Block transfer -- `LINKED_LIST`: Linked list transfer - -#### DmaPriority -- `LOW`: Low priority (0) -- `MEDIUM`: Medium priority (1) -- `HIGH`: High priority (2) -- `HIGHEST`: Highest priority (3) - -### Configuration Structures - -#### DmaChannelConfig -```cpp -struct DmaChannelConfig { - DmaPriority priority; // Channel priority - uint32_t flags; // Configuration flags -}; -``` - -#### DmaTransferConfig -```cpp -struct DmaTransferConfig { - void* srcAddr; // Source address - void* dstAddr; // Destination address - size_t dataSize; // Size of data to transfer - DmaDirection direction; // Transfer direction - DmaTransferType type; // Transfer type - DmaPriority priority; // Transfer priority - bool autoReload; // Auto-reload mode - bool enableInterrupt; // Enable transfer complete interrupt -}; -``` - -#### DmaDescriptor -```cpp -struct DmaDescriptor { - uint32_t size; // Size of data to transfer - uint32_t length; // Actual length of valid data - uint32_t sosf : 1; // Start of sub-frame - uint32_t eof : 1; // End of frame - uint32_t owner : 1; // Owner (0: CPU, 1: DMA) - uint32_t reserved : 29; // Reserved bits - void* buffer; // Pointer to data buffer - DmaDescriptor* next; // Pointer to next descriptor -}; -``` - -## Usage Examples - -### Basic DMA Channel Allocation - -```cpp -#include "dma.hpp" - -// DMA transfer completion callback -void dmaCallback(gdma_channel_handle_t channel, gdma_event_data_t* eventData, void* userData) { - printf("DMA transfer completed!\n"); -} - -// Create DMA instance -Dma dma; - -// Allocate DMA channel -DmaChannelConfig config = Dma::getDefaultChannelConfig(); -config.priority = DmaPriority::HIGH; - -gdma_channel_handle_t channel; -dma.allocateChannel(config, &channel); - -// Set callback -dma.setCallback(channel, dmaCallback, nullptr); -``` - -### Memory-to-Memory Transfer - -```cpp -// Allocate DMA-capable memory -size_t dataSize = 1024; -void* srcBuffer = dma.allocateDmaMemory(dataSize); -void* dstBuffer = dma.allocateDmaMemory(dataSize); - -// Fill source buffer with test data -memset(srcBuffer, 0xAA, dataSize); - -// Perform DMA copy -bool success = dma.memcpy(dstBuffer, srcBuffer, dataSize, channel); - -if (success) { - printf("DMA copy completed successfully\n"); -} - -// Clean up -dma.freeDmaMemory(srcBuffer); -dma.freeDmaMemory(dstBuffer); -dma.deallocateChannel(channel); -``` - -### Descriptor-Based Transfer - -```cpp -// Create source and destination buffers -uint8_t* srcData = (uint8_t*)dma.allocateDmaMemory(512); -uint8_t* dstData = (uint8_t*)dma.allocateDmaMemory(512); - -// Fill source with test pattern -for (int i = 0; i < 512; i++) { - srcData[i] = i & 0xFF; -} - -// Create DMA descriptors -DmaDescriptor* desc1 = dma.createDescriptor(srcData, 256, false); -DmaDescriptor* desc2 = dma.createDescriptor(srcData + 256, 256, true); - -// Link descriptors for chained transfer -dma.linkDescriptors(desc1, desc2); - -// Configure and start transfer -DmaTransferConfig transferConfig = Dma::getDefaultTransferConfig(); -transferConfig.srcAddr = srcData; -transferConfig.dstAddr = dstData; -transferConfig.dataSize = 512; -transferConfig.direction = DmaDirection::MEM_TO_MEM; - -dma.configureTransfer(channel, transferConfig); -dma.startTransfer(channel); - -// Wait for completion (in real application, use callback) -// ... - -// Clean up descriptors -dma.freeDescriptor(desc1); -dma.freeDescriptor(desc2); -``` - -### Large Data Transfer with Chunking - -```cpp -void transferLargeData(Dma& dma, void* src, void* dst, size_t totalSize) { - const size_t chunkSize = 4096; // 4KB chunks - size_t remaining = totalSize; - uint8_t* srcPtr = (uint8_t*)src; - uint8_t* dstPtr = (uint8_t*)dst; - - gdma_channel_handle_t channel; - DmaChannelConfig config = Dma::getDefaultChannelConfig(); - dma.allocateChannel(config, &channel); - - while (remaining > 0) { - size_t currentChunk = (remaining > chunkSize) ? chunkSize : remaining; - - // Perform DMA transfer for current chunk - bool success = dma.memcpy(dstPtr, srcPtr, currentChunk, channel); - - if (!success) { - printf("DMA transfer failed for chunk\n"); - break; - } - - srcPtr += currentChunk; - dstPtr += currentChunk; - remaining -= currentChunk; - - printf("Transferred %zu bytes, %zu remaining\n", currentChunk, remaining); - } - - dma.deallocateChannel(channel); -} -``` - -### Peripheral-to-Memory Transfer - -```cpp -// Example: DMA transfer from SPI peripheral to memory -void setupSpiDmaTransfer(Dma& dma) { - // Allocate receive buffer - uint8_t* rxBuffer = (uint8_t*)dma.allocateDmaMemory(1024); - - // Allocate DMA channel - gdma_channel_handle_t channel; - DmaChannelConfig config = Dma::getDefaultChannelConfig(); - dma.allocateChannel(config, &channel); - - // Configure transfer from SPI to memory - DmaTransferConfig transferConfig = {}; - transferConfig.srcAddr = nullptr; // Will be set by SPI driver - transferConfig.dstAddr = rxBuffer; - transferConfig.dataSize = 1024; - transferConfig.direction = DmaDirection::PERIPH_TO_MEM; - transferConfig.enableInterrupt = true; - - dma.configureTransfer(channel, transferConfig); - - // SPI driver would typically handle the actual peripheral configuration - // and trigger the DMA transfer - - // Clean up when done - dma.freeDmaMemory(rxBuffer); - dma.deallocateChannel(channel); -} -``` - -## API Reference - -### Constructor/Destructor - -- **Dma()**: Initialize DMA wrapper instance -- **~Dma()**: Clean up resources and deallocate all channels - -### Channel Management - -- **allocateChannel(config, handle)**: Allocate DMA channel -- **deallocateChannel(handle)**: Deallocate DMA channel -- **enableChannel(handle)**: Enable DMA channel -- **disableChannel(handle)**: Disable DMA channel -- **resetChannel(handle)**: Reset DMA channel -- **getChannelState(handle)**: Get current channel state - -### Transfer Control - -- **configureTransfer(handle, config)**: Configure DMA transfer -- **startTransfer(handle)**: Start DMA transfer -- **stopTransfer(handle)**: Stop DMA transfer - -### Memory Management - -- **allocateDmaMemory(size, caps)**: Allocate DMA-capable memory -- **freeDmaMemory(ptr)**: Free DMA-capable memory -- **isDmaCapable(addr)**: Check if address is DMA-capable - -### Descriptor Management - -- **createDescriptor(buffer, size, eof)**: Create DMA descriptor -- **linkDescriptors(desc1, desc2)**: Link two descriptors -- **freeDescriptor(descriptor)**: Free DMA descriptor - -### Callback and Events - -- **setCallback(handle, callback, userData)**: Set transfer completion callback - -### Utility Methods - -- **memcpy(dst, src, size, handle)**: High-performance DMA memory copy -- **getDefaultChannelConfig()**: Get default channel configuration -- **getDefaultTransferConfig()**: Get default transfer configuration - -## Error Handling - -The module provides comprehensive error handling: -- Channel handle validation -- Memory allocation checks -- ESP-IDF error codes are caught and logged -- Return values indicate success/failure for all operations -- Automatic cleanup of allocated resources - -## Dependencies - -- ESP-IDF GDMA driver (`driver/gdma.h`) -- ESP-IDF DMA utilities (`esp_dma_utils.h`) -- ESP-IDF hardware support (`esp_hw_support`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) -- ESP-IDF heap capabilities (`esp_heap_caps.h`) - -## Thread Safety - -The DMA wrapper uses ESP-IDF's thread-safe GDMA driver. Multiple tasks can safely use different DMA channels simultaneously. - -## Memory Usage - -- Fixed memory footprint per instance -- Channel handles stored in fixed-size array -- DMA descriptors allocated from DMA-capable memory -- No hidden dynamic allocations - -## Performance Considerations - -- Direct ESP-IDF GDMA calls for optimal performance -- DMA transfers are asynchronous and non-blocking -- Use callbacks for transfer completion notification -- DMA-capable memory required for source/destination buffers -- Descriptor chaining for large transfers - -## DMA Memory Requirements - -### DMA-Capable Memory -- Source and destination buffers must be in DMA-capable memory -- Use `allocateDmaMemory()` or `MALLOC_CAP_DMA` flag -- Check memory capability with `isDmaCapable()` - -### Memory Alignment -- Some transfers may require specific alignment -- Descriptors must be in DMA-capable memory -- Buffer addresses should be word-aligned for best performance - -## Limitations - -- Maximum 8 DMA channels can be managed simultaneously -- Memory buffers must be DMA-capable -- Transfer size limitations depend on ESP32 variant -- Some peripherals have specific DMA requirements -- Descriptor chains limited by available DMA memory - -## Use Cases - -### High-Speed Data Transfer -- Large memory copies -- Image processing -- Audio/video streaming -- Network packet processing - -### Peripheral Integration -- SPI high-speed transfers -- I2S audio streaming -- UART bulk data transfer -- ADC continuous sampling - -### Background Processing -- Asynchronous data movement -- Buffer management -- Real-time data streaming -- Multi-buffer ping-pong operations - -## Troubleshooting - -### Common Issues - -1. **Memory Allocation Failures**: Ensure sufficient DMA-capable memory -2. **Transfer Failures**: Check buffer alignment and DMA capability -3. **Performance Issues**: Use appropriate transfer sizes and descriptor chaining -4. **Channel Exhaustion**: Monitor channel allocation and deallocation -5. **Callback Issues**: Ensure callback functions are in IRAM for interrupt context \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.cpp deleted file mode 100644 index 253f387..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/** - * @file dma.cpp - * @brief DMA wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "dma.hpp" -#include "logger.hpp" -#include "esp_memory_utils.h" -#include - -static const char* TAG = "DMA_WRAPPER"; - -Dma::Dma() -{ - // Initialize channel handles and allocation status - memset(m_channels_, 0, sizeof(m_channels_)); - memset(m_channelAllocated_, false, sizeof(m_channelAllocated_)); - ASF_LOGI(TAG, 2200, asf::logger::Criticality::LOW, "DMA wrapper initialized"); -} - -Dma::~Dma() -{ - // Deallocate all channels - for (int i = 0; i < MAX_CHANNELS; i++) { - if (m_channelAllocated_[i]) { - deallocateChannel(m_channels_[i]); - } - } - ASF_LOGI(TAG, 2201, asf::logger::Criticality::LOW, "DMA wrapper destroyed"); -} - -bool Dma::initialize(DmaChannel channel, const DmaConfig& config) -{ - ASF_LOGI(TAG, 2202, asf::logger::Criticality::LOW, "DMA initialized successfully"); - return true; -} - -#if SOC_GDMA_SUPPORTED -bool Dma::allocateChannel(const DmaChannelConfig& config, gdma_channel_handle_t* channelHandle) -#else -bool Dma::allocateChannel(const DmaChannelConfig& config, void** channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2203, asf::logger::Criticality::HIGH, "Invalid channel handle pointer"); - return false; - } - - int slotIndex = findFreeChannelSlot(); - if (slotIndex < 0) { - ASF_LOGE(TAG, 2204, asf::logger::Criticality::HIGH, "No free channel slots available"); - return false; - } - -#if SOC_GDMA_SUPPORTED - gdma_channel_alloc_config_t allocConfig = {}; - allocConfig.direction = GDMA_CHANNEL_DIRECTION_TX; // Default to TX, can be changed later - allocConfig.flags.reserve_sibling = 0; - - esp_err_t ret = gdma_new_channel(&allocConfig, channelHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2205, asf::logger::Criticality::HIGH, "Failed to allocate DMA channel: %s", esp_err_to_name(ret)); - return false; - } - - m_channels_[slotIndex] = *channelHandle; - m_channelAllocated_[slotIndex] = true; - - ASF_LOGI(TAG, 2206, asf::logger::Criticality::LOW, "DMA channel allocated successfully (slot %d)", slotIndex); - return true; -#else - ASF_LOGW(TAG, 2207, asf::logger::Criticality::MEDIUM, "GDMA not supported on this target"); - return false; -#endif -} - -#if SOC_GDMA_SUPPORTED -bool Dma::deallocateChannel(gdma_channel_handle_t channelHandle) -#else -bool Dma::deallocateChannel(void* channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2208, asf::logger::Criticality::HIGH, "Invalid channel handle"); - return false; - } - - int slotIndex = findChannelSlot(channelHandle); - if (slotIndex < 0) { - ASF_LOGE(TAG, 2209, asf::logger::Criticality::HIGH, "Channel handle not found"); - return false; - } - -#if SOC_GDMA_SUPPORTED - esp_err_t ret = gdma_del_channel(channelHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2210, asf::logger::Criticality::HIGH, "Failed to deallocate DMA channel: %s", esp_err_to_name(ret)); - return false; - } - - m_channels_[slotIndex] = nullptr; - m_channelAllocated_[slotIndex] = false; - - ASF_LOGI(TAG, 2211, asf::logger::Criticality::LOW, "DMA channel deallocated successfully (slot %d)", slotIndex); - return true; -#else - return false; -#endif -} - -#if SOC_GDMA_SUPPORTED -bool Dma::configureTransfer(gdma_channel_handle_t channelHandle, const DmaTransferConfig& config) -#else -bool Dma::configureTransfer(void* channelHandle, const DmaTransferConfig& config) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2212, asf::logger::Criticality::HIGH, "Invalid channel handle"); - return false; - } - - // Configure transfer based on direction - switch (config.direction) { - case DmaDirection::MEM_TO_MEM: - // Memory to memory transfer configuration - break; - case DmaDirection::MEM_TO_PERIPH: - // Memory to peripheral transfer configuration - break; - case DmaDirection::PERIPH_TO_MEM: - // Peripheral to memory transfer configuration - break; - case DmaDirection::PERIPH_TO_PERIPH: - // Peripheral to peripheral transfer configuration - break; - } - - ASF_LOGI(TAG, 2213, asf::logger::Criticality::LOW, "DMA transfer configured successfully"); - return true; -} - -#if SOC_GDMA_SUPPORTED -bool Dma::startTransfer(gdma_channel_handle_t channelHandle) -#else -bool Dma::startTransfer(void* channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2214, asf::logger::Criticality::HIGH, "Invalid channel handle"); - return false; - } - -#if SOC_GDMA_SUPPORTED - esp_err_t ret = gdma_start(channelHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2215, asf::logger::Criticality::HIGH, "Failed to start DMA transfer: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2216, asf::logger::Criticality::LOW, "DMA transfer started successfully"); - return true; -#else - return false; -#endif -} - -#if SOC_GDMA_SUPPORTED -bool Dma::stopTransfer(gdma_channel_handle_t channelHandle) -#else -bool Dma::stopTransfer(void* channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2217, asf::logger::Criticality::HIGH, "Invalid channel handle"); - return false; - } - -#if SOC_GDMA_SUPPORTED - esp_err_t ret = gdma_stop(channelHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2218, asf::logger::Criticality::HIGH, "Failed to stop DMA transfer: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2219, asf::logger::Criticality::LOW, "DMA transfer stopped successfully"); - return true; -#else - return false; -#endif -} - -#if SOC_GDMA_SUPPORTED -bool Dma::resetChannel(gdma_channel_handle_t channelHandle) -#else -bool Dma::resetChannel(void* channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2220, asf::logger::Criticality::HIGH, "Invalid channel handle"); - return false; - } - -#if SOC_GDMA_SUPPORTED - esp_err_t ret = gdma_reset(channelHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2221, asf::logger::Criticality::HIGH, "Failed to reset DMA channel: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2222, asf::logger::Criticality::LOW, "DMA channel reset successfully"); - return true; -#else - return false; -#endif -} - -void* Dma::allocateDmaMemory(size_t size, uint32_t caps) -{ - void* ptr = heap_caps_malloc(size, caps); - if (ptr == nullptr) { - ASF_LOGE(TAG, 2223, asf::logger::Criticality::HIGH, "Failed to allocate DMA memory of size %zu", size); - return nullptr; - } - - ASF_LOGI(TAG, 2224, asf::logger::Criticality::LOW, "DMA memory allocated: %zu bytes at %p", size, ptr); - return ptr; -} - -void Dma::freeDmaMemory(void* ptr) -{ - if (ptr != nullptr) { - heap_caps_free(ptr); - ASF_LOGI(TAG, 2225, asf::logger::Criticality::LOW, "DMA memory freed at %p", ptr); - } -} - -DmaDescriptor* Dma::createDescriptor(void* buffer, size_t size, bool eof) -{ - if (buffer == nullptr || size == 0) { - ASF_LOGE(TAG, 2226, asf::logger::Criticality::HIGH, "Invalid buffer or size for descriptor"); - return nullptr; - } - - DmaDescriptor* desc = static_cast( - heap_caps_malloc(sizeof(DmaDescriptor), MALLOC_CAP_DMA)); - - if (desc == nullptr) { - ASF_LOGE(TAG, 2227, asf::logger::Criticality::HIGH, "Failed to allocate DMA descriptor"); - return nullptr; - } - - desc->size = size; - desc->length = size; - desc->sosf = 0; - desc->eof = eof ? 1 : 0; - desc->owner = 1; // DMA owns the descriptor - desc->reserved = 0; - desc->buffer = buffer; - desc->next = nullptr; - - ASF_LOGI(TAG, 2228, asf::logger::Criticality::LOW, "DMA descriptor created: size=%zu, eof=%d", size, eof); - return desc; -} - -bool Dma::linkDescriptors(DmaDescriptor* desc1, DmaDescriptor* desc2) -{ - if (desc1 == nullptr || desc2 == nullptr) { - ASF_LOGE(TAG, 2229, asf::logger::Criticality::HIGH, "Invalid descriptors for linking"); - return false; - } - - desc1->next = desc2; - desc1->eof = 0; // Not end of frame since there's a next descriptor - - ASF_LOGI(TAG, 2230, asf::logger::Criticality::LOW, "DMA descriptors linked successfully"); - return true; -} - -void Dma::freeDescriptor(DmaDescriptor* descriptor) -{ - if (descriptor != nullptr) { - heap_caps_free(descriptor); - ASF_LOGI(TAG, 2231, asf::logger::Criticality::LOW, "DMA descriptor freed"); - } -} - -#if SOC_GDMA_SUPPORTED -bool Dma::setCallback(gdma_channel_handle_t channelHandle, DmaCallback callback, void* userData) -#else -bool Dma::setCallback(void* channelHandle, DmaCallback callback, void* userData) -#endif -{ - if (channelHandle == nullptr || callback == nullptr) { - ASF_LOGE(TAG, 2232, asf::logger::Criticality::HIGH, "Invalid channel handle or callback"); - return false; - } - -#if SOC_GDMA_SUPPORTED - gdma_event_callbacks_t callbacks = {}; - callbacks.on_trans_eof = callback; - - esp_err_t ret = gdma_register_event_callbacks(channelHandle, &callbacks, userData); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2233, asf::logger::Criticality::HIGH, "Failed to set DMA callback: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2234, asf::logger::Criticality::LOW, "DMA callback set successfully"); - return true; -#else - return false; -#endif -} - -#if SOC_GDMA_SUPPORTED -bool Dma::enableChannel(gdma_channel_handle_t channelHandle) -#else -bool Dma::enableChannel(void* channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2235, asf::logger::Criticality::HIGH, "Invalid channel handle"); - return false; - } - -#if SOC_GDMA_SUPPORTED - esp_err_t ret = gdma_start(channelHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2236, asf::logger::Criticality::HIGH, "Failed to enable DMA channel: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2237, asf::logger::Criticality::LOW, "DMA channel enabled successfully"); - return true; -#else - return false; -#endif -} - -#if SOC_GDMA_SUPPORTED -bool Dma::disableChannel(gdma_channel_handle_t channelHandle) -#else -bool Dma::disableChannel(void* channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2238, asf::logger::Criticality::HIGH, "Invalid channel handle"); - return false; - } - -#if SOC_GDMA_SUPPORTED - esp_err_t ret = gdma_stop(channelHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2239, asf::logger::Criticality::HIGH, "Failed to disable DMA channel: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2240, asf::logger::Criticality::LOW, "DMA channel disabled successfully"); - return true; -#else - return false; -#endif -} - -#if SOC_GDMA_SUPPORTED -gdma_channel_state_t Dma::getChannelState(gdma_channel_handle_t channelHandle) -#else -int Dma::getChannelState(void* channelHandle) -#endif -{ - if (channelHandle == nullptr) { - ASF_LOGE(TAG, 2241, asf::logger::Criticality::HIGH, "Invalid channel handle"); -#if SOC_GDMA_SUPPORTED - return GDMA_CHANNEL_STATE_INVALID; -#else - return -1; -#endif - } - - // Note: ESP-IDF doesn't provide a direct API to get channel state - // This would need to be implemented by reading hardware registers -#if SOC_GDMA_SUPPORTED - return GDMA_CHANNEL_STATE_IDLE; -#else - return 0; -#endif -} - -#if SOC_GDMA_SUPPORTED -bool Dma::memcpy(void* dst, const void* src, size_t size, gdma_channel_handle_t channelHandle) -#else -bool Dma::memcpy(void* dst, const void* src, size_t size, void* channelHandle) -#endif -{ - if (dst == nullptr || src == nullptr || size == 0) { - ASF_LOGE(TAG, 2242, asf::logger::Criticality::HIGH, "Invalid parameters for DMA memcpy"); - return false; - } - -#if SOC_GDMA_SUPPORTED - bool allocatedChannel = false; - gdma_channel_handle_t channel = channelHandle; - - // Allocate channel if not provided - if (channel == nullptr) { - DmaChannelConfig config = getDefaultChannelConfig(); - if (!allocateChannel(config, &channel)) { - return false; - } - allocatedChannel = true; - } - - // Perform DMA copy using ESP-IDF DMA utilities - // Note: This implementation is a placeholder, actual GDMA memcpy requires descriptors - ::memcpy(dst, src, size); - esp_err_t ret = ESP_OK; - - // Clean up if we allocated the channel - if (allocatedChannel) { - deallocateChannel(channel); - } - - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2243, asf::logger::Criticality::HIGH, "DMA memcpy failed: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2244, asf::logger::Criticality::LOW, "DMA memcpy completed: %zu bytes", size); - return true; -#else - // Fallback to standard memcpy if GDMA not supported - ::memcpy(dst, src, size); - return true; -#endif -} - -DmaChannelConfig Dma::getDefaultChannelConfig() -{ - DmaChannelConfig config = {}; - config.priority = DmaPriority::MEDIUM; - config.flags = 0; - return config; -} - -DmaTransferConfig Dma::getDefaultTransferConfig() -{ - DmaTransferConfig config = {}; - config.srcAddr = nullptr; - config.dstAddr = nullptr; - config.dataSize = 0; - config.direction = DmaDirection::MEM_TO_MEM; - config.type = DmaTransferType::SINGLE; - config.priority = DmaPriority::MEDIUM; - config.autoReload = false; - config.enableInterrupt = false; - return config; -} - -bool Dma::isDmaCapable(const void* addr) -{ - return esp_ptr_dma_capable(addr); -} - -int Dma::findFreeChannelSlot() -{ - for (int i = 0; i < MAX_CHANNELS; i++) { - if (!m_channelAllocated_[i]) { - return i; - } - } - return -1; -} - -#if SOC_GDMA_SUPPORTED -int Dma::findChannelSlot(gdma_channel_handle_t channelHandle) -#else -int Dma::findChannelSlot(void* channelHandle) -#endif -{ - for (int i = 0; i < MAX_CHANNELS; i++) { - if (m_channelAllocated_[i] && m_channels_[i] == channelHandle) { - return i; - } - } - return -1; -} - -#if SOC_GDMA_SUPPORTED -gdma_transfer_ability_t Dma::convertDirection(DmaDirection direction) -{ - switch (direction) { - case DmaDirection::MEM_TO_MEM: - return GDMA_TRANSFER_ABILITY_MEM; - case DmaDirection::MEM_TO_PERIPH: - return GDMA_TRANSFER_ABILITY_MEM; - case DmaDirection::PERIPH_TO_MEM: - return GDMA_TRANSFER_ABILITY_MEM; - case DmaDirection::PERIPH_TO_PERIPH: - return GDMA_TRANSFER_ABILITY_MEM; - default: - return GDMA_TRANSFER_ABILITY_MEM; - } -} -#endif - -int Dma::convertPriority(DmaPriority priority) -{ - return static_cast(priority); -} diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.hpp deleted file mode 100644 index 48bcc60..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/com/dma.hpp +++ /dev/null @@ -1,386 +0,0 @@ -/** - * @file dma.hpp - * @brief DMA wrapper component header - Wrapper for ESP-IDF DMA functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef DMA_HPP -#define DMA_HPP - -#include -#include "esp_dma_utils.h" -#include "esp_err.h" -#include "esp_heap_caps.h" -#include "soc/soc_caps.h" - -#if SOC_GDMA_SUPPORTED -#include "soc/gdma_struct.h" -#include "hal/gdma_ll.h" -#include "driver/gdma.h" -#endif - -/** - * @brief DMA transfer direction enumeration - */ -enum class DmaDirection -{ - MEM_TO_MEM, ///< Memory to memory transfer - MEM_TO_PERIPH, ///< Memory to peripheral transfer - PERIPH_TO_MEM, ///< Peripheral to memory transfer - PERIPH_TO_PERIPH ///< Peripheral to peripheral transfer -}; - -/** - * @brief DMA transfer type enumeration - */ -enum class DmaTransferType -{ - SINGLE, ///< Single transfer - BLOCK, ///< Block transfer - LINKED_LIST ///< Linked list transfer -}; - -/** - * @brief DMA priority enumeration - */ -enum class DmaPriority -{ - LOW = 0, - MEDIUM = 1, - HIGH = 2, - HIGHEST = 3 -}; - -/** - * @brief DMA channel enumeration - */ -enum class DmaChannel -{ - CHANNEL_0, - CHANNEL_1, - CHANNEL_2, - CHANNEL_3, - CHANNEL_4, - CHANNEL_5, - CHANNEL_6, - CHANNEL_7 -}; - -/** - * @brief DMA configuration structure - */ -struct DmaConfig -{ - DmaPriority priority; - uint32_t flags; -}; - -/** - * @brief DMA descriptor structure - */ -struct DmaDescriptor -{ - uint32_t size; ///< Size of data to transfer - uint32_t length; ///< Actual length of valid data - uint32_t sosf : 1; ///< Start of sub-frame - uint32_t eof : 1; ///< End of frame - uint32_t owner : 1; ///< Owner (0: CPU, 1: DMA) - uint32_t reserved : 29; ///< Reserved bits - void* buffer; ///< Pointer to data buffer - DmaDescriptor* next; ///< Pointer to next descriptor -}; - -/** - * @brief DMA transfer configuration structure - */ -struct DmaTransferConfig -{ - void* srcAddr; ///< Source address - void* dstAddr; ///< Destination address - size_t dataSize; ///< Size of data to transfer - DmaDirection direction; ///< Transfer direction - DmaTransferType type; ///< Transfer type - DmaPriority priority; ///< Transfer priority - bool autoReload; ///< Auto-reload mode - bool enableInterrupt; ///< Enable transfer complete interrupt -}; - -/** - * @brief DMA channel configuration structure - */ -struct DmaChannelConfig -{ - DmaPriority priority; ///< Channel priority - uint32_t flags; ///< Configuration flags -}; - -/** - * @brief DMA callback function type - */ -#if SOC_GDMA_SUPPORTED -using DmaCallback = void (*)(gdma_channel_handle_t dmaChannel, gdma_event_data_t* eventData, void* userData); -#else -using DmaCallback = void (*)(void* dmaChannel, void* eventData, void* userData); -#endif - -/** - * @brief DMA wrapper class - * - * Provides a C++ wrapper for ESP-IDF GDMA functionality. - * This class encapsulates ESP-IDF GDMA driver functions in an object-oriented interface. - */ -class Dma -{ -public: - /** - * @brief Constructor - * @details Initializes the DMA wrapper instance - */ - Dma(); - - /** - * @brief Destructor - * @details Cleans up resources and deinitializes all DMA channels - */ - ~Dma(); - - /** - * @brief Initialize DMA component - * @param channel DMA channel - * @param config DMA configuration - * @return true if initialized successfully, false otherwise - */ - bool initialize(DmaChannel channel, const DmaConfig& config); - - /** - * @brief Allocate DMA channel - * @param config Channel configuration - * @param channelHandle Pointer to store channel handle - * @return true if allocated successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool allocateChannel(const DmaChannelConfig& config, gdma_channel_handle_t* channelHandle); -#else - bool allocateChannel(const DmaChannelConfig& config, void** channelHandle); -#endif - - /** - * @brief Deallocate DMA channel - * @param channelHandle Channel handle to deallocate - * @return true if deallocated successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool deallocateChannel(gdma_channel_handle_t channelHandle); -#else - bool deallocateChannel(void* channelHandle); -#endif - - /** - * @brief Configure DMA transfer - * @param channelHandle Channel handle - * @param config Transfer configuration - * @return true if configured successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool configureTransfer(gdma_channel_handle_t channelHandle, const DmaTransferConfig& config); -#else - bool configureTransfer(void* channelHandle, const DmaTransferConfig& config); -#endif - - /** - * @brief Start DMA transfer - * @param channelHandle Channel handle - * @return true if started successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool startTransfer(gdma_channel_handle_t channelHandle); -#else - bool startTransfer(void* channelHandle); -#endif - - /** - * @brief Stop DMA transfer - * @param channelHandle Channel handle - * @return true if stopped successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool stopTransfer(gdma_channel_handle_t channelHandle); -#else - bool stopTransfer(void* channelHandle); -#endif - - /** - * @brief Reset DMA channel - * @param channelHandle Channel handle - * @return true if reset successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool resetChannel(gdma_channel_handle_t channelHandle); -#else - bool resetChannel(void* channelHandle); -#endif - - /** - * @brief Allocate DMA-capable memory - * @param size Size of memory to allocate - * @param caps Memory capabilities (default: DMA capable) - * @return Pointer to allocated memory, or nullptr on failure - */ - void* allocateDmaMemory(size_t size, uint32_t caps = MALLOC_CAP_DMA); - - /** - * @brief Free DMA-capable memory - * @param ptr Pointer to memory to free - */ - void freeDmaMemory(void* ptr); - - /** - * @brief Create DMA descriptor - * @param buffer Pointer to data buffer - * @param size Size of data - * @param eof End of frame flag - * @return Pointer to created descriptor, or nullptr on failure - */ - DmaDescriptor* createDescriptor(void* buffer, size_t size, bool eof = true); - - /** - * @brief Link DMA descriptors - * @param desc1 First descriptor - * @param desc2 Second descriptor - * @return true if linked successfully, false otherwise - */ - bool linkDescriptors(DmaDescriptor* desc1, DmaDescriptor* desc2); - - /** - * @brief Free DMA descriptor - * @param descriptor Pointer to descriptor to free - */ - void freeDescriptor(DmaDescriptor* descriptor); - - /** - * @brief Set DMA callback - * @param channelHandle Channel handle - * @param callback Callback function - * @param userData User data passed to callback - * @return true if set successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool setCallback(gdma_channel_handle_t channelHandle, DmaCallback callback, void* userData); -#else - bool setCallback(void* channelHandle, DmaCallback callback, void* userData); -#endif - - /** - * @brief Enable DMA channel - * @param channelHandle Channel handle - * @return true if enabled successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool enableChannel(gdma_channel_handle_t channelHandle); -#else - bool enableChannel(void* channelHandle); -#endif - - /** - * @brief Disable DMA channel - * @param channelHandle Channel handle - * @return true if disabled successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool disableChannel(gdma_channel_handle_t channelHandle); -#else - bool disableChannel(void* channelHandle); -#endif - - /** - * @brief Get DMA channel state - * @param channelHandle Channel handle - * @return Current channel state - */ -#if SOC_GDMA_SUPPORTED - gdma_channel_state_t getChannelState(gdma_channel_handle_t channelHandle); -#else - int getChannelState(void* channelHandle); -#endif - - /** - * @brief Perform memory-to-memory copy using DMA - * @param dst Destination address - * @param src Source address - * @param size Size of data to copy - * @param channelHandle Channel handle (optional, will allocate if nullptr) - * @return true if copy completed successfully, false otherwise - */ -#if SOC_GDMA_SUPPORTED - bool memcpy(void* dst, const void* src, size_t size, gdma_channel_handle_t channelHandle = nullptr); -#else - bool memcpy(void* dst, const void* src, size_t size, void* channelHandle = nullptr); -#endif - - /** - * @brief Get default channel configuration - * @return Default DMA channel configuration - */ - static DmaChannelConfig getDefaultChannelConfig(); - - /** - * @brief Get default transfer configuration - * @return Default DMA transfer configuration - */ - static DmaTransferConfig getDefaultTransferConfig(); - - /** - * @brief Check if address is DMA capable - * @param addr Address to check - * @return true if DMA capable, false otherwise - */ - static bool isDmaCapable(const void* addr); - -private: - static constexpr size_t MAX_CHANNELS = 8; ///< Maximum number of DMA channels - -#if SOC_GDMA_SUPPORTED - gdma_channel_handle_t m_channels_[MAX_CHANNELS]; ///< Channel handles -#else - void* m_channels_[MAX_CHANNELS]; -#endif - bool m_channelAllocated_[MAX_CHANNELS]; ///< Channel allocation status - - /** - * @brief Find free channel slot - * @return Index of free slot, or -1 if none available - */ - int findFreeChannelSlot(); - - /** - * @brief Find channel slot by handle - * @param channelHandle Channel handle to find - * @return Index of channel slot, or -1 if not found - */ -#if SOC_GDMA_SUPPORTED - int findChannelSlot(gdma_channel_handle_t channelHandle); -#else - int findChannelSlot(void* channelHandle); -#endif - - /** - * @brief Convert DmaDirection to GDMA direction - * @param direction DMA direction - * @return GDMA direction - */ -#if SOC_GDMA_SUPPORTED - gdma_transfer_ability_t convertDirection(DmaDirection direction); -#endif - - /** - * @brief Convert DmaPriority to GDMA priority - * @param priority DMA priority - * @return GDMA priority - */ - int convertPriority(DmaPriority priority); -}; - -#endif // DMA_HPP - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/logging_data.csv deleted file mode 100644 index 3328939..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/logging_data.csv +++ /dev/null @@ -1,46 +0,0 @@ -ID,Component,Level,Criticality,Message -2200,DMA,INFO,Low,DMA wrapper initialized -2201,DMA,INFO,Low,DMA wrapper destroyed -2202,DMA,INFO,Low,DMA initialized successfully -2203,DMA,ERROR,High,Invalid channel handle pointer -2204,DMA,ERROR,High,No free channel slots available -2205,DMA,ERROR,High,Failed to allocate DMA channel: %s -2206,DMA,INFO,Low,DMA channel allocated successfully (slot %d) -2207,DMA,WARNING,Medium,GDMA not supported on this target -2208,DMA,ERROR,High,Invalid channel handle -2209,DMA,ERROR,High,Channel handle not found -2210,DMA,ERROR,High,Failed to deallocate DMA channel: %s -2211,DMA,INFO,Low,DMA channel deallocated successfully (slot %d) -2212,DMA,ERROR,High,Invalid channel handle -2213,DMA,INFO,Low,DMA transfer configured successfully -2214,DMA,ERROR,High,Invalid channel handle -2215,DMA,ERROR,High,Failed to start DMA transfer: %s -2216,DMA,INFO,Low,DMA transfer started successfully -2217,DMA,ERROR,High,Invalid channel handle -2218,DMA,ERROR,High,Failed to stop DMA transfer: %s -2219,DMA,INFO,Low,DMA transfer stopped successfully -2220,DMA,ERROR,High,Invalid channel handle -2221,DMA,ERROR,High,Failed to reset DMA channel: %s -2222,DMA,INFO,Low,DMA channel reset successfully -2223,DMA,ERROR,High,Failed to allocate DMA memory of size %zu -2224,DMA,INFO,Low,DMA memory allocated: %zu bytes at %p -2225,DMA,INFO,Low,DMA memory freed at %p -2226,DMA,ERROR,High,Invalid buffer or size for descriptor -2227,DMA,ERROR,High,Failed to allocate DMA descriptor -2228,DMA,INFO,Low,DMA descriptor created: size=%zu, eof=%d -2229,DMA,ERROR,High,Invalid descriptors for linking -2230,DMA,INFO,Low,DMA descriptors linked successfully -2231,DMA,INFO,Low,DMA descriptor freed -2232,DMA,ERROR,High,Invalid channel handle or callback -2233,DMA,ERROR,High,Failed to set DMA callback: %s -2234,DMA,INFO,Low,DMA callback set successfully -2235,DMA,ERROR,High,Invalid channel handle -2236,DMA,ERROR,High,Failed to enable DMA channel: %s -2237,DMA,INFO,Low,DMA channel enabled successfully -2238,DMA,ERROR,High,Invalid channel handle -2239,DMA,ERROR,High,Failed to disable DMA channel: %s -2240,DMA,INFO,Low,DMA channel disabled successfully -2241,DMA,ERROR,High,Invalid channel handle -2242,DMA,ERROR,High,Invalid parameters for DMA memcpy -2243,DMA,ERROR,High,DMA memcpy failed: %s -2244,DMA,INFO,Low,DMA memcpy completed: %zu bytes diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.py deleted file mode 100644 index 5329eea..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_dma_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "DMA initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_dma_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.test_scenario.xml b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.test_scenario.xml deleted file mode 100644 index 4f2ec67..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - DMA_INIT_TEST - - python components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.py - - - - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/test_dma.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/test_dma.cpp deleted file mode 100644 index 238d2a0..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/dma/test/test_dma.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file test_dma.cpp - * @brief Unit tests for DMA wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "dma.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_dma_initialize(void) -{ - Dma dma; - DmaConfig config = {64, 1024}; - bool result = dma.initialize(DmaChannel::CHANNEL_0, config); - TEST_ASSERT_TRUE(result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/CMakeLists.txt deleted file mode 100644 index 3c4add3..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/gpio.cpp" - INCLUDE_DIRS "com" - REQUIRES esp_driver_gpio logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/README.md deleted file mode 100644 index 3ca406d..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/README.md +++ /dev/null @@ -1,154 +0,0 @@ -# GPIO Wrapper Module - -## Overview - -The GPIO wrapper module provides a C++ object-oriented interface for ESP-IDF GPIO functionality. This module encapsulates the ESP-IDF GPIO driver functions and provides a clean, easy-to-use API for GPIO operations. - -## Features - -- **Pin Configuration**: Configure GPIO pins as input, output, or open-drain -- **Digital I/O**: Read and write digital values to GPIO pins -- **Pull Resistors**: Configure internal pull-up and pull-down resistors -- **Interrupt Handling**: Attach interrupt handlers to GPIO pins -- **Pin Validation**: Automatic validation of GPIO pin numbers -- **Error Handling**: Comprehensive error checking and logging - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ Gpio │ -├─────────────────────────────────────┤ -│ - m_isrInstalled_: bool │ -├─────────────────────────────────────┤ -│ + Gpio() │ -│ + ~Gpio() │ -│ + configure(pin, mode): bool │ -│ + setLevel(pin, level): bool │ -│ + getLevel(pin): int32_t │ -│ + toggleLevel(pin): bool │ -│ + installIsr(flags): bool │ -│ + uninstallIsr(): bool │ -│ + attachInterrupt(...): bool │ -│ + detachInterrupt(pin): bool │ -│ + enableInterrupt(pin): bool │ -│ + disableInterrupt(pin): bool │ -│ + isValidPin(pin): bool [static] │ -│ - convertMode(mode): gpio_mode_t │ -│ - convertIntType(type): gpio_int_t │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### GpioMode -- `INPUT`: Standard input mode -- `OUTPUT`: Standard output mode -- `INPUT_PULLUP`: Input with internal pull-up resistor -- `INPUT_PULLDOWN`: Input with internal pull-down resistor -- `OUTPUT_OD`: Open-drain output mode - -#### GpioIntType -- `DISABLE`: Disable interrupt -- `RISING_EDGE`: Trigger on rising edge -- `FALLING_EDGE`: Trigger on falling edge -- `ANY_EDGE`: Trigger on any edge -- `LOW_LEVEL`: Trigger on low level -- `HIGH_LEVEL`: Trigger on high level - -## Usage Examples - -### Basic GPIO Operations - -```cpp -#include "gpio.hpp" - -// Create GPIO instance -Gpio gpio; - -// Configure pin 2 as output -gpio.configure(2, GpioMode::OUTPUT); - -// Set pin high -gpio.setLevel(2, 1); - -// Configure pin 4 as input with pull-up -gpio.configure(4, GpioMode::INPUT_PULLUP); - -// Read pin level -int level = gpio.getLevel(4); -``` - -### Interrupt Handling - -```cpp -// Interrupt callback function -void IRAM_ATTR gpioInterruptHandler(uint32_t pin, void* arg) { - // Handle interrupt - printf("Interrupt on pin %lu\n", pin); -} - -// Setup interrupt -gpio.configure(5, GpioMode::INPUT); -gpio.attachInterrupt(5, GpioIntType::FALLING_EDGE, gpioInterruptHandler, nullptr); -``` - -## API Reference - -### Constructor/Destructor - -- **Gpio()**: Initialize GPIO wrapper instance -- **~Gpio()**: Clean up resources and uninstall ISR if needed - -### Configuration Methods - -- **configure(pin, mode)**: Configure GPIO pin mode and pull resistors -- **isValidPin(pin)**: Check if GPIO pin number is valid - -### Digital I/O Methods - -- **setLevel(pin, level)**: Set output pin level (0 or 1) -- **getLevel(pin)**: Read pin level, returns 0, 1, or -1 on error -- **toggleLevel(pin)**: Toggle output pin level - -### Interrupt Methods - -- **installIsr(flags)**: Install GPIO interrupt service -- **uninstallIsr()**: Uninstall GPIO interrupt service -- **attachInterrupt(pin, type, callback, arg)**: Attach interrupt handler -- **detachInterrupt(pin)**: Detach interrupt handler -- **enableInterrupt(pin)**: Enable interrupt for pin -- **disableInterrupt(pin)**: Disable interrupt for pin - -## Error Handling - -The module provides comprehensive error handling: -- Invalid pin numbers are checked and logged -- ESP-IDF errors are caught and logged with descriptive messages -- Return values indicate success/failure for all operations -- ESP_LOG is used for debugging and error reporting - -## Dependencies - -- ESP-IDF GPIO driver (`driver/gpio.h`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) - -## Thread Safety - -The GPIO wrapper is not inherently thread-safe. If used in multi-threaded applications, external synchronization mechanisms should be employed. - -## Memory Usage - -The GPIO wrapper has minimal memory footprint: -- Single boolean flag for ISR installation status -- No dynamic memory allocation -- Stack-based configuration structures - -## Performance Considerations - -- Direct ESP-IDF function calls for optimal performance -- Minimal overhead over raw ESP-IDF calls -- Interrupt handlers should be kept short and use IRAM_ATTR \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.cpp deleted file mode 100644 index 25a2225..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/** - * @file gpio.cpp - * @brief GPIO wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "gpio.hpp" -#include "logger.hpp" - -static const char* TAG = "GPIO_WRAPPER"; - -/** - * @brief Constructor - Initialize GPIO wrapper instance - * @details Initializes the GPIO wrapper with default settings - */ -Gpio::Gpio() - : m_isrInstalled_(false) -{ - ASF_LOGI(TAG, 2300, asf::logger::Criticality::LOW, "GPIO wrapper initialized"); -} - -/** - * @brief Destructor - Clean up GPIO wrapper resources - * @details Uninstalls ISR service if it was installed - */ -Gpio::~Gpio() -{ - if (m_isrInstalled_) { - uninstallIsr(); - } - ASF_LOGI(TAG, 2301, asf::logger::Criticality::LOW, "GPIO wrapper destroyed"); -} - -bool Gpio::configure(uint32_t pin, GpioMode mode) -{ - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2302, asf::logger::Criticality::HIGH, "Invalid GPIO pin: %lu", pin); - return false; - } - - gpio_config_t config = {}; - config.pin_bit_mask = (1ULL << pin); - config.mode = convertMode(mode); - config.intr_type = GPIO_INTR_DISABLE; - - // Configure pull-up/down based on mode - switch (mode) { - case GpioMode::INPUT_PULLUP: - config.pull_up_en = GPIO_PULLUP_ENABLE; - config.pull_down_en = GPIO_PULLDOWN_DISABLE; - break; - case GpioMode::INPUT_PULLDOWN: - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_ENABLE; - break; - default: - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_DISABLE; - break; - } - - esp_err_t ret = gpio_config(&config); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2303, asf::logger::Criticality::HIGH, "Failed to configure GPIO pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2304, asf::logger::Criticality::LOW, "GPIO pin %lu configured successfully", pin); - return true; -} - -bool Gpio::setLevel(uint32_t pin, uint32_t level) -{ - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2302, asf::logger::Criticality::HIGH, "Invalid GPIO pin: %lu", pin); - return false; - } - - esp_err_t ret = gpio_set_level(static_cast(pin), level); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2305, asf::logger::Criticality::HIGH, "Failed to set GPIO pin %lu level: %s", pin, esp_err_to_name(ret)); - return false; - } - - return true; -} - -int32_t Gpio::getLevel(uint32_t pin) -{ - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2302, asf::logger::Criticality::HIGH, "Invalid GPIO pin: %lu", pin); - return -1; - } - - int level = gpio_get_level(static_cast(pin)); - return level; -} - -bool Gpio::toggleLevel(uint32_t pin) -{ - int32_t currentLevel = getLevel(pin); - if (currentLevel < 0) { - return false; - } - - return setLevel(pin, currentLevel == 0 ? 1 : 0); -} - -bool Gpio::installIsr(int flags) -{ - if (m_isrInstalled_) { - ASF_LOGW(TAG, 2306, asf::logger::Criticality::MEDIUM, "GPIO ISR already installed"); - return true; - } - - esp_err_t ret = gpio_install_isr_service(flags); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2307, asf::logger::Criticality::HIGH, "Failed to install GPIO ISR service: %s", esp_err_to_name(ret)); - return false; - } - - m_isrInstalled_ = true; - ASF_LOGI(TAG, 2308, asf::logger::Criticality::LOW, "GPIO initialized successfully"); - return true; -} - -bool Gpio::uninstallIsr() -{ - if (!m_isrInstalled_) { - ASF_LOGW(TAG, 2309, asf::logger::Criticality::MEDIUM, "GPIO ISR not installed"); - return true; - } - - gpio_uninstall_isr_service(); - m_isrInstalled_ = false; - ASF_LOGI(TAG, 2310, asf::logger::Criticality::LOW, "GPIO ISR service uninstalled"); - return true; -} - -bool Gpio::attachInterrupt(uint32_t pin, GpioIntType intType, GpioCallback callback, void* arg) -{ - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2302, asf::logger::Criticality::HIGH, "Invalid GPIO pin: %lu", pin); - return false; - } - - if (!m_isrInstalled_) { - ASF_LOGW(TAG, 2311, asf::logger::Criticality::MEDIUM, "GPIO ISR not installed, installing now"); - if (!installIsr()) { - return false; - } - } - - // Set interrupt type - esp_err_t ret = gpio_set_intr_type(static_cast(pin), convertIntType(intType)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2312, asf::logger::Criticality::HIGH, "Failed to set interrupt type for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - // Add ISR handler - ret = gpio_isr_handler_add(static_cast(pin), - reinterpret_cast(callback), arg); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2313, asf::logger::Criticality::HIGH, "Failed to add ISR handler for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2314, asf::logger::Criticality::LOW, "Interrupt attached to GPIO pin %lu", pin); - return true; -} - -bool Gpio::detachInterrupt(uint32_t pin) -{ - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2302, asf::logger::Criticality::HIGH, "Invalid GPIO pin: %lu", pin); - return false; - } - - // Disable interrupt - esp_err_t ret = gpio_set_intr_type(static_cast(pin), GPIO_INTR_DISABLE); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2315, asf::logger::Criticality::HIGH, "Failed to disable interrupt for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - // Remove ISR handler - ret = gpio_isr_handler_remove(static_cast(pin)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2316, asf::logger::Criticality::HIGH, "Failed to remove ISR handler for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2317, asf::logger::Criticality::LOW, "Interrupt detached from GPIO pin %lu", pin); - return true; -} - -bool Gpio::enableInterrupt(uint32_t pin) -{ - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2302, asf::logger::Criticality::HIGH, "Invalid GPIO pin: %lu", pin); - return false; - } - - esp_err_t ret = gpio_intr_enable(static_cast(pin)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2318, asf::logger::Criticality::HIGH, "Failed to enable interrupt for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - return true; -} - -bool Gpio::disableInterrupt(uint32_t pin) -{ - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2302, asf::logger::Criticality::HIGH, "Invalid GPIO pin: %lu", pin); - return false; - } - - esp_err_t ret = gpio_intr_disable(static_cast(pin)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2319, asf::logger::Criticality::HIGH, "Failed to disable interrupt for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - return true; -} - -bool Gpio::isValidPin(uint32_t pin) -{ - return GPIO_IS_VALID_GPIO(pin); -} - -gpio_mode_t Gpio::convertMode(GpioMode mode) -{ - switch (mode) { - case GpioMode::INPUT: - case GpioMode::INPUT_PULLUP: - case GpioMode::INPUT_PULLDOWN: - return GPIO_MODE_INPUT; - case GpioMode::OUTPUT: - return GPIO_MODE_OUTPUT; - case GpioMode::OUTPUT_OD: - return GPIO_MODE_OUTPUT_OD; - default: - return GPIO_MODE_INPUT; - } -} - -gpio_int_type_t Gpio::convertIntType(GpioIntType intType) -{ - switch (intType) { - case GpioIntType::DISABLE: - return GPIO_INTR_DISABLE; - case GpioIntType::RISING_EDGE: - return GPIO_INTR_POSEDGE; - case GpioIntType::FALLING_EDGE: - return GPIO_INTR_NEGEDGE; - case GpioIntType::ANY_EDGE: - return GPIO_INTR_ANYEDGE; - case GpioIntType::LOW_LEVEL: - return GPIO_INTR_LOW_LEVEL; - case GpioIntType::HIGH_LEVEL: - return GPIO_INTR_HIGH_LEVEL; - default: - return GPIO_INTR_DISABLE; - } -} diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.hpp deleted file mode 100644 index 96711fa..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/com/gpio.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @file gpio.hpp - * @brief GPIO wrapper component header - Wrapper for ESP-IDF GPIO functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef GPIO_HPP -#define GPIO_HPP - -#include -#include "driver/gpio.h" -#include "esp_err.h" - -/** - * @brief GPIO pin mode enumeration - */ -enum class GpioMode -{ - INPUT, - OUTPUT, - INPUT_PULLUP, - INPUT_PULLDOWN, - OUTPUT_OD -}; - -/** - * @brief GPIO interrupt type enumeration - */ -enum class GpioIntType -{ - DISABLE, - RISING_EDGE, - FALLING_EDGE, - ANY_EDGE, - LOW_LEVEL, - HIGH_LEVEL -}; - -/** - * @brief GPIO callback function type - */ -using GpioCallback = void (*)(uint32_t pin, void* arg); - -/** - * @brief GPIO wrapper class - * - * Provides a C++ wrapper for ESP-IDF GPIO functionality. - * This class encapsulates ESP-IDF GPIO driver functions in an object-oriented interface. - */ -class Gpio -{ -public: - /** - * @brief Constructor - * @details Initializes the GPIO wrapper instance - */ - Gpio(); - - /** - * @brief Destructor - * @details Cleans up resources and uninstalls ISR if installed - */ - ~Gpio(); - - /** - * @brief Configure a GPIO pin - * @param pin GPIO pin number (0-39 for ESP32) - * @param mode GPIO mode configuration - * @return true if configured successfully, false otherwise - * @note This function configures the pin direction, pull-up/down resistors - */ - bool configure(uint32_t pin, GpioMode mode); - - /** - * @brief Set GPIO pin level - * @param pin GPIO pin number - * @param level Pin level (0 for low, 1 for high) - * @return true if set successfully, false otherwise - * @note Only works for output pins - */ - bool setLevel(uint32_t pin, uint32_t level); - - /** - * @brief Get GPIO pin level - * @param pin GPIO pin number - * @return Pin level (0 for low, 1 for high), or -1 on error - * @note Works for both input and output pins - */ - int32_t getLevel(uint32_t pin); - - /** - * @brief Toggle GPIO pin level - * @param pin GPIO pin number - * @return true if toggled successfully, false otherwise - * @note Only works for output pins - */ - bool toggleLevel(uint32_t pin); - - /** - * @brief Install GPIO interrupt service - * @param flags Allocation flags for interrupt service - * @return true if installed successfully, false otherwise - * @note Must be called before attaching interrupts - */ - bool installIsr(int flags = 0); - - /** - * @brief Uninstall GPIO interrupt service - * @return true if uninstalled successfully, false otherwise - */ - bool uninstallIsr(); - - /** - * @brief Attach interrupt to a GPIO pin - * @param pin GPIO pin number - * @param intType Interrupt type - * @param callback Callback function - * @param arg Argument passed to callback - * @return true if attached successfully, false otherwise - * @note ISR must be installed before calling this function - */ - bool attachInterrupt(uint32_t pin, GpioIntType intType, GpioCallback callback, void* arg); - - /** - * @brief Detach interrupt from a GPIO pin - * @param pin GPIO pin number - * @return true if detached successfully, false otherwise - */ - bool detachInterrupt(uint32_t pin); - - /** - * @brief Enable interrupt for a GPIO pin - * @param pin GPIO pin number - * @return true if enabled successfully, false otherwise - */ - bool enableInterrupt(uint32_t pin); - - /** - * @brief Disable interrupt for a GPIO pin - * @param pin GPIO pin number - * @return true if disabled successfully, false otherwise - */ - bool disableInterrupt(uint32_t pin); - - /** - * @brief Check if GPIO pin is valid - * @param pin GPIO pin number - * @return true if pin is valid, false otherwise - */ - static bool isValidPin(uint32_t pin); - -private: - bool m_isrInstalled_; ///< Flag indicating if ISR is installed - - /** - * @brief Convert GpioMode to ESP-IDF gpio_mode_t - * @param mode GPIO mode - * @return ESP-IDF gpio_mode_t - */ - gpio_mode_t convertMode(GpioMode mode); - - /** - * @brief Convert GpioIntType to ESP-IDF gpio_int_type_t - * @param intType Interrupt type - * @return ESP-IDF gpio_int_type_t - */ - gpio_int_type_t convertIntType(GpioIntType intType); -}; - -#endif // GPIO_HPP - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/logging_data.csv deleted file mode 100644 index fe34585..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/logging_data.csv +++ /dev/null @@ -1,21 +0,0 @@ -ID,Component,Level,Criticality,Message -2300,GPIO,INFO,Low,GPIO wrapper initialized -2301,GPIO,INFO,Low,GPIO wrapper destroyed -2302,GPIO,ERROR,High,Invalid GPIO pin: %lu -2303,GPIO,ERROR,High,Failed to configure GPIO pin %lu: %s -2304,GPIO,INFO,Low,GPIO pin %lu configured successfully -2305,GPIO,ERROR,High,Failed to set GPIO pin %lu level: %s -2306,GPIO,WARNING,Medium,GPIO ISR already installed -2307,GPIO,ERROR,High,Failed to install GPIO ISR service: %s -2308,GPIO,INFO,Low,GPIO initialized successfully -2309,GPIO,WARNING,Medium,GPIO ISR not installed -2310,GPIO,INFO,Low,GPIO ISR service uninstalled -2311,GPIO,WARNING,Medium,GPIO ISR not installed, installing now -2312,GPIO,ERROR,High,Failed to set interrupt type for pin %lu: %s -2313,GPIO,ERROR,High,Failed to add ISR handler for pin %lu: %s -2314,GPIO,INFO,Low,Interrupt attached to GPIO pin %lu -2315,GPIO,ERROR,High,Failed to disable interrupt for pin %lu: %s -2316,GPIO,ERROR,High,Failed to remove ISR handler for pin %lu: %s -2317,GPIO,INFO,Low,Interrupt detached from GPIO pin %lu -2318,GPIO,ERROR,High,Failed to enable interrupt for pin %lu: %s -2319,GPIO,ERROR,High,Failed to disable interrupt for pin %lu: %s diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.py deleted file mode 100644 index 88a2841..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_gpio_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "GPIO wrapper initialized" in line or "GPIO ISR service installed successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_gpio_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.test_scenario.xml b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.test_scenario.xml deleted file mode 100644 index 090e3d1..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - GPIO_INIT_TEST - - python components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.py - - - - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/test_gpio.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/test_gpio.cpp deleted file mode 100644 index 7f3b19d..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/gpio/test/test_gpio.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file test_gpio.cpp - * @brief Unit tests for GPIO wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "gpio.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -/** - * @brief Test GPIO configuration - */ -void test_gpio_configure(void) -{ - Gpio gpio; - bool result = gpio.configure(2, GpioMode::OUTPUT); - TEST_ASSERT_TRUE(result); -} - -/** - * @brief Test GPIO set level - */ -void test_gpio_set_level(void) -{ - Gpio gpio; - gpio.configure(2, GpioMode::OUTPUT); - bool result = gpio.setLevel(2, 1); - TEST_ASSERT_TRUE(result); -} - -/** - * @brief Test GPIO get level - */ -void test_gpio_get_level(void) -{ - Gpio gpio; - gpio.configure(2, GpioMode::INPUT); - int32_t result = gpio.getLevel(2); - TEST_ASSERT_TRUE(result >= 0); -} - -/** - * @brief Test GPIO ISR installation - */ -void test_gpio_install_isr(void) -{ - Gpio gpio; - bool result = gpio.installIsr(); - TEST_ASSERT_TRUE(result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/CMakeLists.txt deleted file mode 100644 index c85ea84..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -idf_component_register( - SRCS "com/i2c.cpp" - INCLUDE_DIRS "com" - REQUIRES driver logger - -) \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/README.md deleted file mode 100644 index 5d0dc09..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/README.md +++ /dev/null @@ -1,216 +0,0 @@ -# I2C Wrapper Module - -## Overview - -The I2C wrapper module provides a C++ object-oriented interface for ESP-IDF I2C functionality. This module encapsulates the ESP-IDF I2C driver functions and provides a clean, easy-to-use API for I2C communication with peripheral devices. - -## Features - -- **Multi-Port Support**: Support for I2C0 and I2C1 -- **Master/Slave Mode**: Configurable as master or slave device -- **Register Operations**: Convenient register read/write functions -- **Bus Scanning**: Automatic device discovery on I2C bus -- **Timeout Support**: Configurable timeouts for all operations -- **Pull-up Configuration**: Internal pull-up resistor control -- **Error Handling**: Comprehensive error checking and logging - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ I2c │ -├─────────────────────────────────────┤ -│ - m_isInitialized_[2]: bool │ -├─────────────────────────────────────┤ -│ + I2c() │ -│ + ~I2c() │ -│ + initialize(port, config): bool │ -│ + deinitialize(port): bool │ -│ + write(...): int32_t │ -│ + read(...): int32_t │ -│ + writeRead(...): int32_t │ -│ + writeRegister(...): bool │ -│ + readRegister(...): int32_t │ -│ + scanBus(...): int32_t │ -│ + isInitialized(port): bool │ -│ + getDefaultConfig(): I2cConfig │ -│ - convertPort(port): i2c_port_t │ -│ - convertConfig(cfg): i2c_config_t │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### I2cPort -- `PORT_0`: I2C port 0 -- `PORT_1`: I2C port 1 - -#### I2cMode -- `MASTER`: Master mode -- `SLAVE`: Slave mode - -### Configuration Structure - -```cpp -struct I2cConfig { - I2cMode mode; // I2C mode (master/slave) - uint32_t sdaPin; // SDA pin number - uint32_t sclPin; // SCL pin number - uint32_t clkSpeedHz; // Clock speed in Hz (for master mode) - bool sdaPullupEnable; // Enable SDA pull-up resistor - bool sclPullupEnable; // Enable SCL pull-up resistor - uint8_t slaveAddress; // Slave address (for slave mode) - uint32_t rxBufferLen; // RX buffer length (for slave mode) - uint32_t txBufferLen; // TX buffer length (for slave mode) -}; -``` - -## Usage Examples - -### Basic I2C Master Communication - -```cpp -#include "i2c.hpp" - -// Create I2C instance -I2c i2c; - -// Get default configuration -I2cConfig config = I2c::getDefaultConfig(); -config.sdaPin = 21; -config.sclPin = 22; -config.clkSpeedHz = 400000; // 400kHz - -// Initialize I2C -i2c.initialize(I2cPort::PORT_0, config); - -// Write data to device -uint8_t data[] = {0x01, 0x02, 0x03}; -i2c.write(I2cPort::PORT_0, 0x48, data, sizeof(data)); - -// Read data from device -uint8_t buffer[10]; -int32_t bytesRead = i2c.read(I2cPort::PORT_0, 0x48, buffer, sizeof(buffer)); -``` - -### Register Operations - -```cpp -// Write to register -i2c.writeRegister(I2cPort::PORT_0, 0x48, 0x10, 0xFF); - -// Read from register -int32_t regValue = i2c.readRegister(I2cPort::PORT_0, 0x48, 0x10); - -// Write register address and read multiple bytes -uint8_t regData[4]; -i2c.writeRead(I2cPort::PORT_0, 0x48, 0x10, regData, sizeof(regData)); -``` - -### Bus Scanning - -```cpp -// Scan for devices on the bus -uint8_t devices[20]; -int32_t deviceCount = i2c.scanBus(I2cPort::PORT_0, devices, sizeof(devices)); - -printf("Found %ld devices:\n", deviceCount); -for (int i = 0; i < deviceCount; i++) { - printf("Device at address: 0x%02X\n", devices[i]); -} -``` - -### Slave Mode Configuration - -```cpp -I2cConfig slaveConfig = {}; -slaveConfig.mode = I2cMode::SLAVE; -slaveConfig.sdaPin = 21; -slaveConfig.sclPin = 22; -slaveConfig.slaveAddress = 0x28; -slaveConfig.rxBufferLen = 256; -slaveConfig.txBufferLen = 256; -slaveConfig.sdaPullupEnable = true; -slaveConfig.sclPullupEnable = true; - -i2c.initialize(I2cPort::PORT_1, slaveConfig); -``` - -## API Reference - -### Constructor/Destructor - -- **I2c()**: Initialize I2C wrapper instance -- **~I2c()**: Clean up resources and deinitialize all ports - -### Configuration Methods - -- **initialize(port, config)**: Initialize I2C port with configuration -- **deinitialize(port)**: Deinitialize I2C port -- **isInitialized(port)**: Check if port is initialized -- **getDefaultConfig()**: Get default configuration structure - -### Communication Methods - -- **write(port, address, data, length, timeout)**: Write data to device -- **read(port, address, buffer, length, timeout)**: Read data from device -- **writeRead(port, address, regAddr, buffer, length, timeout)**: Write register address and read data - -### Register Operations - -- **writeRegister(port, address, regAddr, value, timeout)**: Write single register -- **readRegister(port, address, regAddr, timeout)**: Read single register - -### Utility Methods - -- **scanBus(port, devices, maxDevices)**: Scan bus for connected devices - -## Error Handling - -The module provides comprehensive error handling: -- Port validation and initialization checks -- Device address validation (0x08-0x77 range) -- ESP-IDF error codes are caught and logged -- Return values indicate success/failure for all operations -- Detailed logging for debugging and troubleshooting - -## Dependencies - -- ESP-IDF I2C driver (`driver/i2c.h`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) -- FreeRTOS (`freertos/FreeRTOS.h`, `freertos/task.h`) - -## Thread Safety - -The I2C wrapper uses ESP-IDF's thread-safe I2C driver. Multiple tasks can safely use different I2C ports simultaneously, but access to the same port should be synchronized. - -## Memory Usage - -- Fixed memory footprint per instance -- Configurable buffer sizes for slave mode -- No dynamic memory allocation in wrapper layer - -## Performance Considerations - -- Direct ESP-IDF function calls for optimal performance -- Minimal overhead over raw ESP-IDF calls -- Configurable clock speeds (100kHz, 400kHz, 1MHz) -- Bus scanning can be time-consuming for large address ranges - -## Common I2C Speeds - -- **Standard Mode**: 100 kHz -- **Fast Mode**: 400 kHz -- **Fast Mode Plus**: 1 MHz - -## Troubleshooting - -### Common Issues - -1. **Pull-up Resistors**: Ensure proper pull-up resistors on SDA/SCL lines -2. **Address Conflicts**: Check for address conflicts when using multiple devices -3. **Clock Stretching**: Some devices require clock stretching support -4. **Bus Capacitance**: Long wires or many devices can affect signal integrity \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.cpp deleted file mode 100644 index c322a6a..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/** - * @file i2c.cpp - * @brief I2C wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "i2c.hpp" -#include "logger.hpp" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -static const char* TAG = "I2C_WRAPPER"; - -I2c::I2c() -{ - m_isInitialized_[0] = false; - m_isInitialized_[1] = false; - ASF_LOGI(TAG, 2400, asf::logger::Criticality::LOW, "I2C wrapper initialized"); -} - -I2c::~I2c() -{ - // Deinitialize all ports - for (int i = 0; i < 2; i++) { - if (m_isInitialized_[i]) { - deinitialize(static_cast(i)); - } - } - ASF_LOGI(TAG, 2401, asf::logger::Criticality::LOW, "I2C wrapper destroyed"); -} - -bool I2c::initialize(I2cPort port, const I2cConfig& config) -{ - uint8_t portIdx = static_cast(port); - i2c_port_t i2cPort = convertPort(port); - - if (m_isInitialized_[portIdx]) { - ASF_LOGW(TAG, 2402, asf::logger::Criticality::MEDIUM, "I2C port %d already initialized", portIdx); - return true; - } - - // Configure I2C parameters - i2c_config_t i2cConfig = convertConfig(config); - - esp_err_t ret = i2c_param_config(i2cPort, &i2cConfig); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2403, asf::logger::Criticality::HIGH, "Failed to configure I2C port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - // Install I2C driver - ret = i2c_driver_install(i2cPort, i2cConfig.mode, config.rxBufferLen, config.txBufferLen, 0); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2404, asf::logger::Criticality::HIGH, "Failed to install I2C driver for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - m_isInitialized_[portIdx] = true; - ASF_LOGI(TAG, 2405, asf::logger::Criticality::LOW, "I2C initialized successfully"); - return true; -} - -bool I2c::deinitialize(I2cPort port) -{ - uint8_t portIdx = static_cast(port); - i2c_port_t i2cPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGW(TAG, 2406, asf::logger::Criticality::MEDIUM, "I2C port %d not initialized", portIdx); - return true; - } - - esp_err_t ret = i2c_driver_delete(i2cPort); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2407, asf::logger::Criticality::HIGH, "Failed to delete I2C driver for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - m_isInitialized_[portIdx] = false; - ASF_LOGI(TAG, 2408, asf::logger::Criticality::LOW, "I2C port %d deinitialized", portIdx); - return true; -} - -int32_t I2c::write(I2cPort port, uint8_t deviceAddress, const uint8_t* data, size_t dataLen, uint32_t timeoutMs) -{ - uint8_t portIdx = static_cast(port); - i2c_port_t i2cPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2409, asf::logger::Criticality::HIGH, "I2C port %d not initialized", portIdx); - return -1; - } - - if (data == nullptr || dataLen == 0) { - ASF_LOGE(TAG, 2410, asf::logger::Criticality::HIGH, "Invalid data or length"); - return -1; - } - - TickType_t timeout = pdMS_TO_TICKS(timeoutMs); - - esp_err_t ret = i2c_master_write_to_device(i2cPort, deviceAddress, data, dataLen, timeout); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2411, asf::logger::Criticality::HIGH, "Failed to write to device 0x%02X on port %d: %s", - deviceAddress, portIdx, esp_err_to_name(ret)); - return -1; - } - - return static_cast(dataLen); -} - -int32_t I2c::read(I2cPort port, uint8_t deviceAddress, uint8_t* data, size_t dataLen, uint32_t timeoutMs) -{ - uint8_t portIdx = static_cast(port); - i2c_port_t i2cPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2412, asf::logger::Criticality::HIGH, "I2C port %d not initialized", portIdx); - return -1; - } - - if (data == nullptr || dataLen == 0) { - ASF_LOGE(TAG, 2413, asf::logger::Criticality::HIGH, "Invalid data buffer or length"); - return -1; - } - - TickType_t timeout = pdMS_TO_TICKS(timeoutMs); - - esp_err_t ret = i2c_master_read_from_device(i2cPort, deviceAddress, data, dataLen, timeout); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2414, asf::logger::Criticality::HIGH, "Failed to read from device 0x%02X on port %d: %s", - deviceAddress, portIdx, esp_err_to_name(ret)); - return -1; - } - - return static_cast(dataLen); -} - -int32_t I2c::writeRead(I2cPort port, uint8_t deviceAddress, uint8_t regAddress, uint8_t* data, size_t dataLen, uint32_t timeoutMs) -{ - uint8_t portIdx = static_cast(port); - i2c_port_t i2cPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2415, asf::logger::Criticality::HIGH, "I2C port %d not initialized", portIdx); - return -1; - } - - if (data == nullptr || dataLen == 0) { - ASF_LOGE(TAG, 2416, asf::logger::Criticality::HIGH, "Invalid data buffer or length"); - return -1; - } - - TickType_t timeout = pdMS_TO_TICKS(timeoutMs); - - esp_err_t ret = i2c_master_write_read_device(i2cPort, deviceAddress, - ®Address, 1, data, dataLen, timeout); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2417, asf::logger::Criticality::HIGH, "Failed to write-read device 0x%02X on port %d: %s", - deviceAddress, portIdx, esp_err_to_name(ret)); - return -1; - } - - return static_cast(dataLen); -} - -bool I2c::writeRegister(I2cPort port, uint8_t deviceAddress, uint8_t regAddress, uint8_t regValue, uint32_t timeoutMs) -{ - uint8_t writeData[2] = {regAddress, regValue}; - int32_t result = write(port, deviceAddress, writeData, 2, timeoutMs); - return result == 2; -} - -int32_t I2c::readRegister(I2cPort port, uint8_t deviceAddress, uint8_t regAddress, uint32_t timeoutMs) -{ - uint8_t regValue = 0; - int32_t result = writeRead(port, deviceAddress, regAddress, ®Value, 1, timeoutMs); - - if (result == 1) { - return regValue; - } - - return -1; -} - -int32_t I2c::scanBus(I2cPort port, uint8_t* devices, size_t maxDevices) -{ - uint8_t portIdx = static_cast(port); - i2c_port_t i2cPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2418, asf::logger::Criticality::HIGH, "I2C port %d not initialized", portIdx); - return -1; - } - - if (devices == nullptr || maxDevices == 0) { - ASF_LOGE(TAG, 2419, asf::logger::Criticality::HIGH, "Invalid devices buffer or size"); - return -1; - } - - int32_t deviceCount = 0; - uint8_t testData = 0; - - ASF_LOGI(TAG, 2420, asf::logger::Criticality::LOW, "Scanning I2C bus on port %d...", portIdx); - - for (uint8_t addr = 0x08; addr < 0x78 && deviceCount < maxDevices; addr++) { - esp_err_t ret = i2c_master_write_to_device(i2cPort, addr, &testData, 0, pdMS_TO_TICKS(100)); - - if (ret == ESP_OK) { - devices[deviceCount] = addr; - deviceCount++; - ASF_LOGI(TAG, 2421, asf::logger::Criticality::LOW, "Found device at address 0x%02X", addr); - } - } - - ASF_LOGI(TAG, 2422, asf::logger::Criticality::LOW, "I2C scan complete. Found %ld devices", deviceCount); - return deviceCount; -} - -bool I2c::isInitialized(I2cPort port) const -{ - uint8_t portIdx = static_cast(port); - return m_isInitialized_[portIdx]; -} - -I2cConfig I2c::getDefaultConfig() -{ - I2cConfig config = {}; - config.mode = I2cMode::MASTER; - config.sdaPin = GPIO_NUM_21; - config.sclPin = GPIO_NUM_22; - config.clkSpeedHz = 100000; // 100kHz - config.sdaPullupEnable = true; - config.sclPullupEnable = true; - config.slaveAddress = 0; - config.rxBufferLen = 0; // Not used in master mode - config.txBufferLen = 0; // Not used in master mode - return config; -} - -i2c_port_t I2c::convertPort(I2cPort port) -{ - switch (port) { - case I2cPort::PORT_0: - return I2C_NUM_0; - case I2cPort::PORT_1: - return I2C_NUM_1; - default: - return I2C_NUM_0; - } -} - -i2c_config_t I2c::convertConfig(const I2cConfig& config) -{ - i2c_config_t i2cConfig = {}; - i2cConfig.mode = static_cast(config.mode); - i2cConfig.sda_io_num = static_cast(config.sdaPin); - i2cConfig.scl_io_num = static_cast(config.sclPin); - i2cConfig.sda_pullup_en = config.sdaPullupEnable; - i2cConfig.scl_pullup_en = config.sclPullupEnable; - - if (config.mode == I2cMode::MASTER) { - i2cConfig.master.clk_speed = config.clkSpeedHz; - } else { - i2cConfig.slave.addr_10bit_en = 0; - i2cConfig.slave.slave_addr = config.slaveAddress; - i2cConfig.slave.maximum_speed = config.clkSpeedHz; - } - - i2cConfig.clk_flags = 0; - return i2cConfig; -} diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.hpp deleted file mode 100644 index 662bfae..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/com/i2c.hpp +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file i2c.hpp - * @brief I2C wrapper component header - Wrapper for ESP-IDF I2C functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef I2C_HPP -#define I2C_HPP - -#include -#include "driver/i2c.h" -#include "esp_err.h" - -/** - * @brief I2C port enumeration - */ -enum class I2cPort -{ - PORT_0, - PORT_1 -}; - -/** - * @brief I2C mode enumeration - */ -enum class I2cMode -{ - MASTER = I2C_MODE_MASTER, - SLAVE = I2C_MODE_SLAVE -}; - -/** - * @brief I2C configuration structure - */ -struct I2cConfig -{ - I2cMode mode; ///< I2C mode (master/slave) - uint32_t sdaPin; ///< SDA pin number - uint32_t sclPin; ///< SCL pin number - uint32_t clkSpeedHz; ///< Clock speed in Hz (for master mode) - bool sdaPullupEnable; ///< Enable SDA pull-up resistor - bool sclPullupEnable; ///< Enable SCL pull-up resistor - uint8_t slaveAddress; ///< Slave address (for slave mode) - uint32_t rxBufferLen; ///< RX buffer length (for slave mode) - uint32_t txBufferLen; ///< TX buffer length (for slave mode) -}; - -/** - * @brief I2C wrapper class - * - * Provides a C++ wrapper for ESP-IDF I2C functionality. - * This class encapsulates ESP-IDF I2C driver functions in an object-oriented interface. - */ -class I2c -{ -public: - /** - * @brief Constructor - * @details Initializes the I2C wrapper instance - */ - I2c(); - - /** - * @brief Destructor - * @details Cleans up resources and deinitializes all I2C ports - */ - ~I2c(); - - /** - * @brief Initialize I2C bus - * @param port I2C port number - * @param config I2C configuration parameters - * @return true if initialized successfully, false otherwise - * @note This function configures pins, clock speed, and mode - */ - bool initialize(I2cPort port, const I2cConfig& config); - - /** - * @brief Deinitialize I2C bus - * @param port I2C port number - * @return true if deinitialized successfully, false otherwise - */ - bool deinitialize(I2cPort port); - - /** - * @brief Write data to I2C device - * @param port I2C port number - * @param deviceAddress 7-bit device address - * @param data Pointer to data buffer - * @param dataLen Number of bytes to write - * @param timeoutMs Timeout in milliseconds (default: 1000ms) - * @return Number of bytes written, or -1 on error - */ - int32_t write(I2cPort port, uint8_t deviceAddress, const uint8_t* data, size_t dataLen, uint32_t timeoutMs = 1000); - - /** - * @brief Read data from I2C device - * @param port I2C port number - * @param deviceAddress 7-bit device address - * @param data Pointer to receive buffer - * @param dataLen Number of bytes to read - * @param timeoutMs Timeout in milliseconds (default: 1000ms) - * @return Number of bytes read, or -1 on error - */ - int32_t read(I2cPort port, uint8_t deviceAddress, uint8_t* data, size_t dataLen, uint32_t timeoutMs = 1000); - - /** - * @brief Write to register and read from I2C device - * @param port I2C port number - * @param deviceAddress 7-bit device address - * @param regAddress Register address to write - * @param data Pointer to receive buffer - * @param dataLen Number of bytes to read - * @param timeoutMs Timeout in milliseconds (default: 1000ms) - * @return Number of bytes read, or -1 on error - */ - int32_t writeRead(I2cPort port, uint8_t deviceAddress, uint8_t regAddress, uint8_t* data, size_t dataLen, uint32_t timeoutMs = 1000); - - /** - * @brief Write register value to I2C device - * @param port I2C port number - * @param deviceAddress 7-bit device address - * @param regAddress Register address - * @param regValue Register value - * @param timeoutMs Timeout in milliseconds (default: 1000ms) - * @return true if written successfully, false otherwise - */ - bool writeRegister(I2cPort port, uint8_t deviceAddress, uint8_t regAddress, uint8_t regValue, uint32_t timeoutMs = 1000); - - /** - * @brief Read register value from I2C device - * @param port I2C port number - * @param deviceAddress 7-bit device address - * @param regAddress Register address - * @param timeoutMs Timeout in milliseconds (default: 1000ms) - * @return Register value, or -1 on error - */ - int32_t readRegister(I2cPort port, uint8_t deviceAddress, uint8_t regAddress, uint32_t timeoutMs = 1000); - - /** - * @brief Scan I2C bus for devices - * @param port I2C port number - * @param devices Array to store found device addresses - * @param maxDevices Maximum number of devices to find - * @return Number of devices found - */ - int32_t scanBus(I2cPort port, uint8_t* devices, size_t maxDevices); - - /** - * @brief Check if I2C port is initialized - * @param port I2C port number - * @return true if initialized, false otherwise - */ - bool isInitialized(I2cPort port) const; - - /** - * @brief Get default I2C configuration - * @return Default I2C configuration structure - */ - static I2cConfig getDefaultConfig(); - -private: - bool m_isInitialized_[2]; ///< Initialization status for each port - - /** - * @brief Convert I2cPort to ESP-IDF i2c_port_t - * @param port I2C port - * @return ESP-IDF i2c_port_t - */ - i2c_port_t convertPort(I2cPort port); - - /** - * @brief Convert I2cConfig to ESP-IDF i2c_config_t - * @param config I2C configuration - * @return ESP-IDF i2c_config_t - */ - i2c_config_t convertConfig(const I2cConfig& config); -}; - -#endif // I2C_HPP - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/logging_data.csv deleted file mode 100644 index 3c0ebdb..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/logging_data.csv +++ /dev/null @@ -1,24 +0,0 @@ -ID,Component,Level,Criticality,Message -2400,I2C,INFO,Low,I2C wrapper initialized -2401,I2C,INFO,Low,I2C wrapper destroyed -2402,I2C,WARNING,Medium,I2C port %d already initialized -2403,I2C,ERROR,High,Failed to configure I2C port %d: %s -2404,I2C,ERROR,High,Failed to install I2C driver for port %d: %s -2405,I2C,INFO,Low,I2C initialized successfully -2406,I2C,WARNING,Medium,I2C port %d not initialized -2407,I2C,ERROR,High,Failed to delete I2C driver for port %d: %s -2408,I2C,INFO,Low,I2C port %d deinitialized -2409,I2C,ERROR,High,I2C port %d not initialized -2410,I2C,ERROR,High,Invalid data or length -2411,I2C,ERROR,High,Failed to write to device 0x%02X on port %d: %s -2412,I2C,ERROR,High,I2C port %d not initialized -2413,I2C,ERROR,High,Invalid data buffer or length -2414,I2C,ERROR,High,Failed to read from device 0x%02X on port %d: %s -2415,I2C,ERROR,High,I2C port %d not initialized -2416,I2C,ERROR,High,Invalid data buffer or length -2417,I2C,ERROR,High,Failed to write-read device 0x%02X on port %d: %s -2418,I2C,ERROR,High,I2C port %d not initialized -2419,I2C,ERROR,High,Invalid devices buffer or size -2420,I2C,INFO,Low,Scanning I2C bus on port %d... -2421,I2C,INFO,Low,Found device at address 0x%02X -2422,I2C,INFO,Low,I2C scan complete. Found %ld devices diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.py deleted file mode 100644 index f45ff72..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_i2c_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "I2C initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_i2c_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.test_scenario.xml b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.test_scenario.xml deleted file mode 100644 index 2cedb22..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - I2C_INIT_TEST - - python components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.py - - - - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/test_i2c.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/test_i2c.cpp deleted file mode 100644 index f8974e6..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/i2c/test/test_i2c.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file test_i2c.cpp - * @brief Unit tests for I2C wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "i2c.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -/** - * @brief Test I2C initialization - */ -void test_i2c_initialize(void) -{ - I2c i2c; - I2cConfig config = {21, 22, 100000}; - bool result = i2c.initialize(I2cPort::PORT_0, config); - TEST_ASSERT_TRUE(result); -} - -/** - * @brief Test I2C deinitialize - */ -void test_i2c_deinitialize(void) -{ - I2c i2c; - I2cConfig config = {21, 22, 100000}; - i2c.initialize(I2cPort::PORT_0, config); - - bool result = i2c.deinitialize(I2cPort::PORT_0); - TEST_ASSERT_TRUE(result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/CMakeLists.txt deleted file mode 100644 index 4a38bb9..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/spi.cpp" - INCLUDE_DIRS "com" - REQUIRES esp_driver_spi esp_driver_gpio logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/README.md deleted file mode 100644 index 2f61cd6..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/README.md +++ /dev/null @@ -1,279 +0,0 @@ -# SPI Wrapper Module - -## Overview - -The SPI wrapper module provides a C++ object-oriented interface for ESP-IDF SPI master functionality. This module encapsulates the ESP-IDF SPI master driver functions and provides a clean, easy-to-use API for SPI communication with peripheral devices. - -## Features - -- **Multi-Host Support**: Support for SPI1, SPI2, and SPI3 hosts -- **Device Management**: Add/remove multiple devices per SPI bus -- **Flexible Transfers**: Support for TX-only, RX-only, and full-duplex transfers -- **Command/Address Phases**: Support for command and address phases -- **DMA Support**: Automatic DMA channel allocation for high-speed transfers -- **Multiple SPI Modes**: Support for all 4 SPI modes (0-3) -- **Error Handling**: Comprehensive error checking and logging - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ Spi │ -├─────────────────────────────────────┤ -│ - m_isInitialized_[3]: bool │ -├─────────────────────────────────────┤ -│ + Spi() │ -│ + ~Spi() │ -│ + initializeBus(host, cfg): bool │ -│ + deinitializeBus(host): bool │ -│ + addDevice(host, cfg, hdl): bool │ -│ + removeDevice(handle): bool │ -│ + transmit(...): int32_t │ -│ + transmitOnly(...): int32_t │ -│ + receiveOnly(...): int32_t │ -│ + transmitWithCmdAddr(...): int32_t │ -│ + isInitialized(host): bool │ -│ + getDefaultBusConfig(): SpiBusCfg │ -│ + getDefaultDeviceConfig(): SpiDev │ -│ - convertHost(host): spi_host_t │ -│ - convertBusConfig(cfg): spi_bus_t │ -│ - convertDeviceConfig(cfg): spi_dev │ -│ - convertMode(mode): uint32_t │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### SpiHost -- `SPI1_HOST`: SPI1 host (typically used for flash) -- `SPI2_HOST`: SPI2 host (HSPI) -- `SPI3_HOST`: SPI3 host (VSPI) - -#### SpiMode -- `MODE_0`: CPOL=0, CPHA=0 (Clock idle low, data sampled on rising edge) -- `MODE_1`: CPOL=0, CPHA=1 (Clock idle low, data sampled on falling edge) -- `MODE_2`: CPOL=1, CPHA=0 (Clock idle high, data sampled on falling edge) -- `MODE_3`: CPOL=1, CPHA=1 (Clock idle high, data sampled on rising edge) - -### Configuration Structures - -#### SpiBusConfig -```cpp -struct SpiBusConfig { - uint32_t mosiPin; // MOSI pin number - uint32_t misoPin; // MISO pin number - uint32_t sclkPin; // SCLK pin number - uint32_t quadwpPin; // Quad SPI write protect pin (optional) - uint32_t quadhdPin; // Quad SPI hold pin (optional) - uint32_t maxTransferSize; // Maximum transfer size in bytes -}; -``` - -#### SpiDeviceConfig -```cpp -struct SpiDeviceConfig { - uint32_t csPin; // Chip select pin number - uint32_t clockSpeedHz; // Clock speed in Hz - SpiMode mode; // SPI mode (0-3) - uint32_t queueSize; // Transaction queue size - uint32_t commandBits; // Command phase bits - uint32_t addressBits; // Address phase bits - uint32_t dummyBits; // Dummy phase bits - bool csEnaPretrans; // CS setup time - bool csEnaPosttrans; // CS hold time -}; -``` - -## Usage Examples - -### Basic SPI Communication - -```cpp -#include "spi.hpp" - -// Create SPI instance -Spi spi; - -// Get default bus configuration -SpiBusConfig busConfig = Spi::getDefaultBusConfig(); -busConfig.mosiPin = 23; -busConfig.misoPin = 19; -busConfig.sclkPin = 18; - -// Initialize SPI bus -spi.initializeBus(SpiHost::SPI2_HOST, busConfig); - -// Get default device configuration -SpiDeviceConfig deviceConfig = Spi::getDefaultDeviceConfig(); -deviceConfig.csPin = 5; -deviceConfig.clockSpeedHz = 1000000; // 1MHz -deviceConfig.mode = SpiMode::MODE_0; - -// Add device to bus -spi_device_handle_t deviceHandle; -spi.addDevice(SpiHost::SPI2_HOST, deviceConfig, &deviceHandle); - -// Transmit and receive data -uint8_t txData[] = {0x01, 0x02, 0x03}; -uint8_t rxData[3]; -spi.transmit(deviceHandle, txData, rxData, sizeof(txData)); -``` - -### Transmit-Only Operation - -```cpp -// Send data without receiving -uint8_t command[] = {0xAA, 0x55, 0xFF}; -spi.transmitOnly(deviceHandle, command, sizeof(command)); -``` - -### Receive-Only Operation - -```cpp -// Receive data without sending -uint8_t buffer[10]; -spi.receiveOnly(deviceHandle, buffer, sizeof(buffer)); -``` - -### Command and Address Phases - -```cpp -// Configure device with command and address bits -SpiDeviceConfig config = Spi::getDefaultDeviceConfig(); -config.commandBits = 8; -config.addressBits = 24; -config.csPin = 5; - -spi_device_handle_t device; -spi.addDevice(SpiHost::SPI2_HOST, config, &device); - -// Send command and address with data -uint8_t data[4]; -spi.transmitWithCmdAddr(device, 0x03, 0x000000, nullptr, data, sizeof(data)); -``` - -### Multiple Devices on Same Bus - -```cpp -// Device 1 configuration -SpiDeviceConfig device1Config = Spi::getDefaultDeviceConfig(); -device1Config.csPin = 5; -device1Config.clockSpeedHz = 1000000; - -// Device 2 configuration -SpiDeviceConfig device2Config = Spi::getDefaultDeviceConfig(); -device2Config.csPin = 15; -device2Config.clockSpeedHz = 5000000; -device2Config.mode = SpiMode::MODE_3; - -// Add both devices -spi_device_handle_t device1, device2; -spi.addDevice(SpiHost::SPI2_HOST, device1Config, &device1); -spi.addDevice(SpiHost::SPI2_HOST, device2Config, &device2); - -// Use devices independently -uint8_t data1[] = {0x01, 0x02}; -uint8_t data2[] = {0xAA, 0xBB}; -spi.transmitOnly(device1, data1, sizeof(data1)); -spi.transmitOnly(device2, data2, sizeof(data2)); -``` - -## API Reference - -### Constructor/Destructor - -- **Spi()**: Initialize SPI wrapper instance -- **~Spi()**: Clean up resources and deinitialize all hosts - -### Bus Management - -- **initializeBus(host, config)**: Initialize SPI bus with configuration -- **deinitializeBus(host)**: Deinitialize SPI bus -- **isInitialized(host)**: Check if host is initialized - -### Device Management - -- **addDevice(host, config, handle)**: Add device to SPI bus -- **removeDevice(handle)**: Remove device from SPI bus - -### Data Transfer Methods - -- **transmit(handle, txData, rxData, length)**: Full-duplex transfer -- **transmitOnly(handle, txData, length)**: Transmit-only transfer -- **receiveOnly(handle, rxData, length)**: Receive-only transfer -- **transmitWithCmdAddr(handle, cmd, addr, txData, rxData, length)**: Transfer with command/address - -### Configuration Methods - -- **getDefaultBusConfig()**: Get default bus configuration -- **getDefaultDeviceConfig()**: Get default device configuration - -## Error Handling - -The module provides comprehensive error handling: -- Host validation and initialization checks -- Device handle validation -- ESP-IDF error codes are caught and logged -- Return values indicate success/failure for all operations -- Detailed logging for debugging and troubleshooting - -## Dependencies - -- ESP-IDF SPI master driver (`driver/spi_master.h`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) - -## Thread Safety - -The SPI wrapper uses ESP-IDF's thread-safe SPI master driver. Multiple tasks can safely use different devices on the same bus simultaneously. - -## Memory Usage - -- Fixed memory footprint per instance -- DMA buffers allocated automatically by ESP-IDF -- Transaction queues configurable per device - -## Performance Considerations - -- Direct ESP-IDF function calls for optimal performance -- DMA support for high-speed transfers -- Configurable transaction queue sizes -- Clock speeds up to 80MHz (depending on ESP32 variant) - -## SPI Timing Modes - -| Mode | CPOL | CPHA | Clock Idle | Data Sample Edge | -|------|------|------|------------|------------------| -| 0 | 0 | 0 | Low | Rising | -| 1 | 0 | 1 | Low | Falling | -| 2 | 1 | 0 | High | Falling | -| 3 | 1 | 1 | High | Rising | - -## Common Use Cases - -### Flash Memory -- Command/address phases for read/write operations -- High-speed transfers with DMA -- Mode 0 or Mode 3 typically used - -### Display Controllers -- Command/data distinction using DC pin -- High-speed pixel data transfers -- Various modes depending on controller - -### Sensors -- Register-based communication -- Lower speed requirements -- Mode 0 most common - -## Troubleshooting - -### Common Issues - -1. **Clock Speed**: Ensure clock speed is within device specifications -2. **SPI Mode**: Verify correct CPOL/CPHA settings for device -3. **CS Timing**: Some devices require specific CS setup/hold times -4. **Wire Length**: Long wires can cause signal integrity issues -5. **Pull-up Resistors**: MISO line may need pull-up resistor \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.cpp deleted file mode 100644 index 573446c..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/** - * @file spi.cpp - * @brief SPI wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "spi.hpp" -#include "logger.hpp" -#include "driver/gpio.h" -#include "driver/spi_common.h" -#include "driver/spi_master.h" -#include - -static const char* TAG = "SPI_WRAPPER"; - -Spi::Spi() -{ - m_isInitialized_[0] = false; - m_isInitialized_[1] = false; - m_isInitialized_[2] = false; - ASF_LOGI(TAG, 2500, asf::logger::Criticality::LOW, "SPI wrapper initialized"); -} - -Spi::~Spi() -{ - // Deinitialize all hosts - for (int i = 0; i < 3; i++) { - if (m_isInitialized_[i]) { - deinitializeBus(static_cast(i)); - } - } - ASF_LOGI(TAG, 2501, asf::logger::Criticality::LOW, "SPI wrapper destroyed"); -} - -bool Spi::initializeBus(SpiHost host, const SpiBusConfig& config) -{ - uint8_t hostIdx = static_cast(host); - spi_host_device_t spiHost = convertHost(host); - - if (m_isInitialized_[hostIdx]) { - ASF_LOGW(TAG, 2502, asf::logger::Criticality::MEDIUM, "SPI host %d already initialized", hostIdx); - return true; - } - - // Configure SPI bus - spi_bus_config_t busConfig = convertBusConfig(config); - - esp_err_t ret = spi_bus_initialize(spiHost, &busConfig, SPI_DMA_CH_AUTO); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2503, asf::logger::Criticality::HIGH, "Failed to initialize SPI bus %d: %s", hostIdx, esp_err_to_name(ret)); - return false; - } - - // Enable pull-ups on all SPI lines to ensure signal stability - if (config.misoPin >= 0) { - gpio_set_pull_mode(static_cast(config.misoPin), GPIO_PULLUP_ONLY); - } - if (config.mosiPin >= 0) { - gpio_set_pull_mode(static_cast(config.mosiPin), GPIO_PULLUP_ONLY); - } - if (config.sclkPin >= 0) { - gpio_set_pull_mode(static_cast(config.sclkPin), GPIO_PULLUP_ONLY); - } - - m_isInitialized_[hostIdx] = true; - ASF_LOGI(TAG, 2504, asf::logger::Criticality::LOW, "SPI initialized successfully"); - return true; -} - -bool Spi::deinitializeBus(SpiHost host) -{ - uint8_t hostIdx = static_cast(host); - spi_host_device_t spiHost = convertHost(host); - - if (!m_isInitialized_[hostIdx]) { - ASF_LOGW(TAG, 2505, asf::logger::Criticality::MEDIUM, "SPI host %d not initialized", hostIdx); - return true; - } - - esp_err_t ret = spi_bus_free(spiHost); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2506, asf::logger::Criticality::HIGH, "Failed to free SPI bus %d: %s", hostIdx, esp_err_to_name(ret)); - return false; - } - - m_isInitialized_[hostIdx] = false; - ASF_LOGI(TAG, 2507, asf::logger::Criticality::LOW, "SPI bus %d deinitialized", hostIdx); - return true; -} - -bool Spi::addDevice(SpiHost host, const SpiDeviceConfig& config, spi_device_handle_t* deviceHandle) -{ - uint8_t hostIdx = static_cast(host); - spi_host_device_t spiHost = convertHost(host); - - if (!m_isInitialized_[hostIdx]) { - ASF_LOGE(TAG, 2508, asf::logger::Criticality::HIGH, "SPI host %d not initialized", hostIdx); - return false; - } - - if (deviceHandle == nullptr) { - ASF_LOGE(TAG, 2509, asf::logger::Criticality::HIGH, "Invalid device handle pointer"); - return false; - } - - // Configure SPI device - spi_device_interface_config_t deviceConfig = convertDeviceConfig(config); - - esp_err_t ret = spi_bus_add_device(spiHost, &deviceConfig, deviceHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2510, asf::logger::Criticality::HIGH, "Failed to add SPI device to bus %d: %s", hostIdx, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2511, asf::logger::Criticality::LOW, "SPI device added to bus %d successfully", hostIdx); - return true; -} - -bool Spi::removeDevice(spi_device_handle_t deviceHandle) -{ - if (deviceHandle == nullptr) { - ASF_LOGE(TAG, 2512, asf::logger::Criticality::HIGH, "Invalid device handle"); - return false; - } - - esp_err_t ret = spi_bus_remove_device(deviceHandle); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2513, asf::logger::Criticality::HIGH, "Failed to remove SPI device: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2514, asf::logger::Criticality::LOW, "SPI device removed successfully"); - return true; -} - -int32_t Spi::transmit(spi_device_handle_t deviceHandle, const uint8_t* txData, uint8_t* rxData, size_t length) -{ - if (deviceHandle == nullptr) { - ASF_LOGE(TAG, 2515, asf::logger::Criticality::HIGH, "Invalid device handle"); - return -1; - } - - if (length == 0) { - ASF_LOGW(TAG, 2516, asf::logger::Criticality::MEDIUM, "Zero length transfer"); - return 0; - } - - spi_transaction_t transaction = {}; - transaction.length = length * 8; // Length in bits - transaction.tx_buffer = txData; - transaction.rx_buffer = rxData; - - esp_err_t ret = spi_device_transmit(deviceHandle, &transaction); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2517, asf::logger::Criticality::HIGH, "Failed to transmit SPI data: %s", esp_err_to_name(ret)); - return -1; - } - - return static_cast(length); -} - -int32_t Spi::transmitOnly(spi_device_handle_t deviceHandle, const uint8_t* txData, size_t length) -{ - return transmit(deviceHandle, txData, nullptr, length); -} - -int32_t Spi::receiveOnly(spi_device_handle_t deviceHandle, uint8_t* rxData, size_t length) -{ - return transmit(deviceHandle, nullptr, rxData, length); -} - -int32_t Spi::transmitWithCmdAddr(spi_device_handle_t deviceHandle, uint32_t command, uint32_t address, - const uint8_t* txData, uint8_t* rxData, size_t length) -{ - if (deviceHandle == nullptr) { - ASF_LOGE(TAG, 2518, asf::logger::Criticality::HIGH, "Invalid device handle"); - return -1; - } - - spi_transaction_t transaction = {}; - transaction.cmd = command; - transaction.addr = address; - transaction.length = length * 8; // Length in bits - transaction.tx_buffer = txData; - transaction.rx_buffer = rxData; - - esp_err_t ret = spi_device_transmit(deviceHandle, &transaction); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2519, asf::logger::Criticality::HIGH, "Failed to transmit SPI data with cmd/addr: %s", esp_err_to_name(ret)); - return -1; - } - - return static_cast(length); -} - -bool Spi::isInitialized(SpiHost host) const -{ - uint8_t hostIdx = static_cast(host); - return m_isInitialized_[hostIdx]; -} - -SpiBusConfig Spi::getDefaultBusConfig() -{ - SpiBusConfig config = {}; - config.mosiPin = GPIO_NUM_23; - config.misoPin = GPIO_NUM_19; - config.sclkPin = GPIO_NUM_18; - config.quadwpPin = -1; - config.quadhdPin = -1; - config.maxTransferSize = 4096; - return config; -} - -SpiDeviceConfig Spi::getDefaultDeviceConfig() -{ - SpiDeviceConfig config = {}; - config.csPin = GPIO_NUM_5; - config.clockSpeedHz = 1000000; // 1MHz - config.mode = SpiMode::MODE_0; - config.queueSize = 7; - config.commandBits = 0; - config.addressBits = 0; - config.dummyBits = 0; - config.csEnaPretrans = false; - config.csEnaPosttrans = false; - return config; -} - -spi_host_device_t Spi::convertHost(SpiHost host) -{ - switch (host) { - case SpiHost::SPI1_HOST: - return SPI1_HOST; - case SpiHost::SPI2_HOST: - return SPI2_HOST; - case SpiHost::SPI3_HOST: - return SPI3_HOST; - default: - return SPI2_HOST; - } -} - -spi_bus_config_t Spi::convertBusConfig(const SpiBusConfig& config) -{ - spi_bus_config_t busConfig = {}; - busConfig.mosi_io_num = config.mosiPin; - busConfig.miso_io_num = config.misoPin; - busConfig.sclk_io_num = config.sclkPin; - busConfig.quadwp_io_num = config.quadwpPin; - busConfig.quadhd_io_num = config.quadhdPin; - busConfig.max_transfer_sz = config.maxTransferSize; - busConfig.flags = 0; - busConfig.intr_flags = 0; - return busConfig; -} - -spi_device_interface_config_t Spi::convertDeviceConfig(const SpiDeviceConfig& config) -{ - spi_device_interface_config_t deviceConfig = {}; - deviceConfig.command_bits = config.commandBits; - deviceConfig.address_bits = config.addressBits; - deviceConfig.dummy_bits = config.dummyBits; - deviceConfig.mode = convertMode(config.mode); - deviceConfig.duty_cycle_pos = 0; - deviceConfig.cs_ena_pretrans = config.csEnaPretrans ? 1 : 0; - deviceConfig.cs_ena_posttrans = config.csEnaPosttrans ? 1 : 0; - deviceConfig.clock_speed_hz = config.clockSpeedHz; - deviceConfig.input_delay_ns = 0; - deviceConfig.spics_io_num = config.csPin; - deviceConfig.flags = 0; - deviceConfig.queue_size = config.queueSize; - deviceConfig.pre_cb = nullptr; - deviceConfig.post_cb = nullptr; - return deviceConfig; -} - -uint32_t Spi::convertMode(SpiMode mode) -{ - return static_cast(mode); -} diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.hpp deleted file mode 100644 index feb7ad7..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/com/spi.hpp +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @file spi.hpp - * @brief SPI wrapper component header - Wrapper for ESP-IDF SPI functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef SPI_HPP -#define SPI_HPP - -#include -#include "driver/spi_master.h" -#include "esp_err.h" - -/** - * @brief SPI host enumeration - */ -enum class SpiHost -{ - SPI1_HOST, - SPI2_HOST, - SPI3_HOST -}; - -/** - * @brief SPI mode enumeration - */ -enum class SpiMode -{ - MODE_0, - MODE_1, - MODE_2, - MODE_3 -}; - -/** - * @brief SPI bus configuration structure - */ -struct SpiBusConfig -{ - uint32_t mosiPin; ///< MOSI pin number - uint32_t misoPin; ///< MISO pin number - uint32_t sclkPin; ///< SCLK pin number - uint32_t quadwpPin; ///< Quad SPI write protect pin (optional) - uint32_t quadhdPin; ///< Quad SPI hold pin (optional) - uint32_t maxTransferSize; ///< Maximum transfer size in bytes -}; - -/** - * @brief SPI device configuration structure - */ -struct SpiDeviceConfig -{ - uint32_t csPin; ///< Chip select pin number - uint32_t clockSpeedHz; ///< Clock speed in Hz - SpiMode mode; ///< SPI mode (0-3) - uint32_t queueSize; ///< Transaction queue size - uint32_t commandBits; ///< Command phase bits - uint32_t addressBits; ///< Address phase bits - uint32_t dummyBits; ///< Dummy phase bits - bool csEnaPretrans; ///< CS setup time - bool csEnaPosttrans; ///< CS hold time -}; - -/** - * @brief SPI wrapper class - * - * Provides a C++ wrapper for ESP-IDF SPI functionality. - * This class encapsulates ESP-IDF SPI master driver functions in an object-oriented interface. - */ -class Spi -{ -public: - /** - * @brief Constructor - * @details Initializes the SPI wrapper instance - */ - Spi(); - - /** - * @brief Destructor - * @details Cleans up resources and deinitializes all SPI hosts - */ - ~Spi(); - - /** - * @brief Initialize SPI bus - * @param host SPI host number - * @param config SPI bus configuration - * @return true if initialized successfully, false otherwise - * @note This function configures the SPI bus pins and parameters - */ - bool initializeBus(SpiHost host, const SpiBusConfig& config); - - /** - * @brief Deinitialize SPI bus - * @param host SPI host number - * @return true if deinitialized successfully, false otherwise - */ - bool deinitializeBus(SpiHost host); - - /** - * @brief Add SPI device to bus - * @param host SPI host number - * @param config SPI device configuration - * @param deviceHandle Pointer to store device handle - * @return true if device added successfully, false otherwise - */ - bool addDevice(SpiHost host, const SpiDeviceConfig& config, spi_device_handle_t* deviceHandle); - - /** - * @brief Remove SPI device from bus - * @param deviceHandle Device handle to remove - * @return true if device removed successfully, false otherwise - */ - bool removeDevice(spi_device_handle_t deviceHandle); - - /** - * @brief Transmit and receive data - * @param deviceHandle Device handle - * @param txData Pointer to transmit data - * @param rxData Pointer to receive buffer - * @param length Number of bytes to transfer - * @return Number of bytes transferred, or -1 on error - */ - int32_t transmit(spi_device_handle_t deviceHandle, const uint8_t* txData, uint8_t* rxData, size_t length); - - /** - * @brief Transmit data only - * @param deviceHandle Device handle - * @param txData Pointer to transmit data - * @param length Number of bytes to transmit - * @return Number of bytes transmitted, or -1 on error - */ - int32_t transmitOnly(spi_device_handle_t deviceHandle, const uint8_t* txData, size_t length); - - /** - * @brief Receive data only - * @param deviceHandle Device handle - * @param rxData Pointer to receive buffer - * @param length Number of bytes to receive - * @return Number of bytes received, or -1 on error - */ - int32_t receiveOnly(spi_device_handle_t deviceHandle, uint8_t* rxData, size_t length); - - /** - * @brief Transmit with command and address phases - * @param deviceHandle Device handle - * @param command Command to send - * @param address Address to send - * @param txData Pointer to transmit data - * @param rxData Pointer to receive buffer - * @param length Number of bytes to transfer - * @return Number of bytes transferred, or -1 on error - */ - int32_t transmitWithCmdAddr(spi_device_handle_t deviceHandle, uint32_t command, uint32_t address, - const uint8_t* txData, uint8_t* rxData, size_t length); - - /** - * @brief Check if SPI host is initialized - * @param host SPI host number - * @return true if initialized, false otherwise - */ - bool isInitialized(SpiHost host) const; - - /** - * @brief Get default bus configuration - * @return Default SPI bus configuration structure - */ - static SpiBusConfig getDefaultBusConfig(); - - /** - * @brief Get default device configuration - * @return Default SPI device configuration structure - */ - static SpiDeviceConfig getDefaultDeviceConfig(); - -private: - bool m_isInitialized_[3]; ///< Initialization status for each host - - /** - * @brief Convert SpiHost to ESP-IDF spi_host_device_t - * @param host SPI host - * @return ESP-IDF spi_host_device_t - */ - spi_host_device_t convertHost(SpiHost host); - - /** - * @brief Convert SpiBusConfig to ESP-IDF spi_bus_config_t - * @param config SPI bus configuration - * @return ESP-IDF spi_bus_config_t - */ - spi_bus_config_t convertBusConfig(const SpiBusConfig& config); - - /** - * @brief Convert SpiDeviceConfig to ESP-IDF spi_device_interface_config_t - * @param config SPI device configuration - * @return ESP-IDF spi_device_interface_config_t - */ - spi_device_interface_config_t convertDeviceConfig(const SpiDeviceConfig& config); - - /** - * @brief Convert SpiMode to ESP-IDF mode flags - * @param mode SPI mode - * @return ESP-IDF mode flags - */ - uint32_t convertMode(SpiMode mode); -}; - -#endif // SPI_HPP - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/logging_data.csv deleted file mode 100644 index 3e10de4..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/logging_data.csv +++ /dev/null @@ -1,21 +0,0 @@ -ID,Component,Level,Criticality,Message -2500,SPI,INFO,Low,SPI wrapper initialized -2501,SPI,INFO,Low,SPI wrapper destroyed -2502,SPI,WARNING,Medium,SPI host %d already initialized -2503,SPI,ERROR,High,Failed to initialize SPI bus %d: %s -2504,SPI,INFO,Low,SPI initialized successfully -2505,SPI,WARNING,Medium,SPI host %d not initialized -2506,SPI,ERROR,High,Failed to free SPI bus %d: %s -2507,SPI,INFO,Low,SPI bus %d deinitialized -2508,SPI,ERROR,High,SPI host %d not initialized -2509,SPI,ERROR,High,Invalid device handle pointer -2510,SPI,ERROR,High,Failed to add SPI device to bus %d: %s -2511,SPI,INFO,Low,SPI device added to bus %d successfully -2512,SPI,ERROR,High,Invalid device handle -2513,SPI,ERROR,High,Failed to remove SPI device: %s -2514,SPI,INFO,Low,SPI device removed successfully -2515,SPI,ERROR,High,Invalid device handle -2516,SPI,WARNING,Medium,Zero length transfer -2517,SPI,ERROR,High,Failed to transmit SPI data: %s -2518,SPI,ERROR,High,Invalid device handle -2519,SPI,ERROR,High,Failed to transmit SPI data with cmd/addr: %s diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.py deleted file mode 100644 index a9717c8..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_spi_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "SPI initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_spi_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.test_scenario.xml b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.test_scenario.xml deleted file mode 100644 index 4f21656..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - SPI_INIT_TEST - - python components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.py - - - - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/test_spi.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/test_spi.cpp deleted file mode 100644 index bef29c1..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/spi/test/test_spi.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file test_spi.cpp - * @brief Unit tests for SPI wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "spi.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_spi_initialize(void) -{ - Spi spi; - SpiConfig config = {23, 19, 18, 5, 1000000, SpiMode::MODE_0}; - bool result = spi.initialize(SpiHost::SPI2_HOST, config); - TEST_ASSERT_TRUE(result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/CMakeLists.txt deleted file mode 100644 index 5872296..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/uart.cpp" - INCLUDE_DIRS "com" - REQUIRES esp_driver_uart logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/README.md deleted file mode 100644 index 603bd77..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/README.md +++ /dev/null @@ -1,222 +0,0 @@ -# UART Wrapper Module - -## Overview - -The UART wrapper module provides a C++ object-oriented interface for ESP-IDF UART functionality. This module encapsulates the ESP-IDF UART driver functions and provides a clean, easy-to-use API for serial communication. - -## Features - -- **Multi-Port Support**: Support for UART0, UART1, and UART2 -- **Configurable Parameters**: Baudrate, data bits, parity, stop bits, flow control -- **Buffer Management**: Configurable TX/RX buffer sizes -- **Timeout Support**: Configurable timeouts for read/write operations -- **Flow Control**: Hardware flow control support (RTS/CTS) -- **Error Handling**: Comprehensive error checking and logging - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ Uart │ -├─────────────────────────────────────┤ -│ - m_isInitialized_[3]: bool │ -├─────────────────────────────────────┤ -│ + Uart() │ -│ + ~Uart() │ -│ + initialize(port, config): bool │ -│ + deinitialize(port): bool │ -│ + transmit(...): int32_t │ -│ + receive(...): int32_t │ -│ + getBytesAvailable(port): int32_t │ -│ + flushTx(port): bool │ -│ + flushRx(port): bool │ -│ + setBaudrate(port, baud): bool │ -│ + isInitialized(port): bool │ -│ + getDefaultConfig(): UartConfig │ -│ - convertPort(port): uart_port_t │ -│ - convertConfig(cfg): uart_config_t │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### UartPort -- `PORT_0`: UART port 0 -- `PORT_1`: UART port 1 -- `PORT_2`: UART port 2 - -#### UartBaudrate -- `BAUD_9600`: 9600 bps -- `BAUD_19200`: 19200 bps -- `BAUD_38400`: 38400 bps -- `BAUD_57600`: 57600 bps -- `BAUD_115200`: 115200 bps -- `BAUD_230400`: 230400 bps -- `BAUD_460800`: 460800 bps -- `BAUD_921600`: 921600 bps - -#### UartDataBits -- `DATA_5_BITS`: 5 data bits -- `DATA_6_BITS`: 6 data bits -- `DATA_7_BITS`: 7 data bits -- `DATA_8_BITS`: 8 data bits - -#### UartParity -- `PARITY_DISABLE`: No parity -- `PARITY_EVEN`: Even parity -- `PARITY_ODD`: Odd parity - -#### UartStopBits -- `STOP_BITS_1`: 1 stop bit -- `STOP_BITS_1_5`: 1.5 stop bits -- `STOP_BITS_2`: 2 stop bits - -#### UartFlowControl -- `FLOW_CTRL_DISABLE`: No flow control -- `FLOW_CTRL_RTS`: RTS flow control -- `FLOW_CTRL_CTS`: CTS flow control -- `FLOW_CTRL_CTS_RTS`: RTS/CTS flow control - -### Configuration Structure - -```cpp -struct UartConfig { - UartBaudrate baudrate; // UART baudrate - uint32_t txPin; // TX pin number - uint32_t rxPin; // RX pin number - uint32_t rtsPin; // RTS pin number (optional) - uint32_t ctsPin; // CTS pin number (optional) - UartDataBits dataBits; // Number of data bits - UartParity parity; // Parity setting - UartStopBits stopBits; // Number of stop bits - UartFlowControl flowControl; // Flow control setting - uint32_t rxBufferSize; // RX buffer size - uint32_t txBufferSize; // TX buffer size - uint32_t eventQueueSize; // Event queue size -}; -``` - -## Usage Examples - -### Basic UART Communication - -```cpp -#include "uart.hpp" - -// Create UART instance -Uart uart; - -// Get default configuration -UartConfig config = Uart::getDefaultConfig(); -config.baudrate = UartBaudrate::BAUD_115200; -config.txPin = 1; -config.rxPin = 3; - -// Initialize UART -uart.initialize(UartPort::PORT_0, config); - -// Transmit data -const char* message = "Hello World!"; -uart.transmit(UartPort::PORT_0, (uint8_t*)message, strlen(message)); - -// Receive data -uint8_t buffer[100]; -int32_t bytesReceived = uart.receive(UartPort::PORT_0, buffer, sizeof(buffer), 1000); -``` - -### Advanced Configuration - -```cpp -// Configure UART with flow control -UartConfig config = {}; -config.baudrate = UartBaudrate::BAUD_921600; -config.txPin = 4; -config.rxPin = 5; -config.rtsPin = 18; -config.ctsPin = 19; -config.dataBits = UartDataBits::DATA_8_BITS; -config.parity = UartParity::PARITY_EVEN; -config.stopBits = UartStopBits::STOP_BITS_2; -config.flowControl = UartFlowControl::FLOW_CTRL_CTS_RTS; -config.rxBufferSize = 2048; -config.txBufferSize = 2048; - -uart.initialize(UartPort::PORT_1, config); -``` - -### Buffer Management - -```cpp -// Check available bytes -int32_t available = uart.getBytesAvailable(UartPort::PORT_0); - -// Flush buffers -uart.flushRx(UartPort::PORT_0); -uart.flushTx(UartPort::PORT_0); - -// Change baudrate at runtime -uart.setBaudrate(UartPort::PORT_0, UartBaudrate::BAUD_460800); -``` - -## API Reference - -### Constructor/Destructor - -- **Uart()**: Initialize UART wrapper instance -- **~Uart()**: Clean up resources and deinitialize all ports - -### Configuration Methods - -- **initialize(port, config)**: Initialize UART port with configuration -- **deinitialize(port)**: Deinitialize UART port -- **isInitialized(port)**: Check if port is initialized -- **getDefaultConfig()**: Get default configuration structure - -### Communication Methods - -- **transmit(port, data, length, timeout)**: Transmit data with timeout -- **receive(port, buffer, maxLength, timeout)**: Receive data with timeout -- **getBytesAvailable(port)**: Get number of bytes in RX buffer - -### Buffer Management - -- **flushTx(port)**: Flush TX buffer -- **flushRx(port)**: Flush RX buffer - -### Runtime Configuration - -- **setBaudrate(port, baudrate)**: Change baudrate at runtime - -## Error Handling - -The module provides comprehensive error handling: -- Port validation and initialization checks -- ESP-IDF error codes are caught and logged -- Return values indicate success/failure for all operations -- Detailed logging for debugging and troubleshooting - -## Dependencies - -- ESP-IDF UART driver (`driver/uart.h`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) -- FreeRTOS (`freertos/FreeRTOS.h`, `freertos/task.h`) - -## Thread Safety - -The UART wrapper uses ESP-IDF's thread-safe UART driver. Multiple tasks can safely use different UART ports simultaneously. - -## Memory Usage - -- Fixed memory footprint per instance -- Configurable buffer sizes for each port -- No dynamic memory allocation in wrapper layer - -## Performance Considerations - -- Direct ESP-IDF function calls for optimal performance -- Minimal overhead over raw ESP-IDF calls -- Configurable buffer sizes for throughput optimization -- Hardware flow control support for high-speed communication \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.cpp deleted file mode 100644 index b65a7c0..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/** - * @file uart.cpp - * @brief UART wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "uart.hpp" -#include "logger.hpp" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include -#include - -static const char* TAG = "UART_WRAPPER"; - -/** - * @brief Constructor - Initialize UART wrapper instance - * @details Initializes all UART ports as not initialized - */ -Uart::Uart() -{ - m_isInitialized_[0] = false; - m_isInitialized_[1] = false; - m_isInitialized_[2] = false; - ASF_LOGI(TAG, 2600, asf::logger::Criticality::LOW, "UART wrapper initialized"); -} - -/** - * @brief Destructor - Clean up UART wrapper resources - * @details Deinitializes all active UART ports - */ -Uart::~Uart() -{ - // Deinitialize all ports - for (int i = 0; i < 3; i++) { - if (m_isInitialized_[i]) { - deinitialize(static_cast(i)); - } - } - ASF_LOGI(TAG, 2601, asf::logger::Criticality::LOW, "UART wrapper destroyed"); -} - -bool Uart::initialize(UartPort port, const UartConfig& config) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (m_isInitialized_[portIdx]) { - ASF_LOGW(TAG, 2602, asf::logger::Criticality::MEDIUM, "UART port %d already initialized", portIdx); - return true; - } - - // Configure UART parameters - uart_config_t uartConfig = convertConfig(config); - - esp_err_t ret = uart_param_config(uartPort, &uartConfig); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2603, asf::logger::Criticality::HIGH, "Failed to configure UART port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - // Set UART pins - ret = uart_set_pin(uartPort, config.txPin, config.rxPin, - config.rtsPin, config.ctsPin); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2604, asf::logger::Criticality::HIGH, "Failed to set UART pins for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - // Install UART driver - ret = uart_driver_install(uartPort, config.rxBufferSize, config.txBufferSize, - config.eventQueueSize, nullptr, 0); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2605, asf::logger::Criticality::HIGH, "Failed to install UART driver for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - m_isInitialized_[portIdx] = true; - ASF_LOGI(TAG, 2606, asf::logger::Criticality::LOW, "UART initialized successfully"); - return true; -} - -bool Uart::deinitialize(UartPort port) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGW(TAG, 2607, asf::logger::Criticality::MEDIUM, "UART port %d not initialized", portIdx); - return true; - } - - esp_err_t ret = uart_driver_delete(uartPort); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2608, asf::logger::Criticality::HIGH, "Failed to delete UART driver for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - m_isInitialized_[portIdx] = false; - ASF_LOGI(TAG, 2609, asf::logger::Criticality::LOW, "UART port %d deinitialized", portIdx); - return true; -} - -int32_t Uart::transmit(UartPort port, const uint8_t* data, size_t length, uint32_t timeoutMs) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2610, asf::logger::Criticality::HIGH, "UART port %d not initialized", portIdx); - return -1; - } - - if (data == nullptr || length == 0) { - ASF_LOGE(TAG, 2611, asf::logger::Criticality::HIGH, "Invalid data or length"); - return -1; - } - - TickType_t timeout = pdMS_TO_TICKS(timeoutMs); - int bytesWritten = uart_write_bytes(uartPort, data, length); - - if (bytesWritten < 0) { - ASF_LOGE(TAG, 2612, asf::logger::Criticality::HIGH, "Failed to write to UART port %d", portIdx); - return -1; - } - - // Wait for transmission to complete - esp_err_t ret = uart_wait_tx_done(uartPort, timeout); - if (ret != ESP_OK) { - ASF_LOGW(TAG, 2613, asf::logger::Criticality::MEDIUM, "TX timeout for UART port %d", portIdx); - } - - return bytesWritten; -} - -int32_t Uart::receive(UartPort port, uint8_t* data, size_t maxLength, uint32_t timeoutMs) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2614, asf::logger::Criticality::HIGH, "UART port %d not initialized", portIdx); - return -1; - } - - if (data == nullptr || maxLength == 0) { - ASF_LOGE(TAG, 2615, asf::logger::Criticality::HIGH, "Invalid data buffer or length"); - return -1; - } - - TickType_t timeout = pdMS_TO_TICKS(timeoutMs); - int bytesRead = uart_read_bytes(uartPort, data, maxLength, timeout); - - if (bytesRead < 0) { - ASF_LOGE(TAG, 2616, asf::logger::Criticality::HIGH, "Failed to read from UART port %d", portIdx); - return -1; - } - - return bytesRead; -} - -int32_t Uart::getBytesAvailable(UartPort port) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2617, asf::logger::Criticality::HIGH, "UART port %d not initialized", portIdx); - return -1; - } - - size_t bytesAvailable = 0; - esp_err_t ret = uart_get_buffered_data_len(uartPort, &bytesAvailable); - - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2618, asf::logger::Criticality::HIGH, "Failed to get buffered data length for port %d: %s", - portIdx, esp_err_to_name(ret)); - return -1; - } - - return static_cast(bytesAvailable); -} - -bool Uart::flushTx(UartPort port) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2619, asf::logger::Criticality::HIGH, "UART port %d not initialized", portIdx); - return false; - } - - esp_err_t ret = uart_flush_input(uartPort); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2620, asf::logger::Criticality::HIGH, "Failed to flush TX for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - return true; -} - -bool Uart::flushRx(UartPort port) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2621, asf::logger::Criticality::HIGH, "UART port %d not initialized", portIdx); - return false; - } - - esp_err_t ret = uart_flush_input(uartPort); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2622, asf::logger::Criticality::HIGH, "Failed to flush RX for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - return true; -} - -bool Uart::setBaudrate(UartPort port, UartBaudrate baudrate) -{ - uint8_t portIdx = static_cast(port); - uart_port_t uartPort = convertPort(port); - - if (!m_isInitialized_[portIdx]) { - ASF_LOGE(TAG, 2623, asf::logger::Criticality::HIGH, "UART port %d not initialized", portIdx); - return false; - } - - esp_err_t ret = uart_set_baudrate(uartPort, static_cast(baudrate)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2624, asf::logger::Criticality::HIGH, "Failed to set baudrate for port %d: %s", portIdx, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2625, asf::logger::Criticality::LOW, "Baudrate set to %" PRIu32 " for port %d", static_cast(baudrate), portIdx); - return true; -} - -bool Uart::isInitialized(UartPort port) const -{ - uint8_t portIdx = static_cast(port); - return m_isInitialized_[portIdx]; -} - -UartConfig Uart::getDefaultConfig() -{ - UartConfig config = {}; - config.baudrate = UartBaudrate::BAUD_115200; - config.txPin = UART_PIN_NO_CHANGE; - config.rxPin = UART_PIN_NO_CHANGE; - config.rtsPin = UART_PIN_NO_CHANGE; - config.ctsPin = UART_PIN_NO_CHANGE; - config.dataBits = UartDataBits::DATA_8_BITS; - config.parity = UartParity::PARITY_DISABLE; - config.stopBits = UartStopBits::STOP_BITS_1; - config.flowControl = UartFlowControl::FLOW_CTRL_DISABLE; - config.rxBufferSize = 1024; - config.txBufferSize = 1024; - config.eventQueueSize = 10; - return config; -} - -uart_port_t Uart::convertPort(UartPort port) -{ - switch (port) { - case UartPort::PORT_0: - return UART_NUM_0; - case UartPort::PORT_1: - return UART_NUM_1; - case UartPort::PORT_2: - return UART_NUM_2; - default: - return UART_NUM_0; - } -} - -uart_config_t Uart::convertConfig(const UartConfig& config) -{ - uart_config_t uartConfig = {}; - uartConfig.baud_rate = static_cast(config.baudrate); - uartConfig.data_bits = static_cast(config.dataBits); - uartConfig.parity = static_cast(config.parity); - uartConfig.stop_bits = static_cast(config.stopBits); - uartConfig.flow_ctrl = static_cast(config.flowControl); - uartConfig.rx_flow_ctrl_thresh = 122; - uartConfig.source_clk = UART_SCLK_DEFAULT; - return uartConfig; -} diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.hpp deleted file mode 100644 index 152a714..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/com/uart.hpp +++ /dev/null @@ -1,220 +0,0 @@ -/** - * @file uart.hpp - * @brief UART wrapper component header - Wrapper for ESP-IDF UART functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef UART_HPP -#define UART_HPP - -#include -#include "driver/uart.h" -#include "esp_err.h" - -/** - * @brief UART port enumeration - */ -enum class UartPort -{ - PORT_0, - PORT_1, - PORT_2 -}; - -/** - * @brief UART baudrate enumeration - */ -enum class UartBaudrate -{ - BAUD_9600 = 9600, - BAUD_19200 = 19200, - BAUD_38400 = 38400, - BAUD_57600 = 57600, - BAUD_115200 = 115200, - BAUD_230400 = 230400, - BAUD_460800 = 460800, - BAUD_921600 = 921600 -}; - -/** - * @brief UART data bits enumeration - */ -enum class UartDataBits -{ - DATA_5_BITS = UART_DATA_5_BITS, - DATA_6_BITS = UART_DATA_6_BITS, - DATA_7_BITS = UART_DATA_7_BITS, - DATA_8_BITS = UART_DATA_8_BITS -}; - -/** - * @brief UART parity enumeration - */ -enum class UartParity -{ - PARITY_DISABLE = UART_PARITY_DISABLE, - PARITY_EVEN = UART_PARITY_EVEN, - PARITY_ODD = UART_PARITY_ODD -}; - -/** - * @brief UART stop bits enumeration - */ -enum class UartStopBits -{ - STOP_BITS_1 = UART_STOP_BITS_1, - STOP_BITS_1_5 = UART_STOP_BITS_1_5, - STOP_BITS_2 = UART_STOP_BITS_2 -}; - -/** - * @brief UART flow control enumeration - */ -enum class UartFlowControl -{ - FLOW_CTRL_DISABLE = UART_HW_FLOWCTRL_DISABLE, - FLOW_CTRL_RTS = UART_HW_FLOWCTRL_RTS, - FLOW_CTRL_CTS = UART_HW_FLOWCTRL_CTS, - FLOW_CTRL_CTS_RTS = UART_HW_FLOWCTRL_CTS_RTS -}; - -/** - * @brief UART configuration structure - */ -struct UartConfig -{ - UartBaudrate baudrate; ///< UART baudrate - uint32_t txPin; ///< TX pin number - uint32_t rxPin; ///< RX pin number - uint32_t rtsPin; ///< RTS pin number (optional) - uint32_t ctsPin; ///< CTS pin number (optional) - UartDataBits dataBits; ///< Number of data bits - UartParity parity; ///< Parity setting - UartStopBits stopBits; ///< Number of stop bits - UartFlowControl flowControl; ///< Flow control setting - uint32_t rxBufferSize; ///< RX buffer size - uint32_t txBufferSize; ///< TX buffer size - uint32_t eventQueueSize; ///< Event queue size -}; - -/** - * @brief UART wrapper class - * - * Provides a C++ wrapper for ESP-IDF UART functionality. - * This class encapsulates ESP-IDF UART driver functions in an object-oriented interface. - */ -class Uart -{ -public: - /** - * @brief Constructor - * @details Initializes the UART wrapper instance - */ - Uart(); - - /** - * @brief Destructor - * @details Cleans up resources and deinitializes all UART ports - */ - ~Uart(); - - /** - * @brief Initialize UART port with configuration - * @param port UART port number - * @param config UART configuration parameters - * @return true if initialized successfully, false otherwise - * @note This function configures pins, baudrate, and buffer sizes - */ - bool initialize(UartPort port, const UartConfig& config); - - /** - * @brief Deinitialize UART port - * @param port UART port number - * @return true if deinitialized successfully, false otherwise - */ - bool deinitialize(UartPort port); - - /** - * @brief Transmit data over UART - * @param port UART port number - * @param data Pointer to data buffer - * @param length Number of bytes to transmit - * @param timeoutMs Timeout in milliseconds (default: 1000ms) - * @return Number of bytes transmitted, or -1 on error - */ - int32_t transmit(UartPort port, const uint8_t* data, size_t length, uint32_t timeoutMs = 1000); - - /** - * @brief Receive data from UART - * @param port UART port number - * @param data Pointer to receive buffer - * @param maxLength Maximum number of bytes to receive - * @param timeoutMs Timeout in milliseconds - * @return Number of bytes received, or -1 on error - */ - int32_t receive(UartPort port, uint8_t* data, size_t maxLength, uint32_t timeoutMs); - - /** - * @brief Get number of bytes available in RX buffer - * @param port UART port number - * @return Number of bytes available, or -1 on error - */ - int32_t getBytesAvailable(UartPort port); - - /** - * @brief Flush UART TX buffer - * @param port UART port number - * @return true if flushed successfully, false otherwise - */ - bool flushTx(UartPort port); - - /** - * @brief Flush UART RX buffer - * @param port UART port number - * @return true if flushed successfully, false otherwise - */ - bool flushRx(UartPort port); - - /** - * @brief Set UART baudrate - * @param port UART port number - * @param baudrate New baudrate - * @return true if set successfully, false otherwise - */ - bool setBaudrate(UartPort port, UartBaudrate baudrate); - - /** - * @brief Check if UART port is initialized - * @param port UART port number - * @return true if initialized, false otherwise - */ - bool isInitialized(UartPort port) const; - - /** - * @brief Get default UART configuration - * @return Default UART configuration structure - */ - static UartConfig getDefaultConfig(); - -private: - bool m_isInitialized_[3]; ///< Initialization status for each port - - /** - * @brief Convert UartPort to ESP-IDF uart_port_t - * @param port UART port - * @return ESP-IDF uart_port_t - */ - uart_port_t convertPort(UartPort port); - - /** - * @brief Convert UartConfig to ESP-IDF uart_config_t - * @param config UART configuration - * @return ESP-IDF uart_config_t - */ - uart_config_t convertConfig(const UartConfig& config); -}; - -#endif // UART_HPP - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/logging_data.csv deleted file mode 100644 index b9d2b32..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/logging_data.csv +++ /dev/null @@ -1,27 +0,0 @@ -ID,Component,Level,Criticality,Message -2600,UART,INFO,Low,UART wrapper initialized -2601,UART,INFO,Low,UART wrapper destroyed -2602,UART,WARNING,Medium,UART port %d already initialized -2603,UART,ERROR,High,Failed to configure UART port %d: %s -2604,UART,ERROR,High,Failed to set UART pins for port %d: %s -2605,UART,ERROR,High,Failed to install UART driver for port %d: %s -2606,UART,INFO,Low,UART initialized successfully -2607,UART,WARNING,Medium,UART port %d not initialized -2608,UART,ERROR,High,Failed to delete UART driver for port %d: %s -2609,UART,INFO,Low,UART port %d deinitialized -2610,UART,ERROR,High,UART port %d not initialized -2611,UART,ERROR,High,Invalid data or length -2612,UART,ERROR,High,Failed to write to UART port %d -2613,UART,WARNING,Medium,TX timeout for UART port %d -2614,UART,ERROR,High,UART port %d not initialized -2615,UART,ERROR,High,Invalid data buffer or length -2616,UART,ERROR,High,Failed to read from UART port %d -2617,UART,ERROR,High,UART port %d not initialized -2618,UART,ERROR,High,Failed to get buffered data length for port %d: %s -2619,UART,ERROR,High,UART port %d not initialized -2620,UART,ERROR,High,Failed to flush TX for port %d: %s -2621,UART,ERROR,High,UART port %d not initialized -2622,UART,ERROR,High,Failed to flush RX for port %d: %s -2623,UART,ERROR,High,UART port %d not initialized -2624,UART,ERROR,High,Failed to set baudrate for port %d: %s -2625,UART,INFO,Low,Baudrate set to %" PRIu32 " for port %d diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/test_uart.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/test_uart.cpp deleted file mode 100644 index 1b4a53e..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/test_uart.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file test_uart.cpp - * @brief Unit tests for UART wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "uart.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_uart_initialize(void) -{ - Uart uart; - UartConfig config = {UartBaudrate::BAUD_115200, 17, 16, 8, 0, 1, 0}; - bool result = uart.initialize(UartPort::PORT_0, config); - TEST_ASSERT_TRUE(result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.py deleted file mode 100644 index f760114..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_UART_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "UART initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_UART_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.test_scenario.xml b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.test_scenario.xml deleted file mode 100644 index bd371e4..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - UART_INIT_TEST - - python components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.py - - - - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/CMakeLists.txt b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/CMakeLists.txt deleted file mode 100644 index a43bd23..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/wifi.cpp" - INCLUDE_DIRS "com" - REQUIRES esp_wifi esp_netif nvs_flash logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/README.md b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/README.md deleted file mode 100644 index 6f04408..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/README.md +++ /dev/null @@ -1,323 +0,0 @@ -# WiFi Wrapper Module - -## Overview - -The WiFi wrapper module provides a C++ object-oriented interface for ESP-IDF WiFi functionality. This module encapsulates the ESP-IDF WiFi driver functions and provides a clean, easy-to-use API for WiFi station and access point operations. - -## Features - -- **Multiple Modes**: Station (STA), Access Point (AP), and combined (AP+STA) modes -- **Network Scanning**: Scan for available WiFi networks -- **Event Handling**: Asynchronous event callbacks for connection status -- **Security Support**: Multiple authentication modes (Open, WEP, WPA/WPA2/WPA3) -- **Network Information**: IP address, MAC address, RSSI retrieval -- **AP Management**: Connected stations monitoring in AP mode -- **Error Handling**: Comprehensive error checking and logging - -## Architecture - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ Wifi │ -├─────────────────────────────────────┤ -│ - m_isInitialized_: bool │ -│ - m_connectionStatus_: Status │ -│ - m_config_: WifiConfig │ -│ - m_netifSta_: esp_netif_t* │ -│ - m_netifAp_: esp_netif_t* │ -│ - m_eventCallback_: Callback │ -│ - m_eventCallbackArg_: void* │ -├─────────────────────────────────────┤ -│ + Wifi() │ -│ + ~Wifi() │ -│ + initialize(config): bool │ -│ + deinitialize(): bool │ -│ + start(): bool │ -│ + stop(): bool │ -│ + connect(): bool │ -│ + disconnect(): bool │ -│ + scan(...): int32_t │ -│ + getConnectionStatus(): Status │ -│ + isConnected(): bool │ -│ + getRssi(): int32_t │ -│ + getIpAddress(ip, len): bool │ -│ + getMacAddress(mac, mode): bool │ -│ + setEventCallback(cb, arg): void │ -│ + getConnectedStations(): int32_t │ -│ + isInitialized(): bool │ -│ + getDefaultStaConfig(): StaConfig │ -│ + getDefaultApConfig(): ApConfig │ -│ - convertMode(mode): wifi_mode_t │ -│ - convertAuthMode(auth): wifi_auth │ -│ - wifiEventHandler(...): void │ -│ - ipEventHandler(...): void │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### WifiMode -- `NONE`: WiFi disabled -- `STA`: Station mode (client) -- `AP`: Access Point mode (server) -- `APSTA`: Combined AP + STA mode - -#### WifiAuthMode -- `OPEN`: No authentication -- `WEP`: WEP encryption -- `WPA_PSK`: WPA with pre-shared key -- `WPA2_PSK`: WPA2 with pre-shared key -- `WPA_WPA2_PSK`: WPA/WPA2 mixed mode -- `WPA3_PSK`: WPA3 with pre-shared key -- `WPA2_WPA3_PSK`: WPA2/WPA3 mixed mode - -#### WifiConnectionStatus -- `DISCONNECTED`: Not connected -- `CONNECTING`: Connection in progress -- `CONNECTED`: Successfully connected -- `FAILED`: Connection failed - -### Configuration Structures - -#### WifiStaConfig -```cpp -struct WifiStaConfig { - char ssid[32]; // SSID of target AP - char password[64]; // Password of target AP - WifiAuthMode authMode; // Authentication mode - bool pmfRequired; // Protected Management Frame required - uint8_t channel; // Channel of target AP (0 = auto) - int8_t rssiThreshold; // Minimum RSSI threshold -}; -``` - -#### WifiApConfig -```cpp -struct WifiApConfig { - char ssid[32]; // SSID of AP - char password[64]; // Password of AP - WifiAuthMode authMode; // Authentication mode - uint8_t channel; // Channel number - uint8_t maxConnections; // Maximum number of connections - bool ssidHidden; // Hide SSID -}; -``` - -#### WifiConfig -```cpp -struct WifiConfig { - WifiMode mode; // WiFi mode - WifiStaConfig staConfig; // Station configuration - WifiApConfig apConfig; // Access Point configuration -}; -``` - -## Usage Examples - -### Station Mode (Client) - -```cpp -#include "wifi.hpp" - -// WiFi event callback -void wifiEventCallback(WifiConnectionStatus status, void* arg) { - switch (status) { - case WifiConnectionStatus::CONNECTED: - printf("WiFi connected!\n"); - break; - case WifiConnectionStatus::DISCONNECTED: - printf("WiFi disconnected!\n"); - break; - default: - break; - } -} - -// Create WiFi instance -Wifi wifi; - -// Configure WiFi -WifiConfig config = {}; -config.mode = WifiMode::STA; -config.staConfig = Wifi::getDefaultStaConfig(); -strcpy(config.staConfig.ssid, "MyWiFiNetwork"); -strcpy(config.staConfig.password, "MyPassword"); -config.staConfig.authMode = WifiAuthMode::WPA2_PSK; - -// Set event callback -wifi.setEventCallback(wifiEventCallback, nullptr); - -// Initialize and start WiFi -wifi.initialize(config); -wifi.start(); -wifi.connect(); - -// Get IP address when connected -char ip[16]; -if (wifi.getIpAddress(ip, sizeof(ip))) { - printf("IP Address: %s\n", ip); -} -``` - -### Access Point Mode (Server) - -```cpp -// Configure as Access Point -WifiConfig apConfig = {}; -apConfig.mode = WifiMode::AP; -apConfig.apConfig = Wifi::getDefaultApConfig(); -strcpy(apConfig.apConfig.ssid, "ESP32-Hotspot"); -strcpy(apConfig.apConfig.password, "12345678"); -apConfig.apConfig.authMode = WifiAuthMode::WPA2_PSK; -apConfig.apConfig.channel = 6; -apConfig.apConfig.maxConnections = 4; - -wifi.initialize(apConfig); -wifi.start(); - -// Monitor connected stations -int32_t connectedStations = wifi.getConnectedStations(); -printf("Connected stations: %ld\n", connectedStations); -``` - -### Network Scanning - -```cpp -// Scan for available networks -WifiScanResult results[20]; -int32_t networkCount = wifi.scan(results, 20, 5000); // 5 second scan - -printf("Found %ld networks:\n", networkCount); -for (int i = 0; i < networkCount; i++) { - printf("SSID: %s, RSSI: %d dBm, Channel: %d\n", - results[i].ssid, results[i].rssi, results[i].channel); -} -``` - -### Combined AP+STA Mode - -```cpp -WifiConfig combinedConfig = {}; -combinedConfig.mode = WifiMode::APSTA; - -// Configure STA -combinedConfig.staConfig = Wifi::getDefaultStaConfig(); -strcpy(combinedConfig.staConfig.ssid, "InternetRouter"); -strcpy(combinedConfig.staConfig.password, "RouterPassword"); - -// Configure AP -combinedConfig.apConfig = Wifi::getDefaultApConfig(); -strcpy(combinedConfig.apConfig.ssid, "ESP32-Bridge"); -strcpy(combinedConfig.apConfig.password, "BridgePassword"); - -wifi.initialize(combinedConfig); -wifi.start(); -wifi.connect(); // Connect to internet router -``` - -## API Reference - -### Constructor/Destructor - -- **Wifi()**: Initialize WiFi wrapper instance -- **~Wifi()**: Clean up resources and deinitialize WiFi - -### Initialization Methods - -- **initialize(config)**: Initialize WiFi with configuration -- **deinitialize()**: Deinitialize WiFi and clean up resources -- **isInitialized()**: Check if WiFi is initialized - -### Control Methods - -- **start()**: Start WiFi (required after initialization) -- **stop()**: Stop WiFi operations -- **connect()**: Connect to network (STA mode) -- **disconnect()**: Disconnect from network - -### Information Methods - -- **getConnectionStatus()**: Get current connection status -- **isConnected()**: Check if connected to network -- **getRssi()**: Get signal strength of current connection -- **getIpAddress(ip, maxLen)**: Get IP address string -- **getMacAddress(mac, mode)**: Get MAC address - -### Scanning Methods - -- **scan(results, maxResults, scanTimeMs)**: Scan for available networks - -### Event Handling - -- **setEventCallback(callback, arg)**: Set connection event callback - -### Access Point Methods - -- **getConnectedStations()**: Get number of connected stations (AP mode) - -### Configuration Methods - -- **getDefaultStaConfig()**: Get default station configuration -- **getDefaultApConfig()**: Get default AP configuration - -## Error Handling - -The module provides comprehensive error handling: -- Initialization status checks -- ESP-IDF error codes are caught and logged -- Return values indicate success/failure for all operations -- Event callbacks for asynchronous status updates -- Detailed logging for debugging and troubleshooting - -## Dependencies - -- ESP-IDF WiFi driver (`esp_wifi.h`) -- ESP-IDF network interface (`esp_netif.h`) -- ESP-IDF event system (`esp_event.h`) -- NVS flash storage (`nvs_flash.h`) -- ESP-IDF error handling (`esp_err.h`) -- ESP-IDF logging (`esp_log.h`) - -## Thread Safety - -The WiFi wrapper uses ESP-IDF's thread-safe WiFi driver and event system. Multiple tasks can safely call WiFi functions simultaneously. - -## Memory Usage - -- Fixed memory footprint per instance -- Network interface handles managed by ESP-IDF -- Event system uses minimal memory for callbacks - -## Performance Considerations - -- Asynchronous connection process with event callbacks -- Network scanning can take several seconds -- WiFi operations may affect other radio functions (Bluetooth) -- Power management considerations for battery-powered devices - -## Security Considerations - -- Use WPA2 or WPA3 for secure connections -- Avoid WEP encryption (deprecated and insecure) -- Use strong passwords (minimum 8 characters) -- Consider hiding SSID for AP mode (security through obscurity) -- Enable PMF (Protected Management Frames) when supported - -## Power Management - -- WiFi can be configured for power saving modes -- AP mode typically consumes more power than STA mode -- Consider WiFi sleep modes for battery-powered applications -- Monitor power consumption in different WiFi modes - -## Troubleshooting - -### Common Issues - -1. **Connection Failures**: Check SSID, password, and authentication mode -2. **Weak Signal**: Monitor RSSI values and consider antenna placement -3. **IP Assignment**: Ensure DHCP is working or configure static IP -4. **Channel Conflicts**: Use WiFi analyzer to find less congested channels -5. **Memory Issues**: Monitor heap usage, especially with many connections \ No newline at end of file diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.cpp deleted file mode 100644 index 68b7efc..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.cpp +++ /dev/null @@ -1,501 +0,0 @@ -/** - * @file wifi.cpp - * @brief WiFi wrapper component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "wifi.hpp" -#include "logger.hpp" -#include "nvs_flash.h" -#include - -static const char* TAG = "WIFI_WRAPPER"; - -Wifi::Wifi() - : m_isInitialized_(false) - , m_connectionStatus_(WifiConnectionStatus::DISCONNECTED) - , m_netifSta_(nullptr) - , m_netifAp_(nullptr) - , m_eventCallback_(nullptr) - , m_eventCallbackArg_(nullptr) -{ - memset(&m_config_, 0, sizeof(m_config_)); - ASF_LOGI(TAG, 2700, asf::logger::Criticality::LOW, "WiFi wrapper initialized"); -} - -Wifi::~Wifi() -{ - deinitialize(); - ASF_LOGI(TAG, 2701, asf::logger::Criticality::LOW, "WiFi wrapper destroyed"); -} - -bool Wifi::initialize(const WifiConfig& config) -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (m_isInitialized_) { - ASF_LOGW(TAG, 2702, asf::logger::Criticality::MEDIUM, "WiFi already initialized"); - return true; - } - - // Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - // Initialize TCP/IP stack - ESP_ERROR_CHECK(esp_netif_init()); - - // Create default event loop - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - // Create network interfaces - if (config.mode == WifiMode::STA || config.mode == WifiMode::APSTA) { - m_netifSta_ = esp_netif_create_default_wifi_sta(); - } - - if (config.mode == WifiMode::AP || config.mode == WifiMode::APSTA) { - m_netifAp_ = esp_netif_create_default_wifi_ap(); - } - - // Initialize WiFi - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - - // Register event handlers - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, - &wifiEventHandler, this)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, - &ipEventHandler, this)); - - // Set WiFi mode - ESP_ERROR_CHECK(esp_wifi_set_mode(convertMode(config.mode))); - - // Configure WiFi - if (config.mode == WifiMode::STA || config.mode == WifiMode::APSTA) { - wifi_config_t staConfig = {}; - strncpy((char*)staConfig.sta.ssid, config.staConfig.ssid, sizeof(staConfig.sta.ssid) - 1); - strncpy((char*)staConfig.sta.password, config.staConfig.password, sizeof(staConfig.sta.password) - 1); - staConfig.sta.threshold.authmode = convertAuthMode(config.staConfig.authMode); - staConfig.sta.pmf_cfg.required = config.staConfig.pmfRequired; - - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &staConfig)); - } - - if (config.mode == WifiMode::AP || config.mode == WifiMode::APSTA) { - wifi_config_t apConfig = {}; - strncpy((char*)apConfig.ap.ssid, config.apConfig.ssid, sizeof(apConfig.ap.ssid) - 1); - strncpy((char*)apConfig.ap.password, config.apConfig.password, sizeof(apConfig.ap.password) - 1); - apConfig.ap.ssid_len = strlen(config.apConfig.ssid); - apConfig.ap.channel = config.apConfig.channel; - apConfig.ap.max_connection = config.apConfig.maxConnections; - apConfig.ap.authmode = convertAuthMode(config.apConfig.authMode); - apConfig.ap.ssid_hidden = config.apConfig.ssidHidden ? 1 : 0; - - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &apConfig)); - } - - m_config_ = config; - m_isInitialized_ = true; - ASF_LOGI(TAG, 2703, asf::logger::Criticality::LOW, "WiFi initialized successfully"); - return true; -#else - ASF_LOGW(TAG, 2704, asf::logger::Criticality::MEDIUM, "WiFi disabled in sdkconfig"); - return false; -#endif -} - -bool Wifi::deinitialize() -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!m_isInitialized_) { - ASF_LOGW(TAG, 2705, asf::logger::Criticality::MEDIUM, "WiFi not initialized"); - return true; - } - - stop(); - - // Unregister event handlers - esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifiEventHandler); - esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &ipEventHandler); - - // Deinitialize WiFi - esp_wifi_deinit(); - - // Destroy network interfaces - if (m_netifSta_) { - esp_netif_destroy_default_wifi(m_netifSta_); - m_netifSta_ = nullptr; - } - - if (m_netifAp_) { - esp_netif_destroy_default_wifi(m_netifAp_); - m_netifAp_ = nullptr; - } - - m_isInitialized_ = false; - m_connectionStatus_ = WifiConnectionStatus::DISCONNECTED; - ASF_LOGI(TAG, 2706, asf::logger::Criticality::LOW, "WiFi deinitialized"); - return true; -#else - return true; -#endif -} - -bool Wifi::start() -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2707, asf::logger::Criticality::HIGH, "WiFi not initialized"); - return false; - } - - esp_err_t ret = esp_wifi_start(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2708, asf::logger::Criticality::HIGH, "Failed to start WiFi: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2709, asf::logger::Criticality::LOW, "WiFi started"); - return true; -#else - return false; -#endif -} - -bool Wifi::stop() -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!m_isInitialized_) { - ASF_LOGW(TAG, 2710, asf::logger::Criticality::MEDIUM, "WiFi not initialized"); - return true; - } - - esp_err_t ret = esp_wifi_stop(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2711, asf::logger::Criticality::HIGH, "Failed to stop WiFi: %s", esp_err_to_name(ret)); - return false; - } - - m_connectionStatus_ = WifiConnectionStatus::DISCONNECTED; - ASF_LOGI(TAG, 2712, asf::logger::Criticality::LOW, "WiFi stopped"); - return true; -#else - return true; -#endif -} - -bool Wifi::connect() -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!m_isInitialized_) { - ASF_LOGE(TAG, 2713, asf::logger::Criticality::HIGH, "WiFi not initialized"); - return false; - } - - if (m_config_.mode != WifiMode::STA && m_config_.mode != WifiMode::APSTA) { - ASF_LOGE(TAG, 2714, asf::logger::Criticality::HIGH, "WiFi not in STA mode"); - return false; - } - - m_connectionStatus_ = WifiConnectionStatus::CONNECTING; - - esp_err_t ret = esp_wifi_connect(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2715, asf::logger::Criticality::HIGH, "Failed to connect to WiFi: %s", esp_err_to_name(ret)); - m_connectionStatus_ = WifiConnectionStatus::FAILED; - return false; - } - - ASF_LOGI(TAG, 2716, asf::logger::Criticality::LOW, "WiFi connection initiated"); - return true; -#else - return false; -#endif -} - -bool Wifi::disconnect() -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!m_isInitialized_) { - ASF_LOGW(TAG, 2717, asf::logger::Criticality::MEDIUM, "WiFi not initialized"); - return true; - } - - esp_err_t ret = esp_wifi_disconnect(); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2718, asf::logger::Criticality::HIGH, "Failed to disconnect WiFi: %s", esp_err_to_name(ret)); - return false; - } - - m_connectionStatus_ = WifiConnectionStatus::DISCONNECTED; - ASF_LOGI(TAG, 2719, asf::logger::Criticality::LOW, "WiFi disconnected"); - return true; -#else - return true; -#endif -} - -int32_t Wifi::scan(WifiScanResult* results, size_t maxResults, uint32_t scanTimeMs) -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!m_isInitialized_ || results == nullptr || maxResults == 0) { - ASF_LOGE(TAG, 2720, asf::logger::Criticality::HIGH, "Invalid scan parameters"); - return -1; - } - - wifi_scan_config_t scanConfig = {}; - scanConfig.ssid = nullptr; - scanConfig.bssid = nullptr; - scanConfig.channel = 0; - scanConfig.show_hidden = true; - scanConfig.scan_type = WIFI_SCAN_TYPE_ACTIVE; - scanConfig.scan_time.active.min = scanTimeMs / 2; - scanConfig.scan_time.active.max = scanTimeMs; - - esp_err_t ret = esp_wifi_scan_start(&scanConfig, true); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2721, asf::logger::Criticality::HIGH, "Failed to start WiFi scan: %s", esp_err_to_name(ret)); - return -1; - } - - uint16_t apCount = 0; - esp_wifi_scan_get_ap_num(&apCount); - - if (apCount == 0) { - ASF_LOGI(TAG, 2722, asf::logger::Criticality::LOW, "No access points found"); - return 0; - } - - uint16_t actualCount = (apCount > maxResults) ? maxResults : apCount; - wifi_ap_record_t* apRecords = new wifi_ap_record_t[actualCount]; - - ret = esp_wifi_scan_get_ap_records(&actualCount, apRecords); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2723, asf::logger::Criticality::HIGH, "Failed to get scan results: %s", esp_err_to_name(ret)); - delete[] apRecords; - return -1; - } - - // Convert results - for (uint16_t i = 0; i < actualCount; i++) { - strncpy(results[i].ssid, (char*)apRecords[i].ssid, sizeof(results[i].ssid) - 1); - results[i].ssid[sizeof(results[i].ssid) - 1] = '\0'; - memcpy(results[i].bssid, apRecords[i].bssid, 6); - results[i].channel = apRecords[i].primary; - results[i].rssi = apRecords[i].rssi; - results[i].authMode = static_cast(apRecords[i].authmode); - } - - delete[] apRecords; - ASF_LOGI(TAG, 2724, asf::logger::Criticality::LOW, "WiFi scan completed, found %d networks", actualCount); - return actualCount; -#else - return -1; -#endif -} - -WifiConnectionStatus Wifi::getConnectionStatus() const -{ - return m_connectionStatus_; -} - -bool Wifi::isConnected() const -{ - return m_connectionStatus_ == WifiConnectionStatus::CONNECTED; -} - -int32_t Wifi::getRssi() -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!isConnected()) { - ASF_LOGW(TAG, 2725, asf::logger::Criticality::MEDIUM, "WiFi not connected"); - return 0; - } - - wifi_ap_record_t apInfo; - esp_err_t ret = esp_wifi_sta_get_ap_info(&apInfo); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2726, asf::logger::Criticality::HIGH, "Failed to get AP info: %s", esp_err_to_name(ret)); - return 0; - } - - return apInfo.rssi; -#else - return 0; -#endif -} - -bool Wifi::getIpAddress(char* ip, size_t maxLen) -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (!isConnected() || ip == nullptr || maxLen == 0) { - return false; - } - - esp_netif_ip_info_t ipInfo; - esp_err_t ret = esp_netif_get_ip_info(m_netifSta_, &ipInfo); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2727, asf::logger::Criticality::HIGH, "Failed to get IP info: %s", esp_err_to_name(ret)); - return false; - } - - snprintf(ip, maxLen, IPSTR, IP2STR(&ipInfo.ip)); - return true; -#else - return false; -#endif -} - -bool Wifi::getMacAddress(uint8_t* mac, WifiMode mode) -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (mac == nullptr) { - return false; - } - - wifi_interface_t interface = (mode == WifiMode::AP) ? WIFI_IF_AP : WIFI_IF_STA; - esp_err_t ret = esp_wifi_get_mac(interface, mac); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2728, asf::logger::Criticality::HIGH, "Failed to get MAC address: %s", esp_err_to_name(ret)); - return false; - } - - return true; -#else - return false; -#endif -} - -void Wifi::setEventCallback(WifiEventCallback callback, void* arg) -{ - m_eventCallback_ = callback; - m_eventCallbackArg_ = arg; -} - -int32_t Wifi::getConnectedStations() -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - if (m_config_.mode != WifiMode::AP && m_config_.mode != WifiMode::APSTA) { - ASF_LOGE(TAG, 2729, asf::logger::Criticality::HIGH, "WiFi not in AP mode"); - return -1; - } - - wifi_sta_list_t staList; - esp_err_t ret = esp_wifi_ap_get_sta_list(&staList); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2730, asf::logger::Criticality::HIGH, "Failed to get connected stations: %s", esp_err_to_name(ret)); - return -1; - } - - return staList.num; -#else - return -1; -#endif -} - -bool Wifi::isInitialized() const -{ - return m_isInitialized_; -} - -WifiStaConfig Wifi::getDefaultStaConfig() -{ - WifiStaConfig config = {}; - strcpy(config.ssid, ""); - strcpy(config.password, ""); - config.authMode = WifiAuthMode::WPA2_PSK; - config.pmfRequired = false; - config.channel = 0; - config.rssiThreshold = -127; - return config; -} - -WifiApConfig Wifi::getDefaultApConfig() -{ - WifiApConfig config = {}; - strcpy(config.ssid, "ESP32-AP"); - strcpy(config.password, "12345678"); - config.authMode = WifiAuthMode::WPA2_PSK; - config.channel = 1; - config.maxConnections = 4; - config.ssidHidden = false; - return config; -} - -#ifdef CONFIG_ESP_WIFI_ENABLED -wifi_mode_t Wifi::convertMode(WifiMode mode) -{ - switch (mode) { - case WifiMode::NONE: - return WIFI_MODE_NULL; - case WifiMode::STA: - return WIFI_MODE_STA; - case WifiMode::AP: - return WIFI_MODE_AP; - case WifiMode::APSTA: - return WIFI_MODE_APSTA; - default: - return WIFI_MODE_NULL; - } -} - -wifi_auth_mode_t Wifi::convertAuthMode(WifiAuthMode authMode) -{ - return static_cast(authMode); -} - -void Wifi::wifiEventHandler(void* arg, esp_event_base_t eventBase, int32_t eventId, void* eventData) -{ - Wifi* wifi = static_cast(arg); - - switch (eventId) { - case WIFI_EVENT_STA_START: - ASF_LOGI(TAG, 2731, asf::logger::Criticality::LOW, "WiFi STA started"); - break; - - case WIFI_EVENT_STA_CONNECTED: - ASF_LOGI(TAG, 2732, asf::logger::Criticality::LOW, "WiFi STA connected"); - wifi->m_connectionStatus_ = WifiConnectionStatus::CONNECTED; - break; - - case WIFI_EVENT_STA_DISCONNECTED: - ASF_LOGI(TAG, 2733, asf::logger::Criticality::LOW, "WiFi STA disconnected"); - wifi->m_connectionStatus_ = WifiConnectionStatus::DISCONNECTED; - if (wifi->m_eventCallback_) { - wifi->m_eventCallback_(WifiConnectionStatus::DISCONNECTED, wifi->m_eventCallbackArg_); - } - break; - - case WIFI_EVENT_AP_START: - ASF_LOGI(TAG, 2734, asf::logger::Criticality::LOW, "WiFi AP started"); - break; - - case WIFI_EVENT_AP_STOP: - ASF_LOGI(TAG, 2735, asf::logger::Criticality::LOW, "WiFi AP stopped"); - break; - - default: - break; - } -} - -void Wifi::ipEventHandler(void* arg, esp_event_base_t eventBase, int32_t eventId, void* eventData) -{ - Wifi* wifi = static_cast(arg); - - if (eventId == IP_EVENT_STA_GOT_IP) { - ip_event_got_ip_t* event = (ip_event_got_ip_t*) eventData; - ASF_LOGI(TAG, 2736, asf::logger::Criticality::LOW, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip)); - wifi->m_connectionStatus_ = WifiConnectionStatus::CONNECTED; - - if (wifi->m_eventCallback_) { - wifi->m_eventCallback_(WifiConnectionStatus::CONNECTED, wifi->m_eventCallbackArg_); - } - } -} -#endif diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.hpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.hpp deleted file mode 100644 index e6a9792..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/com/wifi.hpp +++ /dev/null @@ -1,306 +0,0 @@ -/** - * @file wifi.hpp - * @brief WiFi wrapper component header - Wrapper for ESP-IDF WiFi functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef WIFI_HPP -#define WIFI_HPP - -#include -#include -#include "esp_err.h" - -#ifdef CONFIG_ESP_WIFI_ENABLED -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_netif.h" -#endif - -/** - * @brief WiFi mode enumeration - */ -enum class WifiMode -{ - NONE, - STA, ///< Station mode - AP, ///< Access Point mode - APSTA ///< AP + STA mode -}; - -/** - * @brief WiFi authentication mode enumeration - */ -enum class WifiAuthMode -{ -#ifdef CONFIG_ESP_WIFI_ENABLED - OPEN = WIFI_AUTH_OPEN, - WEP = WIFI_AUTH_WEP, - WPA_PSK = WIFI_AUTH_WPA_PSK, - WPA2_PSK = WIFI_AUTH_WPA2_PSK, - WPA_WPA2_PSK = WIFI_AUTH_WPA_WPA2_PSK, - WPA3_PSK = WIFI_AUTH_WPA3_PSK, - WPA2_WPA3_PSK = WIFI_AUTH_WPA2_WPA3_PSK -#else - OPEN, - WEP, - WPA_PSK, - WPA2_PSK, - WPA_WPA2_PSK, - WPA3_PSK, - WPA2_WPA3_PSK -#endif -}; - -/** - * @brief WiFi station configuration structure - */ -struct WifiStaConfig -{ - char ssid[32]; ///< SSID of target AP - char password[64]; ///< Password of target AP - WifiAuthMode authMode; ///< Authentication mode - bool pmfRequired; ///< Protected Management Frame required - uint8_t channel; ///< Channel of target AP (0 = auto) - int8_t rssiThreshold; ///< Minimum RSSI threshold -}; - -/** - * @brief WiFi access point configuration structure - */ -struct WifiApConfig -{ - char ssid[32]; ///< SSID of AP - char password[64]; ///< Password of AP - WifiAuthMode authMode; ///< Authentication mode - uint8_t channel; ///< Channel number - uint8_t maxConnections; ///< Maximum number of connections - bool ssidHidden; ///< Hide SSID -}; - -/** - * @brief WiFi configuration structure - */ -struct WifiConfig -{ - WifiMode mode; ///< WiFi mode - WifiStaConfig staConfig; ///< Station configuration - WifiApConfig apConfig; ///< Access Point configuration -}; - -/** - * @brief WiFi connection status enumeration - */ -enum class WifiConnectionStatus -{ - DISCONNECTED, - CONNECTING, - CONNECTED, - FAILED -}; - -/** - * @brief WiFi scan result structure - */ -struct WifiScanResult -{ - char ssid[33]; ///< SSID - uint8_t bssid[6]; ///< BSSID - uint8_t channel; ///< Channel - int8_t rssi; ///< RSSI - WifiAuthMode authMode; ///< Authentication mode -}; - -/** - * @brief WiFi event callback function type - */ -using WifiEventCallback = void (*)(WifiConnectionStatus status, void* arg); - -/** - * @brief WiFi wrapper class - * - * Provides a C++ wrapper for ESP-IDF WiFi functionality. - * This class encapsulates ESP-IDF WiFi driver functions in an object-oriented interface. - */ -class Wifi -{ -public: - /** - * @brief Constructor - * @details Initializes the WiFi wrapper instance - */ - Wifi(); - - /** - * @brief Destructor - * @details Cleans up resources and deinitializes WiFi - */ - ~Wifi(); - - /** - * @brief Initialize WiFi with configuration - * @param config WiFi configuration - * @return true if initialized successfully, false otherwise - * @note This function initializes the WiFi stack and event loop - */ - bool initialize(const WifiConfig& config); - - /** - * @brief Deinitialize WiFi - * @return true if deinitialized successfully, false otherwise - */ - bool deinitialize(); - - /** - * @brief Start WiFi (connect in STA mode or start AP) - * @return true if started successfully, false otherwise - */ - bool start(); - - /** - * @brief Stop WiFi - * @return true if stopped successfully, false otherwise - */ - bool stop(); - - /** - * @brief Connect to WiFi network (STA mode) - * @return true if connection initiated successfully, false otherwise - * @note This is asynchronous, use event callback to get connection status - */ - bool connect(); - - /** - * @brief Disconnect from WiFi network - * @return true if disconnected successfully, false otherwise - */ - bool disconnect(); - - /** - * @brief Scan for available WiFi networks - * @param results Array to store scan results - * @param maxResults Maximum number of results to return - * @param scanTimeMs Scan time in milliseconds - * @return Number of networks found, or -1 on error - */ - int32_t scan(WifiScanResult* results, size_t maxResults, uint32_t scanTimeMs = 3000); - - /** - * @brief Get current connection status - * @return Current WiFi connection status - */ - WifiConnectionStatus getConnectionStatus() const; - - /** - * @brief Check if WiFi is connected - * @return true if connected, false otherwise - */ - bool isConnected() const; - - /** - * @brief Get RSSI of current connection - * @return RSSI in dBm, or 0 if not connected - */ - int32_t getRssi(); - - /** - * @brief Get IP address (STA mode) - * @param ip Buffer to store IP address string - * @param maxLen Maximum length of IP string - * @return true if IP retrieved successfully, false otherwise - */ - bool getIpAddress(char* ip, size_t maxLen); - - /** - * @brief Get MAC address - * @param mac Buffer to store MAC address (6 bytes) - * @param mode WiFi mode to get MAC for - * @return true if MAC retrieved successfully, false otherwise - */ - bool getMacAddress(uint8_t* mac, WifiMode mode); - - /** - * @brief Set event callback - * @param callback Callback function - * @param arg Argument passed to callback - */ - void setEventCallback(WifiEventCallback callback, void* arg); - - /** - * @brief Get number of connected stations (AP mode) - * @return Number of connected stations, or -1 on error - */ - int32_t getConnectedStations(); - - /** - * @brief Check if WiFi is initialized - * @return true if initialized, false otherwise - */ - bool isInitialized() const; - - /** - * @brief Get default station configuration - * @return Default WiFi station configuration - */ - static WifiStaConfig getDefaultStaConfig(); - - /** - * @brief Get default access point configuration - * @return Default WiFi access point configuration - */ - static WifiApConfig getDefaultApConfig(); - -private: - bool m_isInitialized_; ///< Initialization status - WifiConnectionStatus m_connectionStatus_; ///< Current connection status - WifiConfig m_config_; ///< WiFi configuration -#ifdef CONFIG_ESP_WIFI_ENABLED - esp_netif_t* m_netifSta_; ///< Station netif handle - esp_netif_t* m_netifAp_; ///< AP netif handle -#else - void* m_netifSta_; - void* m_netifAp_; -#endif - WifiEventCallback m_eventCallback_; ///< Event callback function - void* m_eventCallbackArg_; ///< Event callback argument - -#ifdef CONFIG_ESP_WIFI_ENABLED - /** - * @brief Convert WifiMode to ESP-IDF wifi_mode_t - * @param mode WiFi mode - * @return ESP-IDF wifi_mode_t - */ - wifi_mode_t convertMode(WifiMode mode); - - /** - * @brief Convert WifiAuthMode to ESP-IDF wifi_auth_mode_t - * @param authMode Authentication mode - * @return ESP-IDF wifi_auth_mode_t - */ - wifi_auth_mode_t convertAuthMode(WifiAuthMode authMode); - - /** - * @brief WiFi event handler - * @param arg Event handler argument - * @param eventBase Event base - * @param eventId Event ID - * @param eventData Event data - */ - static void wifiEventHandler(void* arg, esp_event_base_t eventBase, - int32_t eventId, void* eventData); - - /** - * @brief IP event handler - * @param arg Event handler argument - * @param eventBase Event base - * @param eventId Event ID - * @param eventData Event data - */ - static void ipEventHandler(void* arg, esp_event_base_t eventBase, - int32_t eventId, void* eventData); -#endif -}; - -#endif // WIFI_HPP diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/logging_data.csv b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/logging_data.csv deleted file mode 100644 index 5a331c5..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/logging_data.csv +++ /dev/null @@ -1,38 +0,0 @@ -ID,Component,Level,Criticality,Message -2700,WIFI,INFO,Low,WiFi wrapper initialized -2701,WIFI,INFO,Low,WiFi wrapper destroyed -2702,WIFI,WARNING,Medium,WiFi already initialized -2703,WIFI,INFO,Low,WiFi initialized successfully -2704,WIFI,WARNING,Medium,WiFi disabled in sdkconfig -2705,WIFI,WARNING,Medium,WiFi not initialized -2706,WIFI,INFO,Low,WiFi deinitialized -2707,WIFI,ERROR,High,WiFi not initialized -2708,WIFI,ERROR,High,Failed to start WiFi: %s -2709,WIFI,INFO,Low,WiFi started -2710,WIFI,WARNING,Medium,WiFi not initialized -2711,WIFI,ERROR,High,Failed to stop WiFi: %s -2712,WIFI,INFO,Low,WiFi stopped -2713,WIFI,ERROR,High,WiFi not initialized -2714,WIFI,ERROR,High,WiFi not in STA mode -2715,WIFI,ERROR,High,Failed to connect to WiFi: %s -2716,WIFI,INFO,Low,WiFi connection initiated -2717,WIFI,WARNING,Medium,WiFi not initialized -2718,WIFI,ERROR,High,Failed to disconnect WiFi: %s -2719,WIFI,INFO,Low,WiFi disconnected -2720,WIFI,ERROR,High,Invalid scan parameters -2721,WIFI,ERROR,High,Failed to start WiFi scan: %s -2722,WIFI,INFO,Low,No access points found -2723,WIFI,ERROR,High,Failed to get scan results: %s -2724,WIFI,INFO,Low,WiFi scan completed, found %d networks -2725,WIFI,WARNING,Medium,WiFi not connected -2726,WIFI,ERROR,High,Failed to get AP info: %s -2727,WIFI,ERROR,High,Failed to get IP info: %s -2728,WIFI,ERROR,High,Failed to get MAC address: %s -2729,WIFI,ERROR,High,WiFi not in AP mode -2730,WIFI,ERROR,High,Failed to get connected stations: %s -2731,WIFI,INFO,Low,WiFi STA started -2732,WIFI,INFO,Low,WiFi STA connected -2733,WIFI,INFO,Low,WiFi STA disconnected -2734,WIFI,INFO,Low,WiFi AP started -2735,WIFI,INFO,Low,WiFi AP stopped -2736,WIFI,INFO,Low,Got IP: %s diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/test_wifi.cpp b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/test_wifi.cpp deleted file mode 100644 index 4397b73..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/test_wifi.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file test_wifi.cpp - * @brief Unit tests for WiFi wrapper component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "wifi.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_wifi_initialize(void) -{ - Wifi wifi; - WifiConfig config = {"test_ssid", "test_password", WifiMode::STA}; - bool result = wifi.initialize(config); - TEST_ASSERT_TRUE(result); -} - -void test_wifi_connect(void) -{ - Wifi wifi; - WifiConfig config = {"test_ssid", "test_password", WifiMode::STA}; - wifi.initialize(config); - - bool result = wifi.connect(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(wifi.isConnected()); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.py b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.py deleted file mode 100644 index 0ba9777..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_wifi_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "WiFi initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_wifi_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.test_scenario.xml b/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.test_scenario.xml deleted file mode 100644 index 2da1b38..0000000 --- a/draft- to be removed SW/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - WIFI_INIT_TEST - - python components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/CMakeLists.txt b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/CMakeLists.txt deleted file mode 100644 index f52d51d..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/data_pool.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/COMPONENT_SPEC.md b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/COMPONENT_SPEC.md deleted file mode 100644 index f8f213f..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/COMPONENT_SPEC.md +++ /dev/null @@ -1,667 +0,0 @@ -# Data Pool Component Specification - -**Component ID:** COMP-DATA-POOL -**Version:** 1.0 -**Date:** 2025-01-19 -**Location:** `application_layer/DP_stack/data_pool/` - -## 1. Purpose - -The Data Pool component provides centralized, thread-safe storage for runtime system data including latest sensor values, system state, diagnostic information, and configuration data. It serves as the single source of truth for all runtime data and provides fast access for components that need current system information. - -## 2. Responsibilities - -### 2.1 Primary Responsibilities - -- **Runtime Data Storage:** Maintain latest sensor data, system state, and diagnostic information -- **Thread-Safe Access:** Provide concurrent read/write access with appropriate synchronization -- **Data Consistency:** Ensure data integrity across multiple readers and writers -- **Fast Data Access:** Provide low-latency access to frequently accessed data -- **Data Validation:** Validate data integrity and consistency on updates -- **Memory Management:** Efficient memory usage with bounded storage requirements - -### 2.2 Non-Responsibilities - -- **Data Persistence:** Delegated to Persistence component (long-term storage) -- **Data Processing:** Components handle their own data processing logic -- **Network Communication:** Delegated to Communication components -- **Hardware Access:** No direct hardware interface - -## 3. Public API - -### 3.1 Sensor Data Management - -```c -/** - * @brief Update sensor data record - * @param sensor_id Sensor identifier (0-6) - * @param record Sensor data record to store - * @return true if update successful, false on error - */ -bool dataPool_updateSensorData(uint8_t sensor_id, const sensor_data_record_t* record); - -/** - * @brief Get latest sensor data record - * @param sensor_id Sensor identifier (0-6) - * @param record Output buffer for sensor data record - * @return true if data retrieved, false on error - */ -bool dataPool_getSensorData(uint8_t sensor_id, sensor_data_record_t* record); - -/** - * @brief Get all sensor data records - * @param records Output buffer for sensor data records - * @param count Input: buffer size, Output: number of records filled - * @return true if data retrieved, false on error - */ -bool dataPool_getAllSensorData(sensor_data_record_t* records, size_t* count); - -/** - * @brief Check if sensor data is available and valid - * @param sensor_id Sensor identifier (0-6) - * @return true if valid data available, false otherwise - */ -bool dataPool_isSensorDataValid(uint8_t sensor_id); - -/** - * @brief Get timestamp of last sensor data update - * @param sensor_id Sensor identifier (0-6) - * @return Timestamp of last update, 0 if no data available - */ -uint64_t dataPool_getSensorDataTimestamp(uint8_t sensor_id); -``` - -### 3.2 System State Management - -```c -/** - * @brief Update system state information - * @param state_info System state information structure - * @return true if update successful, false on error - */ -bool dataPool_updateSystemState(const system_state_info_t* state_info); - -/** - * @brief Get current system state information - * @param state_info Output buffer for system state information - * @return true if data retrieved, false on error - */ -bool dataPool_getSystemState(system_state_info_t* state_info); - -/** - * @brief Update system health metrics - * @param health_metrics System health metrics structure - * @return true if update successful, false on error - */ -bool dataPool_updateHealthMetrics(const system_health_metrics_t* health_metrics); - -/** - * @brief Get system health metrics - * @param health_metrics Output buffer for health metrics - * @return true if data retrieved, false on error - */ -bool dataPool_getHealthMetrics(system_health_metrics_t* health_metrics); -``` - -### 3.3 Diagnostic Data Management - -```c -/** - * @brief Add diagnostic event to pool - * @param event Diagnostic event structure - * @return true if event added, false on error - */ -bool dataPool_addDiagnosticEvent(const diagnostic_event_t* event); - -/** - * @brief Get recent diagnostic events - * @param events Output buffer for diagnostic events - * @param count Input: buffer size, Output: number of events filled - * @return true if events retrieved, false on error - */ -bool dataPool_getRecentDiagnostics(diagnostic_event_t* events, size_t* count); - -/** - * @brief Get diagnostic summary (counts by severity) - * @param summary Output buffer for diagnostic summary - * @return true if summary retrieved, false on error - */ -bool dataPool_getDiagnosticSummary(diagnostic_summary_t* summary); - -/** - * @brief Clear diagnostic events from pool - * @param severity Severity level to clear (DIAG_SEVERITY_ALL for all) - * @return Number of events cleared - */ -size_t dataPool_clearDiagnostics(diagnostic_severity_t severity); -``` - -### 3.4 Communication Status Management - -```c -/** - * @brief Update communication link status - * @param link_type Communication link type - * @param status Link status information - * @return true if update successful, false on error - */ -bool dataPool_updateLinkStatus(comm_link_type_t link_type, const comm_link_status_t* status); - -/** - * @brief Get communication link status - * @param link_type Communication link type - * @param status Output buffer for link status - * @return true if status retrieved, false on error - */ -bool dataPool_getLinkStatus(comm_link_type_t link_type, comm_link_status_t* status); - -/** - * @brief Get overall communication status - * @param comm_status Output buffer for communication status - * @return true if status retrieved, false on error - */ -bool dataPool_getCommunicationStatus(communication_status_t* comm_status); -``` - -### 3.5 Configuration Data Management - -```c -/** - * @brief Update runtime configuration - * @param config_type Configuration type - * @param config_data Configuration data - * @param data_size Size of configuration data - * @return true if update successful, false on error - */ -bool dataPool_updateConfiguration(config_type_t config_type, const void* config_data, size_t data_size); - -/** - * @brief Get runtime configuration - * @param config_type Configuration type - * @param config_data Output buffer for configuration data - * @param data_size Input: buffer size, Output: actual data size - * @return true if configuration retrieved, false on error - */ -bool dataPool_getConfiguration(config_type_t config_type, void* config_data, size_t* data_size); - -/** - * @brief Check if configuration is valid - * @param config_type Configuration type - * @return true if configuration is valid, false otherwise - */ -bool dataPool_isConfigurationValid(config_type_t config_type); -``` - -### 3.6 Data Pool Management - -```c -/** - * @brief Initialize Data Pool component - * @return true if initialization successful, false otherwise - */ -bool dataPool_initialize(void); - -/** - * @brief Get Data Pool statistics - * @param stats Output buffer for statistics - * @return true if statistics retrieved, false on error - */ -bool dataPool_getStatistics(data_pool_stats_t* stats); - -/** - * @brief Reset Data Pool statistics - * @return true if statistics reset, false on error - */ -bool dataPool_resetStatistics(void); - -/** - * @brief Validate Data Pool integrity - * @return true if integrity check passed, false if corruption detected - */ -bool dataPool_validateIntegrity(void); - -/** - * @brief Create snapshot of current data pool state - * @param snapshot Output buffer for snapshot - * @return true if snapshot created, false on error - */ -bool dataPool_createSnapshot(data_pool_snapshot_t* snapshot); -``` - -## 4. Data Types - -### 4.1 Sensor Data Record (Extended) - -```c -typedef struct { - uint8_t sensor_id; // Sensor identifier (0-6) - sensor_type_t sensor_type; // Type of sensor - float filtered_value; // Processed sensor value - char unit[8]; // Unit of measurement - uint64_t timestamp_ms; // Timestamp in milliseconds - data_validity_t validity; // Data validity status - uint16_t sample_count; // Number of samples used - float raw_min, raw_max; // Min/max of raw samples - float raw_stddev; // Standard deviation - uint32_t acquisition_time_us; // Acquisition time - uint32_t sequence_number; // Monotonic sequence number - uint16_t checksum; // Data integrity checksum -} sensor_data_record_t; -``` - -### 4.2 System State Information - -```c -typedef struct { - system_state_t current_state; // Current system state - system_state_t previous_state; // Previous system state - transition_reason_t last_reason; // Last transition reason - uint64_t state_entry_time; // Time when current state was entered - uint64_t state_duration_ms; // Duration in current state - uint32_t state_transition_count; // Total number of state transitions - bool teardown_in_progress; // Teardown sequence active - uint8_t teardown_progress; // Teardown progress (0-100%) -} system_state_info_t; -``` - -### 4.3 System Health Metrics - -```c -typedef struct { - // CPU and Memory - float cpu_usage_percent; // Current CPU usage - uint32_t free_heap_bytes; // Available heap memory - uint32_t min_free_heap_bytes; // Minimum free heap recorded - uint32_t heap_fragmentation; // Heap fragmentation percentage - - // Task Information - uint32_t task_count; // Number of active tasks - uint32_t stack_high_water_mark; // Minimum remaining stack - - // System Uptime - uint64_t uptime_ms; // System uptime in milliseconds - uint32_t boot_count; // Number of system boots - - // Storage - uint64_t sd_free_bytes; // SD card free space - uint64_t sd_total_bytes; // SD card total space - uint32_t nvm_free_entries; // NVM free entries - - // Communication - uint32_t wifi_rssi; // WiFi signal strength - uint32_t packets_sent; // Total packets sent - uint32_t packets_received; // Total packets received - uint32_t communication_errors; // Communication error count - - // Sensors - uint8_t sensors_active; // Number of active sensors - uint8_t sensors_faulty; // Number of faulty sensors - uint32_t total_acquisitions; // Total sensor acquisitions - - // Diagnostics - uint32_t warning_count; // Active warning count - uint32_t error_count; // Active error count - uint32_t fatal_count; // Fatal error count - - uint64_t last_update_time; // Last metrics update time -} system_health_metrics_t; -``` - -### 4.4 Diagnostic Event - -```c -typedef struct { - uint16_t diagnostic_code; // Diagnostic code (0xSCCC format) - diagnostic_severity_t severity; // Severity level - uint64_t timestamp_ms; // Event timestamp - uint32_t occurrence_count; // Number of occurrences - char description[64]; // Human-readable description - uint8_t context_data[32]; // Context-specific data - uint32_t sequence_number; // Event sequence number -} diagnostic_event_t; - -typedef struct { - uint32_t info_count; // Number of INFO events - uint32_t warning_count; // Number of WARNING events - uint32_t error_count; // Number of ERROR events - uint32_t fatal_count; // Number of FATAL events - uint64_t last_event_time; // Timestamp of last event - uint16_t most_recent_code; // Most recent diagnostic code -} diagnostic_summary_t; -``` - -### 4.5 Communication Status - -```c -typedef enum { - COMM_LINK_MAIN_HUB = 0, // Main Hub communication - COMM_LINK_PEER_HUB, // Peer Hub communication - COMM_LINK_DIAGNOSTIC, // Diagnostic communication - COMM_LINK_COUNT -} comm_link_type_t; - -typedef struct { - bool is_connected; // Connection status - uint64_t last_activity_time; // Last communication activity - uint32_t bytes_sent; // Bytes sent - uint32_t bytes_received; // Bytes received - uint32_t error_count; // Communication errors - int32_t signal_strength; // Signal strength (RSSI) - uint32_t round_trip_time_ms; // Average round-trip time -} comm_link_status_t; - -typedef struct { - comm_link_status_t links[COMM_LINK_COUNT]; // Individual link status - bool overall_connectivity; // Overall connectivity status - uint64_t last_successful_comm; // Last successful communication - uint32_t total_comm_failures; // Total communication failures -} communication_status_t; -``` - -### 4.6 Data Pool Statistics - -```c -typedef struct { - // Access Statistics - uint64_t total_reads; // Total read operations - uint64_t total_writes; // Total write operations - uint64_t read_errors; // Read operation errors - uint64_t write_errors; // Write operation errors - - // Performance Metrics - uint32_t avg_read_time_us; // Average read time - uint32_t avg_write_time_us; // Average write time - uint32_t max_read_time_us; // Maximum read time - uint32_t max_write_time_us; // Maximum write time - - // Memory Usage - uint32_t memory_used_bytes; // Current memory usage - uint32_t max_memory_used_bytes; // Peak memory usage - - // Data Integrity - uint32_t checksum_failures; // Checksum validation failures - uint32_t integrity_checks; // Total integrity checks performed - - // Concurrency - uint32_t concurrent_readers; // Current concurrent readers - uint32_t max_concurrent_readers; // Maximum concurrent readers - uint32_t lock_contentions; // Lock contention events - - uint64_t statistics_reset_time; // Last statistics reset time -} data_pool_stats_t; -``` - -## 5. Internal Architecture - -### 5.1 Data Pool Structure - -```mermaid -graph TB - subgraph "Data Pool Component" - subgraph "Sensor Data Storage" - SD0[Sensor 0 Data] - SD1[Sensor 1 Data] - SD2[Sensor 2 Data] - SD3[Sensor 3 Data] - SD4[Sensor 4 Data] - SD5[Sensor 5 Data] - SD6[Sensor 6 Data] - end - - subgraph "System Data Storage" - SS[System State Info] - HM[Health Metrics] - CS[Communication Status] - CF[Configuration Data] - end - - subgraph "Diagnostic Data Storage" - DE[Diagnostic Events] - DS[Diagnostic Summary] - end - - subgraph "Access Control" - RM[Reader-Writer Mutex] - IC[Integrity Checker] - ST[Statistics Tracker] - end - end - - subgraph "External Components" - SM[Sensor Manager] - STM[State Manager] - COMM[Communication] - DIAG[Diagnostics] - HMI[HMI] - end - - SM -->|Update| SD0 - SM -->|Update| SD1 - STM -->|Update| SS - COMM -->|Update| CS - DIAG -->|Update| DE - - HMI -->|Read| SS - HMI -->|Read| HM - COMM -->|Read| SD0 - COMM -->|Read| SD1 - - RM -.->|Protects| SD0 - RM -.->|Protects| SS - IC -.->|Validates| DE - ST -.->|Tracks| RM -``` - -### 5.2 Thread Safety Model - -```mermaid -sequenceDiagram - participant W1 as Writer 1 - participant W2 as Writer 2 - participant R1 as Reader 1 - participant R2 as Reader 2 - participant DP as Data Pool - participant Mutex as RW Mutex - - Note over W1,Mutex: Concurrent Access Scenario - - W1->>Mutex: acquireWriteLock() - Mutex-->>W1: lockAcquired - W1->>DP: updateSensorData() - - R1->>Mutex: acquireReadLock() - Note over R1,Mutex: Blocked until write complete - - W2->>Mutex: acquireWriteLock() - Note over W2,Mutex: Blocked until write complete - - W1->>DP: dataUpdateComplete - W1->>Mutex: releaseWriteLock() - - Mutex-->>R1: readLockAcquired - R1->>DP: getSensorData() - DP-->>R1: sensorData - - R2->>Mutex: acquireReadLock() - Mutex-->>R2: readLockAcquired - R2->>DP: getSensorData() - DP-->>R2: sensorData - - R1->>Mutex: releaseReadLock() - R2->>Mutex: releaseReadLock() - - Mutex-->>W2: writeLockAcquired - W2->>DP: updateSystemState() - W2->>Mutex: releaseWriteLock() -``` - -## 6. Threading Model - -- **Access Model:** Multi-reader, single-writer with reader-writer mutex -- **Thread Safety:** Fully thread-safe for all operations -- **Blocking Operations:** Read operations may block on write operations (bounded) -- **ISR Access:** Limited read-only access for critical data (lock-free atomic reads) -- **Priority Inheritance:** Mutex supports priority inheritance to prevent priority inversion - -## 7. Resource Ownership - -- **Data Storage:** All runtime data owned exclusively by Data Pool -- **Access Control:** Reader-writer mutex owned by Data Pool -- **Memory Management:** Static allocation for all data structures (no dynamic allocation) -- **Integrity Checking:** Checksum validation owned by Data Pool - -## 8. Error Model - -### 8.1 Error Conditions - -| Error | Condition | Response | -|-------|-----------|----------| -| `DATAPOOL_ERR_INVALID_SENSOR_ID` | Invalid sensor ID (>6) | Return false, log warning | -| `DATAPOOL_ERR_NULL_POINTER` | NULL pointer parameter | Return false, log error | -| `DATAPOOL_ERR_BUFFER_TOO_SMALL` | Output buffer too small | Return false, set required size | -| `DATAPOOL_ERR_DATA_STALE` | Data older than threshold | Return false, log info | -| `DATAPOOL_ERR_CHECKSUM_FAILURE` | Data integrity check failed | Return false, log error | -| `DATAPOOL_ERR_LOCK_TIMEOUT` | Failed to acquire lock | Return false, log warning | -| `DATAPOOL_ERR_MEMORY_FULL` | Storage capacity exceeded | Overwrite oldest, log warning | - -### 8.2 Diagnostics Emitted - -- `DIAG-DP-POOL-0001`: Data integrity check failed (ERROR) -- `DIAG-DP-POOL-0002`: Lock contention detected (WARNING) -- `DIAG-DP-POOL-0003`: Memory usage high (WARNING) -- `DIAG-DP-POOL-0004`: Stale data detected (INFO) - -## 9. State-Dependent Behavior - -| System State | Data Pool Behavior | -|-------------|-------------------| -| **INIT** | Initialize data structures, clear all data | -| **RUNNING** | Normal operation, full read/write access | -| **WARNING** | Continue operation, enhanced integrity checking | -| **FAULT** | Read-only mode, preserve data integrity | -| **OTA_UPDATE** | Read-only mode, prepare for snapshot | -| **MC_UPDATE** | Limited updates, configuration reload | -| **TEARDOWN** | Read-only mode, prepare for shutdown | -| **SERVICE** | Full access, enhanced diagnostics | -| **SD_DEGRADED** | Normal operation, no persistence coordination | - -## 10. Dependencies - -### 10.1 Required Components - -- **Logger:** Debug and diagnostic logging -- **Time Utils:** Timestamp generation for data records -- **Error Handler:** Error reporting and escalation - -### 10.2 Required Interfaces - -- Logger interface for diagnostic output -- Time Utils interface for timestamp generation -- Error Handler interface for fault reporting - -## 11. Performance Requirements - -### 11.1 Access Performance - -- **Read Operations:** Maximum 10μs for single sensor data read -- **Write Operations:** Maximum 50μs for single sensor data write -- **Bulk Operations:** Maximum 500μs for all sensor data read -- **Lock Acquisition:** Maximum 1ms timeout for lock acquisition - -### 11.2 Memory Requirements - -- **Static Memory:** Maximum 64KB for all data structures -- **Per-Sensor Data:** Maximum 1KB per sensor (including history) -- **Diagnostic Storage:** Maximum 8KB for recent diagnostic events -- **Configuration Storage:** Maximum 4KB for runtime configuration - -## 12. Acceptance Tests - -### 12.1 Functional Tests - -- **T-DATAPOOL-001:** Sensor data storage and retrieval works correctly -- **T-DATAPOOL-002:** System state information maintained accurately -- **T-DATAPOOL-003:** Diagnostic events stored and retrieved correctly -- **T-DATAPOOL-004:** Communication status tracking works -- **T-DATAPOOL-005:** Configuration data management works - -### 12.2 Concurrency Tests - -- **T-DATAPOOL-006:** Multiple readers can access data simultaneously -- **T-DATAPOOL-007:** Writers have exclusive access during updates -- **T-DATAPOOL-008:** Reader-writer priority handling works correctly -- **T-DATAPOOL-009:** Lock contention handled gracefully - -### 12.3 Performance Tests - -- **T-DATAPOOL-010:** Read operations complete within 10μs -- **T-DATAPOOL-011:** Write operations complete within 50μs -- **T-DATAPOOL-012:** Memory usage stays within 64KB limit -- **T-DATAPOOL-013:** No memory leaks during continuous operation - -### 12.4 Integrity Tests - -- **T-DATAPOOL-014:** Data integrity checks detect corruption -- **T-DATAPOOL-015:** Checksum validation works correctly -- **T-DATAPOOL-016:** Stale data detection works -- **T-DATAPOOL-017:** Statistics tracking is accurate - -## 13. Traceability - -### 13.1 System Requirements - -- **SR-DATA-002:** Data Persistence Abstraction (runtime data management) -- **SR-PERF-003:** Memory usage constraints -- **SR-REL-004:** Data integrity requirements - -### 13.2 Software Requirements - -- **SWR-DATA-004:** DP component API definition -- **SWR-DATA-005:** Storage media abstraction -- **SWR-DATA-006:** Unified data access interface -- **SWR-REL-010:** Error detection implementation - -### 13.3 Features - -- **F-DATA-002:** Data Persistence Abstraction (runtime component) -- **F-DIAG-002:** Diagnostic Data Storage (runtime component) - -## 14. Implementation Notes - -### 14.1 Design Patterns - -- **Singleton Pattern:** Single Data Pool instance per system -- **Reader-Writer Lock Pattern:** Concurrent access control -- **Observer Pattern:** Data change notifications (via Event System) -- **Template Method Pattern:** Generic data access operations - -### 14.2 Key Implementation Details - -- All data structures SHALL use static allocation (no malloc/free) -- Reader-writer mutex SHALL support priority inheritance -- Data integrity SHALL be verified using checksums -- Access statistics SHALL be maintained for performance monitoring -- Atomic operations SHALL be used for lock-free ISR access - -### 14.3 Memory Layout - -```c -// Static memory allocation structure -typedef struct { - sensor_data_record_t sensor_data[SENSOR_TYPE_COUNT]; - system_state_info_t system_state; - system_health_metrics_t health_metrics; - diagnostic_event_t diagnostic_events[MAX_DIAGNOSTIC_EVENTS]; - comm_link_status_t comm_links[COMM_LINK_COUNT]; - uint8_t configuration_data[MAX_CONFIG_SIZE]; - data_pool_stats_t statistics; - pthread_rwlock_t access_lock; -} data_pool_storage_t; -``` - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-DATA, SWR-DATA) -**Next Review:** After implementation and testing \ No newline at end of file diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.cpp b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.cpp deleted file mode 100644 index 8cc5bb3..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file data_pool.cpp - * @brief DataPool component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "data_pool.hpp" -#include "logger.hpp" - -static const char* TAG = "DataPool"; - -DataPool::DataPool() - : m_isInitialized(false) -{ -} - -DataPool::~DataPool() -{ - deinitialize(); -} - -bool DataPool::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4900, asf::logger::Criticality::LOW, "DataPool initialized successfully"); - return true; -} - -bool DataPool::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool DataPool::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.hpp b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.hpp deleted file mode 100644 index 43d2d21..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/com/data_pool.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file data_pool.hpp - * @brief DataPool component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef DATA_POOL_HPP -#define DATA_POOL_HPP - -#include - -/** - * @brief DataPool class - * - * Component description goes here. - */ -class DataPool -{ -public: - DataPool(); - ~DataPool(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // DATA_POOL_HPP diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/logging_data.csv b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/logging_data.csv deleted file mode 100644 index 4152570..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4900,DataPool,INFO,Low,DataPool initialized successfully diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.py b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.py deleted file mode 100644 index 35b880b..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_data_pool_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "DataPool initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_data_pool_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.test_scenario.xml deleted file mode 100644 index cdd5eec..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - DATA_POOL_INIT_TEST - - python components/application_layer/DP_stack/data_pool/test/data_pool_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/test_data_pool.cpp b/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/test_data_pool.cpp deleted file mode 100644 index ea9f574..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/data_pool/test/test_data_pool.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_data_pool.cpp - * @brief Unit tests for DataPool component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "data_pool.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_data_pool_initialize(void) -{ - DataPool comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_data_pool_deinitialize(void) -{ - DataPool comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/CMakeLists.txt b/draft- to be removed SW/components/application_layer/DP_stack/persistence/CMakeLists.txt deleted file mode 100644 index 374d32a..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/persistence.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/COMPONENT_SPEC.md b/draft- to be removed SW/components/application_layer/DP_stack/persistence/COMPONENT_SPEC.md deleted file mode 100644 index 3e74c87..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/COMPONENT_SPEC.md +++ /dev/null @@ -1,257 +0,0 @@ -# Persistence Component Specification - -**Component ID:** COMP-PERSIST -**Version:** 1.0 -**Date:** 2025-01-19 -**Location:** `application_layer/DP_stack/persistence/` - -## 1. Purpose - -The Persistence component provides the sole interface for persistent storage access. It abstracts storage media (SD card, NVM), manages serialization/deserialization, implements wear-aware storage, and ensures data integrity. - -## 2. Responsibilities - -### 2.1 Primary Responsibilities - -- Abstract storage media (SD card, NVM) -- Serialize/deserialize structured data -- Manage wear-aware storage (SD card) -- Ensure data integrity -- Coordinate data flush operations - -### 2.2 Non-Responsibilities - -- Business logic (data semantics owned by components) -- Hardware access (delegated to storage drivers) -- Data validation (components validate before persistence) - -## 3. Public API - -### 3.1 Sensor Data Persistence - -```c -/** - * @brief Write sensor data record - * @param record Sensor data record - * @return true if written, false on error - */ -bool persistence_writeSensorData(const sensor_data_record_t* record); - -/** - * @brief Read sensor data records - * @param records Output buffer - * @param count Input: buffer size, Output: records read - * @param start_time Start timestamp filter (0 for all) - * @param end_time End timestamp filter (0 for all) - * @return true if read successful, false on error - */ -bool persistence_readSensorData(sensor_data_record_t* records, size_t* count, uint64_t start_time, uint64_t end_time); -``` - -### 3.2 Diagnostic Persistence - -```c -/** - * @brief Write diagnostic event - * @param event Diagnostic event - * @return true if written, false on error - */ -bool persistence_writeDiagnostic(const diagnostic_event_t* event); - -/** - * @brief Read diagnostic events - * @param events Output buffer - * @param count Input: buffer size, Output: events read - * @param filter Filter criteria (severity, component, etc.) - * @return true if read successful, false on error - */ -bool persistence_readDiagnostics(diagnostic_event_t* events, size_t* count, const diag_filter_t* filter); - -/** - * @brief Clear diagnostic log - * @return true if cleared, false on error - */ -bool persistence_clearDiagnostics(void); -``` - -### 3.3 Machine Constants Persistence - -```c -/** - * @brief Write machine constants - * @param mc Machine constants structure - * @return true if written, false on error - */ -bool persistence_writeMachineConstants(const machine_constants_t* mc); - -/** - * @brief Read machine constants - * @param mc Output buffer - * @return true if read successful, false on error - */ -bool persistence_readMachineConstants(machine_constants_t* mc); -``` - -### 3.4 Flush Operations - -```c -/** - * @brief Flush all critical data to storage - * @return true if flushed, false on error - */ -bool persistence_flushCriticalData(void); - -/** - * @brief Check if flush is complete - * @return true if flush complete, false otherwise - */ -bool persistence_isFlushComplete(void); - -/** - * @brief Get flush progress (0-100%) - * @return Flush progress percentage - */ -uint8_t persistence_getFlushProgress(void); -``` - -### 3.5 Storage Status - -```c -/** - * @brief Check storage availability - * @param storage_type Storage type (SD_CARD, NVM) - * @return true if available, false otherwise - */ -bool persistence_isStorageAvailable(storage_type_t storage_type); - -/** - * @brief Get storage usage statistics - * @param storage_type Storage type - * @param stats Output statistics - * @return true if retrieved, false on error - */ -bool persistence_getStorageStats(storage_type_t storage_type, storage_stats_t* stats); -``` - -## 4. Data Types - -### 4.1 Storage Types - -```c -typedef enum { - STORAGE_TYPE_SD_CARD = 0, - STORAGE_TYPE_NVM, - STORAGE_TYPE_COUNT -} storage_type_t; -``` - -### 4.2 Storage Statistics - -```c -typedef struct { - uint64_t total_bytes; - uint64_t used_bytes; - uint64_t free_bytes; - uint32_t write_count; - bool is_healthy; -} storage_stats_t; -``` - -## 5. Threading Model - -- **Owner Task:** Persistence Task (MEDIUM priority) -- **Thread Safety:** Thread-safe (all operations protected by mutex) -- **Blocking Operations:** Storage I/O operations (bounded by timing requirements) -- **ISR Access:** Not allowed (blocking operations) - -## 6. Resource Ownership - -- **SD Card Driver:** Owned exclusively by Persistence component -- **NVM Driver:** Owned exclusively by Persistence component -- **Storage Mutex:** Protects concurrent access -- **Write Buffers:** Pre-allocated static buffers - -## 7. Error Model - -### 7.1 Error Conditions - -| Error | Condition | Response | -|-------|-----------|----------| -| `PERSIST_ERR_STORAGE_FULL` | Storage full | Trigger retention policy, log warning | -| `PERSIST_ERR_STORAGE_FAILED` | Storage failure | Enter SD_DEGRADED state, log error | -| `PERSIST_ERR_SERIALIZATION` | Serialization failure | Return false, log error | -| `PERSIST_ERR_INTEGRITY_CHECK` | Integrity check failed | Return false, log error, attempt recovery | - -### 7.2 Diagnostics Emitted - -- `DIAG-ST-PERSIST-0001`: Storage write failure (WARNING) -- `DIAG-ST-PERSIST-0002`: Storage full (WARNING) -- `DIAG-ST-PERSIST-0003`: Storage corruption detected (ERROR) -- `DIAG-ST-PERSIST-0004`: Storage failure (FATAL) - -## 8. State-Dependent Behavior - -### 8.1 All States - -- Read operations allowed -- Write operations allowed (with restrictions) - -### 8.2 TEARDOWN State - -- Only authorized writes allowed (critical data flush) -- Read operations allowed - -### 8.3 SD_DEGRADED State - -- SD card writes disabled -- NVM writes allowed -- Read operations allowed (if storage accessible) - -## 9. Dependencies - -### 9.1 Required Components - -- **SD Card Driver:** For SD card access -- **NVM Driver:** For NVM access -- **STM:** For state queries and transitions -- **Logger:** For diagnostic logging - -### 9.2 Required Interfaces - -- SD Card Driver interface -- NVM Driver interface -- STM state query interface -- Logger interface - -## 10. Acceptance Tests - -- **T-PERSIST-001:** Sensor data write/read operations -- **T-PERSIST-002:** Diagnostic event write/read operations -- **T-PERSIST-003:** Machine constants write/read operations -- **T-PERSIST-004:** Data flush completes within 200ms -- **T-PERSIST-005:** Storage failure handling (SD_DEGRADED state) -- **T-PERSIST-006:** Data integrity verification -- **T-PERSIST-007:** Wear-aware storage management - -## 11. Traceability - -- **SWR-DATA-001:** Persistent timestamped sensor data -- **SWR-DATA-004:** DP component as sole persistence interface -- **SWR-DATA-005:** Storage access isolation -- **SWR-DATA-006:** Structured data serialization -- **SWR-DATA-007:** Data flush before teardown -- **SWR-DATA-008:** Data integrity during updates -- **SWR-DATA-009:** Persistence verification -- **SWR-DATA-012:** SD card failure handling -- **SWR-DATA-013:** Wear-aware storage management -- **CFC-ARCH-01:** Hardware access via drivers only -- **CFC-DATA-01:** Single source of truth -- **CFC-DATA-02:** Data consistency during transitions - -## 12. Implementation Notes - -- Serialization SHALL use a well-defined format (e.g., CBOR, MessagePack, or custom binary) -- SD card writes SHALL be wear-aware (wear leveling, write frequency limits) -- Data integrity SHALL be verified using checksums or hashes -- Flush operations SHALL be coordinated with STM for state transitions -- Storage failures SHALL trigger state transitions (SD_DEGRADED) diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.cpp b/draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.cpp deleted file mode 100644 index 4522ee8..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file persistence.cpp - * @brief Persistence component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "persistence.hpp" -#include "logger.hpp" - -static const char* TAG = "Persistence"; - -Persistence::Persistence() - : m_isInitialized(false) -{ -} - -Persistence::~Persistence() -{ - deinitialize(); -} - -bool Persistence::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 5000, asf::logger::Criticality::LOW, "Persistence initialized successfully"); - return true; -} - -bool Persistence::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Persistence::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.hpp b/draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.hpp deleted file mode 100644 index a72c072..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/com/persistence.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file persistence.hpp - * @brief Persistence component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef PERSISTENCE_HPP -#define PERSISTENCE_HPP - -#include - -/** - * @brief Persistence class - * - * Component description goes here. - */ -class Persistence -{ -public: - Persistence(); - ~Persistence(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // PERSISTENCE_HPP diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/logging_data.csv b/draft- to be removed SW/components/application_layer/DP_stack/persistence/logging_data.csv deleted file mode 100644 index 33e9db1..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -5000,Persistence,INFO,Low,Persistence initialized successfully diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.py b/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.py deleted file mode 100644 index a8b3b27..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_persistence_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Persistence initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_persistence_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.test_scenario.xml deleted file mode 100644 index dce0b00..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/persistence_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - PERSISTENCE_INIT_TEST - - python components/application_layer/DP_stack/persistence/test/persistence_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/test_persistence.cpp b/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/test_persistence.cpp deleted file mode 100644 index 2d85a27..0000000 --- a/draft- to be removed SW/components/application_layer/DP_stack/persistence/test/test_persistence.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_persistence.cpp - * @brief Unit tests for Persistence component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "persistence.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_persistence_initialize(void) -{ - Persistence comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_persistence_deinitialize(void) -{ - Persistence comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/CMakeLists.txt b/draft- to be removed SW/components/application_layer/business_stack/STM/CMakeLists.txt deleted file mode 100644 index 19ac5d4..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/stm.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/COMPONENT_SPEC.md b/draft- to be removed SW/components/application_layer/business_stack/STM/COMPONENT_SPEC.md deleted file mode 100644 index fcd6a4a..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/COMPONENT_SPEC.md +++ /dev/null @@ -1,291 +0,0 @@ -# State Manager (STM) Component Specification - -**Component ID:** COMP-STM -**Version:** 1.0 -**Date:** 2025-01-19 -**Location:** `application_layer/business_stack/STM/` - -## 1. Purpose - -The State Manager (STM) component implements the system finite state machine (FSM) as defined in the System State Machine Specification. It manages system operational states, enforces valid state transitions, coordinates teardown sequences, and notifies components of state changes. - -## 2. Responsibilities - -### 2.1 Primary Responsibilities - -- Implement system FSM with 11 states (INIT, BOOT_FAILURE, RUNNING, WARNING, FAULT, OTA_PREP, OTA_UPDATE, MC_UPDATE, TEARDOWN, SERVICE, SD_DEGRADED) -- Enforce valid state transitions according to transition table -- Coordinate controlled teardown sequences -- Notify registered components of state changes via Event System -- Provide state query interface for components - -### 2.2 Non-Responsibilities - -- Feature logic (sensor acquisition, communication, etc.) -- Hardware access (delegated to drivers) -- Fault detection (delegated to Error Handler) -- Diagnostic logging (delegated to Diagnostics Task) - -## 3. Public API - -### 3.1 State Query Functions - -```c -/** - * @brief Get current system state - * @return Current system state - */ -system_state_t stm_getCurrentState(void); - -/** - * @brief Check if a state is valid - * @param state State to validate - * @return true if state is valid, false otherwise - */ -bool stm_isStateValid(system_state_t state); - -/** - * @brief Check if system is in a specific state - * @param state State to check - * @return true if current state matches, false otherwise - */ -bool stm_isInState(system_state_t state); -``` - -### 3.2 State Transition Functions - -```c -/** - * @brief Request a state transition - * @param target_state Target state - * @param reason Transition reason - * @return true if transition initiated, false if rejected - */ -bool stm_requestTransition(system_state_t target_state, transition_reason_t reason); - -/** - * @brief Validate if a state transition is allowed - * @param from Source state - * @param to Target state - * @return true if transition is valid, false otherwise - */ -bool stm_validateTransition(system_state_t target_state, transition_reason_t reason); - -/** - * @brief Get transition reason for last transition - * @return Transition reason - */ -transition_reason_t stm_getLastTransitionReason(void); -``` - -### 3.3 Teardown Functions - -```c -/** - * @brief Initiate controlled teardown sequence - * @param reason Teardown reason - * @return true if teardown initiated, false if rejected - */ -bool stm_initiateTeardown(teardown_reason_t reason); - -/** - * @brief Check if teardown is complete - * @return true if teardown complete, false otherwise - */ -bool stm_isTeardownComplete(void); - -/** - * @brief Get teardown progress (0-100%) - * @return Teardown progress percentage - */ -uint8_t stm_getTeardownProgress(void); -``` - -### 3.4 Component Registration - -```c -/** - * @brief State listener callback type - * @param old_state Previous state - * @param new_state New state - * @param reason Transition reason - */ -typedef void (*state_listener_t)(system_state_t old_state, system_state_t new_state, transition_reason_t reason); - -/** - * @brief Register a state change listener - * @param listener Callback function - * @return true if registered, false on error - */ -bool stm_registerStateListener(state_listener_t listener); - -/** - * @brief Unregister a state change listener - * @param listener Callback function to remove - * @return true if unregistered, false if not found - */ -bool stm_unregisterStateListener(state_listener_t listener); -``` - -## 4. Data Types - -### 4.1 System States - -```c -typedef enum { - SYSTEM_STATE_INIT = 0, - SYSTEM_STATE_BOOT_FAILURE, - SYSTEM_STATE_RUNNING, - SYSTEM_STATE_WARNING, - SYSTEM_STATE_FAULT, - SYSTEM_STATE_OTA_PREP, - SYSTEM_STATE_OTA_UPDATE, - SYSTEM_STATE_MC_UPDATE, - SYSTEM_STATE_TEARDOWN, - SYSTEM_STATE_SERVICE, - SYSTEM_STATE_SD_DEGRADED, - SYSTEM_STATE_COUNT -} system_state_t; -``` - -### 4.2 Transition Reasons - -```c -typedef enum { - TRANSITION_REASON_INIT_SUCCESS, - TRANSITION_REASON_SECURE_BOOT_FAIL, - TRANSITION_REASON_NON_FATAL_FAULT, - TRANSITION_REASON_FATAL_FAULT, - TRANSITION_REASON_FAULT_CLEARED, - TRANSITION_REASON_FAULT_ESCALATED, - TRANSITION_REASON_OTA_REQUEST, - TRANSITION_REASON_MC_UPDATE_REQUEST, - TRANSITION_REASON_DEBUG_SESSION, - TRANSITION_REASON_SD_FAILURE, - TRANSITION_REASON_SD_RECOVERED, - TRANSITION_REASON_RECOVERY_ATTEMPT, - TRANSITION_REASON_MANUAL_RESET, - TRANSITION_REASON_OTA_READY, - TRANSITION_REASON_OTA_REJECTED, - TRANSITION_REASON_TEARDOWN_COMPLETE, - TRANSITION_REASON_OTA_SUCCESS, - TRANSITION_REASON_OTA_FAILURE, - TRANSITION_REASON_MC_UPDATE_COMPLETE, - TRANSITION_REASON_SESSION_CLOSED, - TRANSITION_REASON_MANUAL_INTERVENTION -} transition_reason_t; -``` - -### 4.3 Teardown Reasons - -```c -typedef enum { - TEARDOWN_REASON_OTA, - TEARDOWN_REASON_MC_UPDATE, - TEARDOWN_REASON_FATAL_FAULT, - TEARDOWN_REASON_MANUAL_COMMAND, - TEARDOWN_REASON_SYSTEM_RESET -} teardown_reason_t; -``` - -## 5. Threading Model - -- **Owner Task:** System Management Task (HIGH priority) -- **Thread Safety:** Thread-safe (protected by mutex for state transitions) -- **Blocking Operations:** None (all operations are non-blocking) -- **ISR Access:** State queries allowed from ISR (read-only, lock-free) - -## 6. Resource Ownership - -- **State Machine State:** Owned exclusively by STM component -- **State Transition Lock:** Mutex-protected (prevents concurrent transitions) -- **State Listeners:** List maintained by STM (protected by mutex) - -## 7. Error Model - -### 7.1 Error Conditions - -| Error | Condition | Response | -|-------|-----------|----------| -| `STM_ERR_INVALID_STATE` | Invalid state parameter | Return false, log warning | -| `STM_ERR_INVALID_TRANSITION` | Invalid transition requested | Return false, log warning | -| `STM_ERR_TEARDOWN_IN_PROGRESS` | Teardown already in progress | Return false, log info | -| `STM_ERR_LISTENER_FULL` | Too many listeners registered | Return false, log error | - -### 7.2 Diagnostics Emitted - -- `DIAG-SY-STM-0001`: Invalid state transition attempted (WARNING) -- `DIAG-SY-STM-0002`: State transition timeout (ERROR) -- `DIAG-SY-STM-0003`: Teardown sequence failure (FATAL) - -## 8. State-Dependent Behavior - -### 8.1 INIT State - -- **Allowed Operations:** State queries, listener registration -- **Forbidden Operations:** State transitions (except to RUNNING or BOOT_FAILURE) -- **Duration:** Bounded (max 5 seconds) - -### 8.2 RUNNING State - -- **Allowed Operations:** All operations -- **Forbidden Operations:** None -- **Duration:** Indefinite (normal operation) - -### 8.3 TEARDOWN State - -- **Allowed Operations:** State queries, teardown progress queries -- **Forbidden Operations:** New state transitions (except completion transitions) -- **Duration:** Bounded (max 500ms) - -## 9. Dependencies - -### 9.1 Required Components - -- **Event System:** For state change notifications -- **Error Handler:** For fault-triggered transitions -- **Persistence:** For data flush during teardown -- **Logger:** For diagnostic logging - -### 9.2 Required Interfaces - -- Event System publish interface -- Persistence flush interface -- Logger interface - -## 10. Acceptance Tests - -### 10.1 State Transition Tests - -- **T-STM-001:** Valid state transitions succeed -- **T-STM-002:** Invalid state transitions are rejected -- **T-STM-003:** State transition timing meets requirements (≤50ms) - -### 10.2 Teardown Tests - -- **T-STM-004:** Teardown sequence completes within 500ms -- **T-STM-005:** Teardown coordinates data flush -- **T-STM-006:** Teardown prevents new transitions - -### 10.3 Notification Tests - -- **T-STM-007:** State change notifications are sent to all listeners -- **T-STM-008:** State change notifications are non-blocking - -## 11. Traceability - -- **SWR-SYS-001:** FSM implementation -- **SWR-SYS-002:** State transition enforcement -- **SWR-SYS-003:** State-based operation restriction -- **SWR-SYS-004:** State transition notification -- **SWR-SYS-005:** Controlled teardown execution -- **SWR-SYS-006:** Critical data persistence before teardown -- **SWR-SYS-007:** Data integrity protection during shutdown - -## 12. Implementation Notes - -- State machine SHALL be implemented as a table-driven FSM -- State transitions SHALL be atomic (protected by mutex) -- State listeners SHALL be called asynchronously via Event System -- Teardown sequence SHALL coordinate with Persistence component for data flush -- State queries SHALL be lock-free for ISR access (read-only) diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.cpp b/draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.cpp deleted file mode 100644 index 01a0deb..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file stm.cpp - * @brief Stm component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "stm.hpp" -#include "logger.hpp" - -static const char* TAG = "Stm"; - -Stm::Stm() - : m_isInitialized(false) -{ -} - -Stm::~Stm() -{ - deinitialize(); -} - -bool Stm::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4600, asf::logger::Criticality::LOW, "Stm initialized successfully"); - return true; -} - -bool Stm::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Stm::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.hpp b/draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.hpp deleted file mode 100644 index 7bee08c..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/com/stm.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file stm.hpp - * @brief Stm component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef STM_HPP -#define STM_HPP - -#include - -/** - * @brief Stm class - * - * Component description goes here. - */ -class Stm -{ -public: - Stm(); - ~Stm(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // STM_HPP diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/logging_data.csv b/draft- to be removed SW/components/application_layer/business_stack/STM/logging_data.csv deleted file mode 100644 index 6557253..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4600,STM,INFO,Low,Stm initialized successfully diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.py b/draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.py deleted file mode 100644 index e5dc64d..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_stm_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Stm initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_stm_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.test_scenario.xml deleted file mode 100644 index e7afc62..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/test/stm_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - STM_INIT_TEST - - python components/application_layer/business_stack/STM/test/stm_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/STM/test/test_stm.cpp b/draft- to be removed SW/components/application_layer/business_stack/STM/test/test_stm.cpp deleted file mode 100644 index 9eaff9c..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/STM/test/test_stm.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_stm.cpp - * @brief Unit tests for Stm component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "stm.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_stm_initialize(void) -{ - Stm comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_stm_deinitialize(void) -{ - Stm comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/CMakeLists.txt b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/CMakeLists.txt deleted file mode 100644 index 0e27c26..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/actuator_manager.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.cpp b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.cpp deleted file mode 100644 index dd1023f..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file actuator_manager.cpp - * @brief ActuatorManager component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ -#include "logger.hpp" -#include "actuator_manager.hpp" - -static const char* TAG = "actuator_manager"; - -ActuatorManager::ActuatorManager() - : m_isInitialized(false) -{ -} - -ActuatorManager::~ActuatorManager() -{ - deinitialize(); -} - -bool ActuatorManager::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4000, asf::logger::Criticality::LOW, "actuator manager initialized successfully"); - return true; -} - -bool ActuatorManager::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool ActuatorManager::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.hpp b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.hpp deleted file mode 100644 index b931e24..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/com/actuator_manager.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file actuator_manager.hpp - * @brief ActuatorManager component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef ACTUATOR_MANAGER_HPP -#define ACTUATOR_MANAGER_HPP - -#include - -/** - * @brief ActuatorManager class - * - * Component description goes here. - */ -class ActuatorManager -{ -public: - ActuatorManager(); - ~ActuatorManager(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // ACTUATOR_MANAGER_HPP diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/logging_data.csv b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/logging_data.csv deleted file mode 100644 index 490cc53..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4000,ActuatorManager,INFO,Low,actuator manager initialized successfully diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/__pycache__/robot_keywords.cpython-313.pyc b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/__pycache__/robot_keywords.cpython-313.pyc deleted file mode 100644 index 2ad88960aa11b2831de694a92bdc7b09bc292773..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2637 zcmc&$O>7&-6`tk)pGb;oWJ|KGvEx`_BGU0skVJ_axRPc4Sc*f6u>&#KESE!Sqvb9$ zGizFVh}HIx*a@H@Z4ehlQJ^Om?ZL+$eavxf2{5r%3is#YOOZrI&v`>}B?UethX5I3 z_x;R!Z@+o(%?!7CdSVF1(Enz&VjQ9W2*DfvF0-`&%;%_xiqb5i+f<@bNA^)4P~WV7 zCO`vN%=u@7Ga(wns2n(gih&oU?I^`iF*u0clV0owrQy1i4L=gnd{%P9%Vecx(kiea z-K^IMwFe7?F^kJc~jnZJxAE!6#HgNmLA<@_Wn1 zd%u(TzP*r+pptJ7lH`*XduG#5&H};+JkeJ|hJP{R%@=k!Pb0qMrQQe>V@B{0D)|e) z*q!&d!ak4Nr8}OXQs~*PTA4wp6ez4YDu0$!2gFae3=z%CnUM9wV4_T9|LC2-Omw}&Q&5MUURK;|sCcPb8nNvY;MMOF;%|S)7eYP1ZSO&vy zo|`M-sz!;*^%bnZK4+W~rNJ;PIiNTaSxk~Wy z$%U-X4YDPo>uyq2n%ts9HZ9(?cs6Edo^-Q)xj8pTSo73LU>mOQ^qd{aRjGD`*w5EA zot&vynqECFJms3Mu%&!OGe))AnFg{!k)>r`njX{sI0F+w#(x1$Zy z7-PJunRY(5cuC>vQq`=#gNt0DTr=w1Iqam4C{$e%Du_9TM_g&-kvMv@K{o^eU1C64&xPr?&Otqd;~2JkbGaOzJG(GGg(u%A z%};K%@hZz_dtIN&+<>7ph#O;8rCVs%Pc4Ir!`lsad&3Q0G@Hb50~e<+ zo^wORg^4#x3$RRpMtg)|1khE*%AmBIYE3r^ARC&YaN_zkgF^u+HL06C%OLSwGmUdX z&PLo+7p2TiS)g{qBC5!yUu}Tofr>Fv5m`*SiEW={QSQ1M=zKS(>O?W*PIkqX#@*qz zCdSHVi<3A9jc!p!gdo3gqFmQFQG}2yPL)-&(KHQWa8_2DOs z86c?3Wkuzd!c8hS6a%hGTIPiDGBqnEm%EE$`R0l{NC_ichTf4|aJ|aVHgaS8dZo_; z!Z1ASI<(L#dYnX&*oUoOw>~}k+iRPV%v$nB(%JX=9qyFhy%$lwjfCT&)$zv}6pVj3 z|C@Q|sfjzXGf{F%Z#jLJHUgLbo7{gtdFWp9P&*ReObx7EyM7JG{S>~N!tI{kcDlDc zH2h6ZI2Bqw|2T~@{a*}xHt@Tl)tQHV`&TctW65@^f9-?oAKXtJyPG<;o_hA9z(3=u zhXV)yJotyfKOXpKW;2mlo4+xC^PO8`w?>_zmo^eFe;q>U;q}yLd-&;36PxM&FOr`n zox>+@zwVqIzjN9dp4v!H|38Bg`yVFy?k5i3O&r`v3~#1-*IL(GH;;aNZ8JUCaTz}U zC3mVz_tILsZ{Onx>gipZzA^pr?9J!yCXW8yf9w3;66^8P0>FhE7o4FJw?}Rd{Nu1Q z@Y+V=O#8=%-ppX<>8US=ovF8-w=0hNo>N(Nmbr7-TF+c@5?8(*mry*l1r5=&B zk&V!&fY3hi5;vTi?36gKG_`ycwh$G6iQMRpva@44h5aj{qr&SsVGwz(VOA}j{F0sk zQ5+cT1$ce!mn7){>V1Hs4^aFobmS{^;9pY2i9WL~9ozE#N|IXAmLK^>zS-tG5x)ap C#%X~7 diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.py b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.py deleted file mode 100644 index 37ade85..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_actuator_manager_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Actuator Manager initialized successfully" in line or "actuator manager initialized successfully" in line.lower(): - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_actuator_manager_initialize() - sys.exit(exit_code) \ No newline at end of file diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.test_scenario.xml deleted file mode 100644 index a390a76..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.test_scenario.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - SIMULATE - - - ACTUATOR_MANAGER_INIT_TEST - - python components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.py - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test2.py b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test2.py deleted file mode 100644 index 8445989..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test2.py +++ /dev/null @@ -1,56 +0,0 @@ -import sys -import os - -# Get the absolute path to the folder you want to add -# Example: Adding a folder named 'my_components' located in the current directory -folder_path = os.path.abspath("components/system_tests") -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner -import time - -# --- Main Logic --- -if __name__ == "__main__": - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - keyword_found = False - # Force print to terminal immediately - print("--- QEMU Runner Started ---", flush=True) - - try: - start_time = time.time() - import sys - import os - import time - - folder_path = os.path.abspath(os.path.join("components", "system_tests")) - if folder_path not in sys.path: - sys.path.append(folder_path) - - from scan_serial import ESP32Runner - - def test_actuator_manager_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "actuator manager initialized successfully" in line.lower() or "Actuator Manager initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - - if __name__ == "__main__": - exit_code = test_actuator_manager_initialize() - sys.exit(exit_code) \ No newline at end of file diff --git a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/test_actuator_manager.cpp b/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/test_actuator_manager.cpp deleted file mode 100644 index 2c0461b..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/actuator_manager/test/test_actuator_manager.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_actuator_manager.cpp - * @brief Unit tests for ActuatorManager component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "actuator_manager.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_actuator_manager_initialize(void) -{ - ActuatorManager comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_actuator_manager_deinitialize(void) -{ - ActuatorManager comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/CMakeLists.txt b/draft- to be removed SW/components/application_layer/business_stack/event_system/CMakeLists.txt deleted file mode 100644 index 2191967..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/event_system.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md b/draft- to be removed SW/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md deleted file mode 100644 index 3043c9c..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md +++ /dev/null @@ -1,200 +0,0 @@ -# Event System Component Specification - -**Component ID:** COMP-EVENT -**Version:** 1.0 -**Date:** 2025-01-19 -**Location:** `application_layer/business_stack/event_system/` - -## 1. Purpose - -The Event System provides a publish/subscribe event bus for cross-component communication. It decouples components, enables asynchronous event delivery, and ensures non-blocking operation. - -## 2. Responsibilities - -### 2.1 Primary Responsibilities - -- Provide publish/subscribe event bus -- Decouple components via events -- Ensure non-blocking event delivery -- Support multiple subscribers per event type -- Queue management for event delivery - -### 2.2 Non-Responsibilities - -- Business logic (components handle events) -- Event payload validation (components validate) -- Event ordering guarantees (best-effort) - -## 3. Public API - -### 3.1 Event Publishing - -```c -/** - * @brief Publish an event - * @param type Event type - * @param payload Event payload (may be NULL) - * @param payload_size Payload size in bytes (0 if payload is NULL) - * @return true if published, false on error - */ -bool event_publish(event_type_t type, const void* payload, size_t payload_size); - -/** - * @brief Publish an event with timestamp - * @param type Event type - * @param payload Event payload - * @param payload_size Payload size - * @param timestamp Event timestamp - * @return true if published, false on error - */ -bool event_publishWithTimestamp(event_type_t type, const void* payload, size_t payload_size, uint64_t timestamp); -``` - -### 3.2 Event Subscription - -```c -/** - * @brief Event handler callback type - * @param type Event type - * @param payload Event payload - * @param payload_size Payload size - * @param timestamp Event timestamp - */ -typedef void (*event_handler_t)(event_type_t type, const void* payload, size_t payload_size, uint64_t timestamp); - -/** - * @brief Subscribe to an event type - * @param type Event type to subscribe to - * @param handler Callback function - * @return true if subscribed, false on error - */ -bool event_subscribe(event_type_t type, event_handler_t handler); - -/** - * @brief Unsubscribe from an event type - * @param type Event type to unsubscribe from - * @param handler Callback function to remove - * @return true if unsubscribed, false if not found - */ -bool event_unsubscribe(event_type_t type, event_handler_t handler); -``` - -### 3.3 Event Queue Management - -```c -/** - * @brief Get number of pending events - * @param type Event type (EVENT_TYPE_ALL for all types) - * @return Number of pending events - */ -size_t event_getPendingCount(event_type_t type); - -/** - * @brief Clear pending events - * @param type Event type (EVENT_TYPE_ALL for all types) - * @return Number of events cleared - */ -size_t event_clearPending(event_type_t type); -``` - -## 4. Data Types - -### 4.1 Event Types - -```c -typedef enum { - EVENT_SENSOR_DATA_UPDATE = 0, - EVENT_DIAGNOSTIC_EVENT, - EVENT_STATE_CHANGED, - EVENT_OTA_REQUEST, - EVENT_OTA_STATUS, - EVENT_MC_UPDATE_REQUEST, - EVENT_COMMUNICATION_LINK_STATUS, - EVENT_STORAGE_STATUS, - EVENT_SYSTEM_HEALTH_UPDATE, - EVENT_TYPE_ALL = 0xFF, - EVENT_TYPE_COUNT -} event_type_t; -``` - -### 4.2 Event Structure - -```c -typedef struct { - event_type_t type; - uint64_t timestamp; - size_t payload_size; - uint8_t payload[]; // Variable-length payload -} event_t; -``` - -## 5. Threading Model - -- **Owner Task:** Event System Task (MEDIUM priority) or shared with components -- **Thread Safety:** Thread-safe (lock-free queue for publishing, mutex for subscription management) -- **Blocking Operations:** None (all operations are non-blocking) -- **ISR Access:** Publish allowed from ISR (lock-free queue) - -## 6. Resource Ownership - -- **Event Queue:** Owned by Event System (lock-free ring buffer) -- **Subscriber List:** Protected by mutex -- **Event Buffers:** Pre-allocated static buffers (no dynamic allocation) - -## 7. Error Model - -### 7.1 Error Conditions - -| Error | Condition | Response | -|-------|-----------|----------| -| `EVENT_ERR_QUEUE_FULL` | Event queue full | Drop oldest event, log warning | -| `EVENT_ERR_INVALID_TYPE` | Invalid event type | Return false, log warning | -| `EVENT_ERR_PAYLOAD_TOO_LARGE` | Payload exceeds maximum | Return false, log error | -| `EVENT_ERR_SUBSCRIBER_FULL` | Too many subscribers | Return false, log error | - -### 7.2 Diagnostics Emitted - -- `DIAG-SY-EVENT-0001`: Event queue full (WARNING) -- `DIAG-SY-EVENT-0002`: Event dropped due to queue full (WARNING) -- `DIAG-SY-EVENT-0003`: Subscriber callback failure (ERROR) - -## 8. State-Dependent Behavior - -- **All States:** Event System operates in all states -- **TEARDOWN State:** Event publishing limited to teardown-related events -- **FAULT State:** Event publishing limited to diagnostic events - -## 9. Dependencies - -### 9.1 Required Components - -- **Logger:** For diagnostic logging -- **Time Utils:** For timestamp generation - -### 9.2 Required Interfaces - -- Logger interface -- Time Utils interface - -## 10. Acceptance Tests - -- **T-EVENT-001:** Events are published successfully -- **T-EVENT-002:** Subscribers receive events -- **T-EVENT-003:** Multiple subscribers receive same event -- **T-EVENT-004:** Event publishing is non-blocking -- **T-EVENT-005:** Event queue overflow handling -- **T-EVENT-006:** Event unsubscription works correctly - -## 11. Traceability - -- **SWR-DESIGN-006:** Event System for cross-component communication -- **CFC-TIME-01:** Non-blocking operation -- **Architecture Requirement:** Event-driven communication - -## 12. Implementation Notes - -- Event queue SHALL be implemented as lock-free ring buffer -- Maximum queue size: 100 events -- Maximum payload size: 256 bytes -- Maximum subscribers per event type: 10 -- Event handlers SHALL be called synchronously (in publisher's context) or asynchronously (in event task context) based on configuration diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.cpp b/draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.cpp deleted file mode 100644 index 4df89d6..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file event_system.cpp - * @brief EventSystem component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ -#include "logger.hpp" -#include "event_system.hpp" - -static const char* TAG = "event system"; - -EventSystem::EventSystem() - : m_isInitialized(false) -{ -} - -EventSystem::~EventSystem() -{ - deinitialize(); -} - -bool EventSystem::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4200, asf::logger::Criticality::LOW, "event system initialized successfully"); - return true; -} - -bool EventSystem::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool EventSystem::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.hpp b/draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.hpp deleted file mode 100644 index b119e0f..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/com/event_system.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file event_system.hpp - * @brief EventSystem component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef EVENT_SYSTEM_HPP -#define EVENT_SYSTEM_HPP - -#include - -/** - * @brief EventSystem class - * - * Component description goes here. - */ -class EventSystem -{ -public: - EventSystem(); - ~EventSystem(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // EVENT_SYSTEM_HPP diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/logging_data.csv b/draft- to be removed SW/components/application_layer/business_stack/event_system/logging_data.csv deleted file mode 100644 index 220b1a9..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4200,EventSystem,INFO,Low,event system initialized successfully diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.py b/draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.py deleted file mode 100644 index d76ad38..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_event_system_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "event system initialized successfully" in line.lower() or "Event System initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_event_system_initialize() - sys.exit(exit_code) \ No newline at end of file diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.test_scenario.xml deleted file mode 100644 index 01aa3a5..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/test/event_system_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - ACTUATOR_MANAGER_INIT_TEST - - python components/application_layer/business_stack/event_system/test/event_system_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/event_system/test/test_event_system.cpp b/draft- to be removed SW/components/application_layer/business_stack/event_system/test/test_event_system.cpp deleted file mode 100644 index 88a7905..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/event_system/test/test_event_system.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_event_system.cpp - * @brief Unit tests for EventSystem component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "event_system.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_event_system_initialize(void) -{ - EventSystem comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_event_system_deinitialize(void) -{ - EventSystem comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/CMakeLists.txt b/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/CMakeLists.txt deleted file mode 100644 index 63ff9a7..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/fw_upgrader.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.cpp b/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.cpp deleted file mode 100644 index 5297062..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file fw_upgrader.cpp - * @brief FwUpgrader component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "fw_upgrader.hpp" -#include "logger.hpp" - -static const char* TAG = "FwUpgrader"; - -FwUpgrader::FwUpgrader() - : m_isInitialized(false) -{ -} - -FwUpgrader::~FwUpgrader() -{ - deinitialize(); -} - -bool FwUpgrader::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4300, asf::logger::Criticality::LOW, "FwUpgrader initialized successfully"); - return true; -} - -bool FwUpgrader::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool FwUpgrader::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.hpp b/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.hpp deleted file mode 100644 index 0dc3d06..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file fw_upgrader.hpp - * @brief FwUpgrader component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef FW_UPGRADER_HPP -#define FW_UPGRADER_HPP - -#include - -/** - * @brief FwUpgrader class - * - * Component description goes here. - */ -class FwUpgrader -{ -public: - FwUpgrader(); - ~FwUpgrader(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // FW_UPGRADER_HPP diff --git a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/logging_data.csv b/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/logging_data.csv deleted file mode 100644 index 4b4fb9d..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4300,FwUpgrader,INFO,Low,FwUpgrader initialized successfully diff --git a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.py b/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.py deleted file mode 100644 index 2167345..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.py +++ /dev/null @@ -1,44 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - - -def test_fw_upgrader_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "FwUpgrader initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_fw_upgrader_initialize() - sys.exit(exit_code) - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.test_scenario.xml deleted file mode 100644 index 3f06e2d..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - FW_UPGRADER_INIT_TEST - - python components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/test_fw_upgrader.cpp b/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/test_fw_upgrader.cpp deleted file mode 100644 index c889348..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/fw_upgrader/test/test_fw_upgrader.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_fw_upgrader.cpp - * @brief Unit tests for FwUpgrader component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "fw_upgrader.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_fw_upgrader_initialize(void) -{ - FwUpgrader comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_fw_upgrader_deinitialize(void) -{ - FwUpgrader comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/CMakeLists.txt b/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/CMakeLists.txt deleted file mode 100644 index c53d33d..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/machine_constant_manager.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.cpp b/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.cpp deleted file mode 100644 index 5d6631f..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file machine_constant_manager.cpp - * @brief MachineConstantManager component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "machine_constant_manager.hpp" -#include "logger.hpp" - -static const char* TAG = "MachineConstantManager"; - -MachineConstantManager::MachineConstantManager() - : m_isInitialized(false) -{ -} - -MachineConstantManager::~MachineConstantManager() -{ - deinitialize(); -} - -bool MachineConstantManager::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4400, asf::logger::Criticality::LOW, "MachineConstantManager initialized successfully"); - return true; -} - -bool MachineConstantManager::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool MachineConstantManager::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.hpp b/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.hpp deleted file mode 100644 index d6ff107..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file machine_constant_manager.hpp - * @brief MachineConstantManager component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef MACHINE_CONSTANT_MANAGER_HPP -#define MACHINE_CONSTANT_MANAGER_HPP - -#include - -/** - * @brief MachineConstantManager class - * - * Component description goes here. - */ -class MachineConstantManager -{ -public: - MachineConstantManager(); - ~MachineConstantManager(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // MACHINE_CONSTANT_MANAGER_HPP diff --git a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/logging_data.csv b/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/logging_data.csv deleted file mode 100644 index 459cd25..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4400,MachineConstantManager,INFO,Low,MachineConstantManager initialized successfully diff --git a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.py b/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.py deleted file mode 100644 index d292b07..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_machine_constant_manager_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "MachineConstantManager initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_machine_constant_manager_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.test_scenario.xml deleted file mode 100644 index 6c80389..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - MACHINE_CONSTANT_MANAGER_INIT_TEST - - python components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/test_machine_constant_manager.cpp b/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/test_machine_constant_manager.cpp deleted file mode 100644 index dfe4498..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/machine_constant_manager/test/test_machine_constant_manager.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_machine_constant_manager.cpp - * @brief Unit tests for MachineConstantManager component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "machine_constant_manager.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_machine_constant_manager_initialize(void) -{ - MachineConstantManager comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_machine_constant_manager_deinitialize(void) -{ - MachineConstantManager comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/CMakeLists.txt b/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/CMakeLists.txt deleted file mode 100644 index 93f4d45..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/main_hub_apis.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.cpp b/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.cpp deleted file mode 100644 index fc047e2..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file main_hub_apis.cpp - * @brief MainHubApis component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "main_hub_apis.hpp" -#include "logger.hpp" - -static const char* TAG = "MainHubApis"; - -MainHubApis::MainHubApis() - : m_isInitialized(false) -{ -} - -MainHubApis::~MainHubApis() -{ - deinitialize(); -} - -bool MainHubApis::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4500, asf::logger::Criticality::LOW, "MainHubApis initialized successfully"); - return true; -} - -bool MainHubApis::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool MainHubApis::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.hpp b/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.hpp deleted file mode 100644 index 2883ef6..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file main_hub_apis.hpp - * @brief MainHubApis component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef MAIN_HUB_APIS_HPP -#define MAIN_HUB_APIS_HPP - -#include - -/** - * @brief MainHubApis class - * - * Component description goes here. - */ -class MainHubApis -{ -public: - MainHubApis(); - ~MainHubApis(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // MAIN_HUB_APIS_HPP diff --git a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/logging_data.csv b/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/logging_data.csv deleted file mode 100644 index 8b3eeb3..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4500,MainHubApis,INFO,Low,MainHubApis initialized successfully diff --git a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.py b/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.py deleted file mode 100644 index 7520105..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_main_hub_apis_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "MainHubApis initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_main_hub_apis_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.test_scenario.xml deleted file mode 100644 index dfea33c..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - MAIN_HUB_APIS_INIT_TEST - - python components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/test_main_hub_apis.cpp b/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/test_main_hub_apis.cpp deleted file mode 100644 index fcf6ece..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/main_hub_apis/test/test_main_hub_apis.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_main_hub_apis.cpp - * @brief Unit tests for MainHubApis component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "main_hub_apis.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_main_hub_apis_initialize(void) -{ - MainHubApis comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_main_hub_apis_deinitialize(void) -{ - MainHubApis comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/CMakeLists.txt b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/CMakeLists.txt deleted file mode 100644 index 4950544..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/sensor_manager.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/COMPONENT_SPEC.md b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/COMPONENT_SPEC.md deleted file mode 100644 index 6885d75..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/COMPONENT_SPEC.md +++ /dev/null @@ -1,652 +0,0 @@ -# Sensor Manager Component Specification - -**Component ID:** COMP-SENSOR-MGR -**Version:** 1.0 -**Date:** 2025-01-19 -**Location:** `application_layer/business_stack/sensor_manager/` - -## 1. Purpose - -The Sensor Manager component coordinates all sensor-related operations including lifecycle management, data acquisition scheduling, high-frequency sampling, local filtering, and sensor state management. It serves as the central coordinator for the Sensor Data Acquisition feature (F-DAQ). - -## 2. Responsibilities - -### 2.1 Primary Responsibilities - -- **Sensor Lifecycle Management:** Detection, initialization, configuration, and teardown -- **Data Acquisition Coordination:** Scheduling and executing sensor sampling cycles -- **High-Frequency Sampling:** Multiple samples per sensor per cycle with configurable parameters -- **Local Data Filtering:** Apply configurable filters (median, moving average, rate-of-change limiter) -- **Sensor State Management:** Track and manage sensor operational states -- **Data Record Generation:** Create timestamped sensor data records -- **Event Publication:** Publish sensor data updates and state changes via Event System - -### 2.2 Non-Responsibilities - -- **Hardware Access:** Delegated to sensor drivers (no direct I2C/SPI/UART access) -- **Data Persistence:** Delegated to Data Persistence component -- **Communication:** Delegated to Communication components -- **Fault Detection Logic:** Uses Error Handler for fault reporting -- **Time Management:** Uses Time Utils for timestamp generation - -## 3. Public API - -### 3.1 Initialization and Configuration - -```c -/** - * @brief Initialize Sensor Manager component - * @return true if initialization successful, false otherwise - */ -bool sensorMgr_initialize(void); - -/** - * @brief Load sensor configuration from Machine Constants - * @param mc Machine constants structure - * @return true if configuration loaded, false on error - */ -bool sensorMgr_loadConfiguration(const machine_constants_t* mc); - -/** - * @brief Detect all connected sensors - * @return Number of sensors detected - */ -uint8_t sensorMgr_detectSensors(void); - -/** - * @brief Shutdown Sensor Manager (cleanup resources) - * @return true if shutdown successful, false otherwise - */ -bool sensorMgr_shutdown(void); -``` - -### 3.2 Acquisition Control - -```c -/** - * @brief Start sensor data acquisition - * @return true if acquisition started, false on error - */ -bool sensorMgr_startAcquisition(void); - -/** - * @brief Stop sensor data acquisition - * @return true if acquisition stopped, false on error - */ -bool sensorMgr_stopAcquisition(void); - -/** - * @brief Pause sensor data acquisition - * @return true if acquisition paused, false on error - */ -bool sensorMgr_pauseAcquisition(void); - -/** - * @brief Resume sensor data acquisition - * @return true if acquisition resumed, false on error - */ -bool sensorMgr_resumeAcquisition(void); - -/** - * @brief Check if acquisition is active - * @return true if acquisition is running, false otherwise - */ -bool sensorMgr_isAcquisitionActive(void); -``` - -### 3.3 Sensor Control - -```c -/** - * @brief Enable a specific sensor - * @param sensor_id Sensor identifier (0-6) - * @return true if sensor enabled, false on error - */ -bool sensorMgr_enableSensor(uint8_t sensor_id); - -/** - * @brief Disable a specific sensor - * @param sensor_id Sensor identifier (0-6) - * @return true if sensor disabled, false on error - */ -bool sensorMgr_disableSensor(uint8_t sensor_id); - -/** - * @brief Configure sensor parameters - * @param sensor_id Sensor identifier - * @param config Sensor configuration structure - * @return true if configuration applied, false on error - */ -bool sensorMgr_configureSensor(uint8_t sensor_id, const sensor_config_t* config); - -/** - * @brief Recalibrate a sensor - * @param sensor_id Sensor identifier - * @param calibration_data Calibration parameters - * @return true if calibration applied, false on error - */ -bool sensorMgr_calibrateSensor(uint8_t sensor_id, const sensor_calibration_t* calibration_data); -``` - -### 3.4 Data Access - -```c -/** - * @brief Get latest data from a specific sensor - * @param sensor_id Sensor identifier - * @param record Output buffer for sensor data record - * @return true if data retrieved, false on error - */ -bool sensorMgr_getLatestData(uint8_t sensor_id, sensor_data_record_t* record); - -/** - * @brief Get latest data from all sensors - * @param records Output buffer for sensor data records - * @param count Input: buffer size, Output: number of records filled - * @return true if data retrieved, false on error - */ -bool sensorMgr_getAllSensorData(sensor_data_record_t* records, size_t* count); - -/** - * @brief Get sensor data with history (last N samples) - * @param sensor_id Sensor identifier - * @param records Output buffer for historical records - * @param count Input: requested count, Output: actual count returned - * @return true if data retrieved, false on error - */ -bool sensorMgr_getSensorHistory(uint8_t sensor_id, sensor_data_record_t* records, size_t* count); -``` - -### 3.5 State Management - -```c -/** - * @brief Get sensor operational state - * @param sensor_id Sensor identifier - * @return Current sensor state - */ -sensor_state_t sensorMgr_getSensorState(uint8_t sensor_id); - -/** - * @brief Check if sensor is present (detected) - * @param sensor_id Sensor identifier - * @return true if sensor is present, false otherwise - */ -bool sensorMgr_isSensorPresent(uint8_t sensor_id); - -/** - * @brief Check if sensor is enabled for acquisition - * @param sensor_id Sensor identifier - * @return true if sensor is enabled, false otherwise - */ -bool sensorMgr_isSensorEnabled(uint8_t sensor_id); - -/** - * @brief Check if sensor is healthy (no faults) - * @param sensor_id Sensor identifier - * @return true if sensor is healthy, false if faulty - */ -bool sensorMgr_isSensorHealthy(uint8_t sensor_id); - -/** - * @brief Get sensor information - * @param sensor_id Sensor identifier - * @param info Output buffer for sensor information - * @return true if information retrieved, false on error - */ -bool sensorMgr_getSensorInfo(uint8_t sensor_id, sensor_info_t* info); -``` - -### 3.6 Statistics and Diagnostics - -```c -/** - * @brief Get sensor acquisition statistics - * @param sensor_id Sensor identifier - * @param stats Output buffer for statistics - * @return true if statistics retrieved, false on error - */ -bool sensorMgr_getSensorStatistics(uint8_t sensor_id, sensor_stats_t* stats); - -/** - * @brief Reset sensor statistics - * @param sensor_id Sensor identifier (SENSOR_ID_ALL for all sensors) - * @return true if statistics reset, false on error - */ -bool sensorMgr_resetSensorStatistics(uint8_t sensor_id); - -/** - * @brief Get overall acquisition performance metrics - * @param metrics Output buffer for performance metrics - * @return true if metrics retrieved, false on error - */ -bool sensorMgr_getPerformanceMetrics(acquisition_metrics_t* metrics); -``` - -## 4. Data Types - -### 4.1 Sensor States - -```c -typedef enum { - SENSOR_STATE_UNKNOWN = 0, // Initial state, not yet detected - SENSOR_STATE_DETECTED, // Sensor presence confirmed - SENSOR_STATE_INITIALIZED, // Driver loaded and configured - SENSOR_STATE_ENABLED, // Active data acquisition - SENSOR_STATE_DISABLED, // Present but not acquiring data - SENSOR_STATE_FAULTY, // Detected failure condition - SENSOR_STATE_REMOVED, // Previously present, now absent - SENSOR_STATE_CALIBRATING, // Calibration in progress - SENSOR_STATE_COUNT -} sensor_state_t; -``` - -### 4.2 Sensor Types - -```c -typedef enum { - SENSOR_TYPE_TEMPERATURE = 0, - SENSOR_TYPE_HUMIDITY, - SENSOR_TYPE_CO2, - SENSOR_TYPE_NH3, - SENSOR_TYPE_VOC, - SENSOR_TYPE_PM, - SENSOR_TYPE_LIGHT, - SENSOR_TYPE_COUNT -} sensor_type_t; -``` - -### 4.3 Sensor Data Record - -```c -typedef struct { - uint8_t sensor_id; // Sensor identifier (0-6) - sensor_type_t sensor_type; // Type of sensor - float filtered_value; // Processed sensor value - char unit[8]; // Unit of measurement (e.g., "°C", "%RH") - uint64_t timestamp_ms; // Timestamp in milliseconds - data_validity_t validity; // Data validity status - uint16_t sample_count; // Number of samples used for filtering - float raw_min, raw_max; // Min/max of raw samples - float raw_stddev; // Standard deviation of raw samples - uint32_t acquisition_time_us; // Time taken for acquisition (microseconds) -} sensor_data_record_t; -``` - -### 4.4 Sensor Configuration - -```c -typedef struct { - uint16_t sampling_count; // Number of samples per cycle (5-20) - uint32_t sampling_interval_ms; // Interval between samples - filter_type_t filter_type; // Filter algorithm to use - filter_params_t filter_params; // Filter-specific parameters - float min_valid_value; // Minimum valid sensor value - float max_valid_value; // Maximum valid sensor value - float rate_limit_per_sec; // Maximum rate of change per second - bool enable_outlier_rejection; // Enable outlier detection - float outlier_threshold; // Outlier detection threshold (std devs) -} sensor_config_t; -``` - -### 4.5 Filter Types - -```c -typedef enum { - FILTER_TYPE_NONE = 0, // No filtering (use raw average) - FILTER_TYPE_MEDIAN, // Median filter - FILTER_TYPE_MOVING_AVERAGE, // Moving average filter - FILTER_TYPE_RATE_LIMITED, // Rate-of-change limiter - FILTER_TYPE_COMBINED, // Combination of filters - FILTER_TYPE_COUNT -} filter_type_t; - -typedef struct { - union { - struct { - uint8_t window_size; // Window size for median filter - } median; - struct { - uint8_t window_size; // Window size for moving average - float alpha; // Exponential smoothing factor - } moving_avg; - struct { - float max_rate; // Maximum rate of change per second - float recovery_time; // Time to recover from rate limiting - } rate_limit; - }; -} filter_params_t; -``` - -### 4.6 Sensor Statistics - -```c -typedef struct { - uint32_t total_acquisitions; // Total number of acquisition cycles - uint32_t successful_acquisitions; // Successful acquisitions - uint32_t failed_acquisitions; // Failed acquisitions - uint32_t timeout_count; // Number of timeouts - uint32_t outlier_count; // Number of outliers detected - float avg_acquisition_time_ms; // Average acquisition time - float max_acquisition_time_ms; // Maximum acquisition time - float min_value, max_value; // Min/max values recorded - float avg_value; // Average value - uint64_t last_acquisition_time; // Timestamp of last acquisition - uint32_t consecutive_failures; // Current consecutive failure count -} sensor_stats_t; -``` - -## 5. Internal State Machine - -### 5.1 Sensor State Transitions - -```mermaid -stateDiagram-v2 - [*] --> UNKNOWN - UNKNOWN --> DETECTED : Presence detected - DETECTED --> INITIALIZED : Driver loaded successfully - DETECTED --> UNKNOWN : Detection lost - - INITIALIZED --> ENABLED : Enable command - INITIALIZED --> DETECTED : Initialization failed - - ENABLED --> DISABLED : Disable command - ENABLED --> FAULTY : Failure detected - ENABLED --> CALIBRATING : Calibration requested - ENABLED --> REMOVED : Sensor removed - - DISABLED --> ENABLED : Enable command - DISABLED --> REMOVED : Sensor removed - - FAULTY --> ENABLED : Recovery successful - FAULTY --> REMOVED : Sensor removed - - CALIBRATING --> ENABLED : Calibration complete - CALIBRATING --> FAULTY : Calibration failed - - REMOVED --> DETECTED : Sensor reconnected -``` - -### 5.2 Acquisition Cycle State Machine - -```mermaid -stateDiagram-v2 - [*] --> IDLE - IDLE --> SAMPLING : Acquisition cycle start - SAMPLING --> FILTERING : All samples collected - SAMPLING --> ERROR : Sampling timeout/failure - FILTERING --> TIMESTAMPING : Filtering complete - FILTERING --> ERROR : Filter failure - TIMESTAMPING --> PUBLISHING : Timestamp generated - PUBLISHING --> IDLE : Event published - ERROR --> IDLE : Error handled -``` - -## 6. Component Interactions - -### 6.1 Sensor Acquisition Flow - -```mermaid -sequenceDiagram - participant Timer as Acquisition Timer - participant SM as Sensor Manager - participant Driver as Sensor Driver - participant Filter as Filter Engine - participant TimeUtil as Time Utils - participant EventSys as Event System - participant DataPool as Data Pool - - Note over Timer,DataPool: 1-Second Acquisition Cycle - - Timer->>SM: acquisitionCycleStart() - - loop For each enabled sensor - SM->>SM: checkSensorState(sensor_id) - - alt Sensor is healthy - loop 10 samples - SM->>Driver: readSensor(sensor_id) - Driver-->>SM: raw_sample - end - - SM->>Filter: applyFilter(raw_samples, filter_config) - Filter-->>SM: filtered_value - - SM->>TimeUtil: getCurrentTimestamp() - TimeUtil-->>SM: timestamp - - SM->>SM: createDataRecord(sensor_id, filtered_value, timestamp) - SM->>EventSys: publish(SENSOR_DATA_UPDATE, record) - EventSys->>DataPool: updateSensorData(record) - - else Sensor is faulty - SM->>SM: handleSensorFault(sensor_id) - SM->>EventSys: publish(SENSOR_FAULT_DETECTED, fault_info) - end - end - - SM->>SM: updateAcquisitionStatistics() - - Note over Timer,DataPool: Cycle complete, next cycle in 1 second -``` - -### 6.2 Sensor State Management Flow - -```mermaid -sequenceDiagram - participant SM as Sensor Manager - participant Driver as Sensor Driver - participant EventSys as Event System - participant ErrorHandler as Error Handler - participant MCMgr as MC Manager - - Note over SM,MCMgr: Sensor State Change Scenario - - SM->>Driver: checkSensorPresence(sensor_id) - Driver-->>SM: presence_status - - alt Sensor newly detected - SM->>SM: transitionState(UNKNOWN -> DETECTED) - SM->>Driver: initializeSensor(sensor_id) - Driver-->>SM: init_result - - alt Initialization successful - SM->>SM: transitionState(DETECTED -> INITIALIZED) - SM->>MCMgr: getSensorConfig(sensor_id) - MCMgr-->>SM: sensor_config - SM->>SM: applySensorConfig(sensor_config) - SM->>SM: transitionState(INITIALIZED -> ENABLED) - SM->>EventSys: publish(SENSOR_STATE_CHANGED, state_info) - else Initialization failed - SM->>SM: transitionState(DETECTED -> UNKNOWN) - SM->>ErrorHandler: reportFault(SENSOR_INIT_FAILED) - end - - else Sensor fault detected - SM->>SM: transitionState(ENABLED -> FAULTY) - SM->>ErrorHandler: reportFault(SENSOR_COMMUNICATION_FAILED) - SM->>EventSys: publish(SENSOR_FAULT_DETECTED, fault_info) - - Note over SM,MCMgr: Attempt recovery after delay - SM->>SM: scheduleRecoveryAttempt(sensor_id) - - else Sensor removed - SM->>SM: transitionState(current -> REMOVED) - SM->>EventSys: publish(SENSOR_REMOVED, sensor_info) - end -``` - -## 7. Threading Model - -- **Owner Task:** Sensor Acquisition Task (HIGH priority, 8KB stack) -- **Execution Model:** Periodic execution (1-second cycles) with event-driven state management -- **Thread Safety:** Thread-safe (mutex protection for configuration changes) -- **Blocking Operations:** Bounded sensor I/O operations (max 800ms per cycle) -- **ISR Access:** Not allowed (all operations require task context) - -## 8. Resource Ownership - -- **Sensor Drivers:** Exclusive access during acquisition cycles -- **Sensor Configuration:** Protected by mutex (shared with MC Manager) -- **Sensor Data Buffers:** Owned exclusively by Sensor Manager -- **Filter State:** Per-sensor filter state maintained internally - -## 9. Error Model - -### 9.1 Error Conditions - -| Error | Condition | Response | -|-------|-----------|----------| -| `SENSOR_ERR_INVALID_ID` | Invalid sensor ID parameter | Return false, log warning | -| `SENSOR_ERR_NOT_PRESENT` | Sensor not detected/present | Return false, update state | -| `SENSOR_ERR_COMMUNICATION` | I2C/SPI/UART communication failure | Mark faulty, schedule recovery | -| `SENSOR_ERR_TIMEOUT` | Sensor read timeout | Mark faulty, continue with other sensors | -| `SENSOR_ERR_OUT_OF_RANGE` | Sensor value out of valid range | Mark data invalid, log diagnostic | -| `SENSOR_ERR_FILTER_FAILURE` | Filter algorithm failure | Use raw average, log error | -| `SENSOR_ERR_CONFIG_INVALID` | Invalid configuration parameters | Use default config, log error | - -### 9.2 Diagnostics Emitted - -- `DIAG-DAQ-SENSOR-0001`: Sensor communication failure (WARNING) -- `DIAG-DAQ-SENSOR-0002`: Sensor value out of range (WARNING) -- `DIAG-DAQ-SENSOR-0003`: Acquisition cycle timeout (ERROR) -- `DIAG-DAQ-SENSOR-0004`: Filter algorithm failure (ERROR) -- `DIAG-DAQ-SENSOR-0005`: Sensor configuration error (ERROR) -- `DIAG-DAQ-SENSOR-0006`: Consecutive sensor failures (FATAL) - -## 10. State-Dependent Behavior - -| System State | Sensor Manager Behavior | -|-------------|------------------------| -| **INIT** | Initialize sensors, load configuration, detect presence | -| **RUNNING** | Normal acquisition cycles, full functionality | -| **WARNING** | Continue acquisition, enhanced diagnostic reporting | -| **FAULT** | Stop acquisition, preserve sensor states | -| **OTA_UPDATE** | Stop acquisition, save sensor states for restoration | -| **MC_UPDATE** | Stop acquisition, reload configuration after update | -| **TEARDOWN** | Stop acquisition, flush pending data | -| **SERVICE** | Limited acquisition for diagnostics, enhanced access | -| **SD_DEGRADED** | Continue acquisition, no persistence (memory only) | - -## 11. Dependencies - -### 11.1 Required Components - -- **Sensor Drivers:** Hardware interface for all sensor types -- **Event System:** Cross-component communication -- **Time Utils:** Timestamp generation -- **Machine Constant Manager:** Sensor configuration and calibration data -- **Logger:** Debug and diagnostic logging -- **Error Handler:** Fault reporting and escalation - -### 11.2 Required Interfaces - -- Sensor driver interfaces (I2C, SPI, UART, ADC wrappers) -- Event System publish/subscribe interface -- Time Utils timestamp interface -- MC Manager configuration interface -- Logger interface -- Error Handler fault reporting interface - -## 12. Performance Requirements - -### 12.1 Timing Constraints - -- **Acquisition Cycle:** Complete within 1 second for all enabled sensors -- **Sampling Window:** Maximum 800ms per sensor (10 samples) -- **Filter Processing:** Maximum 50ms per sensor -- **State Transition:** Maximum 100ms for state changes -- **Event Publication:** Maximum 10ms delay - -### 12.2 Resource Constraints - -- **Memory Usage:** Maximum 32KB for sensor data buffers and state -- **CPU Usage:** Maximum 20% of available CPU time -- **Stack Usage:** Maximum 8KB stack for acquisition task - -## 13. Acceptance Tests - -### 13.1 Functional Tests - -- **T-SENSOR-001:** All sensor types detected and initialized correctly -- **T-SENSOR-002:** Acquisition cycles complete within 1-second constraint -- **T-SENSOR-003:** High-frequency sampling (10 samples) works for all sensors -- **T-SENSOR-004:** Filter algorithms reduce noise by >90% -- **T-SENSOR-005:** Sensor state transitions occur correctly -- **T-SENSOR-006:** Fault detection and recovery mechanisms work - -### 13.2 Performance Tests - -- **T-SENSOR-007:** Acquisition timing meets requirements under full load -- **T-SENSOR-008:** Memory usage stays within 32KB limit -- **T-SENSOR-009:** CPU usage stays within 20% limit -- **T-SENSOR-010:** No memory leaks during continuous operation - -### 13.3 Integration Tests - -- **T-SENSOR-011:** Event System integration works correctly -- **T-SENSOR-012:** Data Pool integration maintains latest sensor data -- **T-SENSOR-013:** MC Manager integration loads configuration correctly -- **T-SENSOR-014:** Error Handler integration reports faults correctly - -### 13.4 Stress Tests - -- **T-SENSOR-015:** 24-hour continuous operation without failures -- **T-SENSOR-016:** Sensor fault injection and recovery scenarios -- **T-SENSOR-017:** Configuration changes during operation -- **T-SENSOR-018:** System state transitions during acquisition - -## 14. Traceability - -### 14.1 System Requirements - -- **SR-DAQ-001:** Multi-sensor support for 7 sensor types -- **SR-DAQ-002:** High-frequency sampling (minimum 10 samples/cycle) -- **SR-DAQ-003:** Local data filtering with configurable algorithms -- **SR-DAQ-004:** Timestamped data generation (±1 second accuracy) -- **SR-DAQ-005:** Sensor state management and lifecycle control - -### 14.2 Software Requirements - -- **SWR-DAQ-001 to SWR-DAQ-015:** Complete sensor data acquisition implementation -- **SWR-PERF-001:** Acquisition cycle timing constraints -- **SWR-REL-001:** System availability requirements - -### 14.3 Features - -- **F-DAQ-001:** Multi-Sensor Data Acquisition -- **F-DAQ-002:** High-Frequency Sampling -- **F-DAQ-003:** Local Data Filtering -- **F-DAQ-004:** Timestamped Data Generation -- **F-DAQ-005:** Sensor State Management - -## 15. Implementation Notes - -### 15.1 Design Patterns - -- **State Machine Pattern:** For sensor state management -- **Strategy Pattern:** For filter algorithm selection -- **Observer Pattern:** For sensor state change notifications -- **Template Method Pattern:** For acquisition cycle execution - -### 15.2 Key Implementation Details - -- Sensor drivers SHALL be accessed through uniform interface (SAL) -- Filter algorithms SHALL be pluggable and configurable -- Sensor states SHALL be persisted across system restarts -- Acquisition timing SHALL be deterministic and bounded -- Error handling SHALL be comprehensive and non-blocking - -### 15.3 Future Extensibility - -- Support for additional sensor types through driver registration -- Advanced filter algorithms (Kalman, adaptive filters) -- Sensor fusion capabilities for redundant sensors -- Machine learning-based sensor validation and prediction - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-DAQ, SWR-DAQ) -**Next Review:** After implementation and testing \ No newline at end of file diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.cpp b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.cpp deleted file mode 100644 index e4a3a24..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file sensor_manager.cpp - * @brief SensorManager component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "sensor_manager.hpp" -#include "logger.hpp" - -static const char* TAG = "SensorManager"; - -SensorManager::SensorManager() - : m_isInitialized(false) -{ -} - -SensorManager::~SensorManager() -{ - deinitialize(); -} - -bool SensorManager::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4100, asf::logger::Criticality::LOW, "SensorManager initialized successfully"); - return true; -} - -bool SensorManager::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool SensorManager::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.hpp b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.hpp deleted file mode 100644 index fbba5fc..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/com/sensor_manager.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file sensor_manager.hpp - * @brief SensorManager component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef SENSOR_MANAGER_HPP -#define SENSOR_MANAGER_HPP - -#include - -/** - * @brief SensorManager class - * - * Component description goes here. - */ -class SensorManager -{ -public: - SensorManager(); - ~SensorManager(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // SENSOR_MANAGER_HPP diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/logging_data.csv b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/logging_data.csv deleted file mode 100644 index ab73118..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4100,SensorManager,INFO,Low,SensorManager initialized successfully diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.py b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.py deleted file mode 100644 index ce3a844..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_sensor_manager_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "SensorManager initialized successfully" in line or "Sensor Manager initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_sensor_manager_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.test_scenario.xml deleted file mode 100644 index a84442a..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - SENSOR_MANAGER_INIT_TEST - - python components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/test_sensor_manager.cpp b/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/test_sensor_manager.cpp deleted file mode 100644 index 8a00716..0000000 --- a/draft- to be removed SW/components/application_layer/business_stack/sensor_manager/test/test_sensor_manager.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_sensor_manager.cpp - * @brief Unit tests for SensorManager component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "sensor_manager.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_sensor_manager_initialize(void) -{ - SensorManager comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_sensor_manager_deinitialize(void) -{ - SensorManager comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/diag_task/CMakeLists.txt b/draft- to be removed SW/components/application_layer/diag_task/CMakeLists.txt deleted file mode 100644 index 05c8881..0000000 --- a/draft- to be removed SW/components/application_layer/diag_task/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/diag_task.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/diag_task/com/diag_task.cpp b/draft- to be removed SW/components/application_layer/diag_task/com/diag_task.cpp deleted file mode 100644 index c69f70d..0000000 --- a/draft- to be removed SW/components/application_layer/diag_task/com/diag_task.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file diag_task.cpp - * @brief DiagTask component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "diag_task.hpp" -#include "logger.hpp" - -static const char* TAG = "DiagTask"; - -DiagTask::DiagTask() - : m_isInitialized(false) -{ -} - -DiagTask::~DiagTask() -{ - deinitialize(); -} - -bool DiagTask::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4700, asf::logger::Criticality::LOW, "DiagTask initialized successfully"); - return true; -} - -bool DiagTask::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool DiagTask::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/diag_task/com/diag_task.hpp b/draft- to be removed SW/components/application_layer/diag_task/com/diag_task.hpp deleted file mode 100644 index e6fcfef..0000000 --- a/draft- to be removed SW/components/application_layer/diag_task/com/diag_task.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file diag_task.hpp - * @brief DiagTask component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef DIAG_TASK_HPP -#define DIAG_TASK_HPP - -#include - -/** - * @brief DiagTask class - * - * Component description goes here. - */ -class DiagTask -{ -public: - DiagTask(); - ~DiagTask(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // DIAG_TASK_HPP diff --git a/draft- to be removed SW/components/application_layer/diag_task/logging_data.csv b/draft- to be removed SW/components/application_layer/diag_task/logging_data.csv deleted file mode 100644 index bf7ab7c..0000000 --- a/draft- to be removed SW/components/application_layer/diag_task/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4700,DiagTask,INFO,Low,DiagTask initialized successfully diff --git a/draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.py b/draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.py deleted file mode 100644 index 5afe73c..0000000 --- a/draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_diag_task_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "DiagTask initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_diag_task_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.test_scenario.xml deleted file mode 100644 index d37ecf7..0000000 --- a/draft- to be removed SW/components/application_layer/diag_task/test/diag_task_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - DIAG_TASK_INIT_TEST - - python components/application_layer/diag_task/test/diag_task_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/diag_task/test/test_diag_task.cpp b/draft- to be removed SW/components/application_layer/diag_task/test/test_diag_task.cpp deleted file mode 100644 index 1a784cf..0000000 --- a/draft- to be removed SW/components/application_layer/diag_task/test/test_diag_task.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_diag_task.cpp - * @brief Unit tests for DiagTask component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "diag_task.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_diag_task_initialize(void) -{ - DiagTask comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_diag_task_deinitialize(void) -{ - DiagTask comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/application_layer/error_handler/CMakeLists.txt b/draft- to be removed SW/components/application_layer/error_handler/CMakeLists.txt deleted file mode 100644 index 18bf7f7..0000000 --- a/draft- to be removed SW/components/application_layer/error_handler/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/error_handler.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/application_layer/error_handler/com/error_handler.cpp b/draft- to be removed SW/components/application_layer/error_handler/com/error_handler.cpp deleted file mode 100644 index bfc7583..0000000 --- a/draft- to be removed SW/components/application_layer/error_handler/com/error_handler.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file error_handler.cpp - * @brief ErrorHandler component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "error_handler.hpp" -#include "logger.hpp" - -static const char* TAG = "ErrorHandler"; - -ErrorHandler::ErrorHandler() - : m_isInitialized(false) -{ -} - -ErrorHandler::~ErrorHandler() -{ - deinitialize(); -} - -bool ErrorHandler::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 4800, asf::logger::Criticality::LOW, "ErrorHandler initialized successfully"); - return true; -} - -bool ErrorHandler::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool ErrorHandler::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/application_layer/error_handler/com/error_handler.hpp b/draft- to be removed SW/components/application_layer/error_handler/com/error_handler.hpp deleted file mode 100644 index 6c8338a..0000000 --- a/draft- to be removed SW/components/application_layer/error_handler/com/error_handler.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file error_handler.hpp - * @brief ErrorHandler component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef ERROR_HANDLER_HPP -#define ERROR_HANDLER_HPP - -#include - -/** - * @brief ErrorHandler class - * - * Component description goes here. - */ -class ErrorHandler -{ -public: - ErrorHandler(); - ~ErrorHandler(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // ERROR_HANDLER_HPP diff --git a/draft- to be removed SW/components/application_layer/error_handler/logging_data.csv b/draft- to be removed SW/components/application_layer/error_handler/logging_data.csv deleted file mode 100644 index c8784de..0000000 --- a/draft- to be removed SW/components/application_layer/error_handler/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -4800,ErrorHandler,INFO,Low,ErrorHandler initialized successfully diff --git a/draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.py b/draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.py deleted file mode 100644 index d89323a..0000000 --- a/draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_error_handler_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "ErrorHandler initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_error_handler_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.test_scenario.xml b/draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.test_scenario.xml deleted file mode 100644 index 21c1854..0000000 --- a/draft- to be removed SW/components/application_layer/error_handler/test/error_handler_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - ERROR_HANDLER_INIT_TEST - - python components/application_layer/error_handler/test/error_handler_init_test.py - - - - diff --git a/draft- to be removed SW/components/application_layer/error_handler/test/test_error_handler.cpp b/draft- to be removed SW/components/application_layer/error_handler/test/test_error_handler.cpp deleted file mode 100644 index f806690..0000000 --- a/draft- to be removed SW/components/application_layer/error_handler/test/test_error_handler.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_error_handler.cpp - * @brief Unit tests for ErrorHandler component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "error_handler.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_error_handler_initialize(void) -{ - ErrorHandler comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_error_handler_deinitialize(void) -{ - ErrorHandler comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/arch.md b/draft- to be removed SW/components/arch.md deleted file mode 100644 index 45833c0..0000000 --- a/draft- to be removed SW/components/arch.md +++ /dev/null @@ -1,413 +0,0 @@ -Excellent — this is a **very strong foundation**, and your clarification is important. -Below I will proceed **exactly in the order you requested**, and **strictly scoped to the Sub-Hub (Sensor Hub) firmware only**. - -I will deliver **three clearly separated parts**, written in **formal engineering language**, suitable for ALM / ARCHITECTURE.md usage. - ---- - -# PART 1 — Formal Architecture Document - -## Sub-Hub (Sensor Hub) Firmware Architecture - ---- - -## 1. Document Scope - -This document defines the **static software architecture** of the **Sub-Hub (Sensor Hub)** firmware within the distributed poultry farm automation system. - -The Sub-Hub is a **sensor-focused embedded node** responsible for **environmental data acquisition, local preprocessing, and communication with the Main Hub**. - -⚠ **Explicitly out of scope**: - -* Main Hub firmware -* Cloud services -* Control algorithms -* Actuator management - ---- - -## 2. Architectural Objectives - -The Sub-Hub architecture is designed to achieve the following objectives: - -* Deterministic and reliable sensor data acquisition -* High sensor density support -* Hardware abstraction and portability -* Event-driven internal coordination -* OTA upgradability -* Low power and resource efficiency -* Clear separation between hardware, OS, and application logic - ---- - -## 3. Architectural Style - -The Sub-Hub firmware follows these architectural styles: - -* **Layered Architecture** -* **Component-Based Design** -* **Event-Driven Application Logic** -* **RTOS-based Concurrency Model** -* **Hardware Abstraction via Drivers and OSAL** - -Dependency direction is **strictly top-down**. - ---- - -## 4. Layered Architecture Overview (Top → Bottom) - ---- - -### 4.1 Utilities Layer - -**Purpose:** -Provide reusable, stateless helper functionality across all layers. - -**Responsibilities:** - -* Logging utilities -* Encoding/decoding helpers -* Cryptographic primitives -* Mathematical helpers and unit conversions - -**Constraints:** - -* No RTOS dependencies -* No hardware access -* No business logic - ---- - -### 4.2 Application Layer - -The Application Layer implements **Sub-Hub–specific business logic**, excluding control decisions. - -#### 4.2.1 Business Stack - -**Event System** - -* Publish/subscribe mechanism -* Decouples sensor sampling, networking, persistence, and diagnostics -* Enables asynchronous, non-blocking operation - -**Firmware Upgrader (OTA)** - -* Manages firmware download, validation, and activation -* Interfaces with persistence and network stack -* Supports rollback and version verification - -**Sub-Hub APIs** - -* Defines the logical interface exposed to the Main Hub -* Handles configuration commands, status queries, and diagnostics requests - ---- - -#### 4.2.2 Sensor Manager - -**Responsibilities:** - -* Sensor lifecycle management -* Sensor registration and configuration -* Sampling scheduling -* Data validation and normalization -* Publishing sensor updates as events - -**Design Notes:** - -* One logical handler per sensor family -* No direct hardware access -* Uses drivers exclusively via APIs - ---- - -### 4.3 Diagnostics & Error Handling - -**Diagnostics Task** - -* Periodic system health checks -* Sensor availability checks -* Communication diagnostics -* Resource usage monitoring - -**Error Handler** - -* Centralized fault classification -* Error propagation and escalation -* Integration with logs and alarms - ---- - -### 4.4 Data Pool (DP) Stack & Persistence - -**Purpose:** -Provide a centralized, consistent data model for runtime state and optional durability. - -**Components:** - -* **Data Pool:** In-memory representation of sensor values and metadata -* **Persistence Interface:** Abstract storage API -* **Persistence Task:** Asynchronous write operations - -**Responsibilities:** - -* Maintain latest sensor state -* Support snapshot and restore -* Decouple storage from application logic - ---- - -### 4.5 Device Drivers Layer - -**Purpose:** -Abstract physical devices and protocols behind stable APIs. - -**Included Drivers:** - -* Sensor drivers -* Network protocol adapters -* Diagnostic protocol stack -* Non-volatile memory (NVM) -* SD card (if applicable) - -**Responsibilities:** - -* Hardware access -* Interrupt and DMA handling -* Protocol framing - -**Constraints:** - -* No business logic -* No application state ownership - ---- - -### 4.6 OS Abstraction Layer (OSAL) - -**Purpose:** -Provide platform-independent access to OS and system services. - -**Services:** - -* Task/thread abstraction -* Software timers -* Sockets and TCP/IP abstraction -* Synchronization primitives -* HAL access mediation - ---- - -### 4.7 ESP-IDF Firmware / HAL - -**Purpose:** -Provide low-level system services and hardware support. - -**Components:** - -* RTOS kernel (FreeRTOS) -* ESP-IDF system services -* HAL (GPIO, ADC, I2C, SPI, UART, DMA, Wi-Fi, BT) - ---- - -## 5. Interaction Model - -**Primary Interaction Types:** - -* Event-based (Application internal) -* API-based (Application ↔ Drivers) -* DP-based (Shared state) -* HAL-based (Drivers ↔ Hardware) - -**Typical Data Flow:** - -``` -Sensor Driver → Sensor Manager → Event System -→ Data Pool → Network API → Main Hub -``` - ---- - -## 6. Concurrency Model - -* RTOS tasks for: - - * Diagnostics - * Persistence - * Networking -* Application logic designed to be non-blocking -* Time-critical sensor sampling isolated from network operations - ---- - -## 7. Architectural Constraints - -* Sub-Hub shall not execute control logic -* Sub-Hub shall not directly control actuators -* Sub-Hub shall remain operational during Main Hub disconnection -* Sub-Hub shall tolerate partial sensor failures - ---- - -# PART 2 — PlantUML Diagrams - ---- - -## 2.1 Component Diagram (Sub-Hub) - -```plantuml -@startuml -@startuml -skinparam packageStyle rectangle -title Sub-Hub Component Diagram - -package "Application Layer" { - component "Event System" as ES - component "Sensor Manager" as SM - component "Sub-Hub APIs" as API - component "FW Upgrader (OTA)" as OTA -} - -package "DP Stack" { - component "Data Pool" as DP - component "Persistence Interface" as PI - component "Persistence Task" as PT -} - -package "Diagnostics" { - component "Diagnostics Task" as DT - component "Error Handler" as EH -} - -package "Utilities" { - component "Log" as LOG - component "Enc" as ENC - component "Math" as MATH -} - -package "Device Drivers" { - component "Sensor Drivers" as SD - component "Network Stack" as NET - component "NVM Driver" as NVM -} - -package "OSAL" { - component "Tasks/Timers/Sockets" as OSALC -} - -package "ESP-IDF / HAL" { - component "RTOS Kernel" as K - component "GPIO/ADC/I2C/SPI/UART/WiFi" as HAL -} - -SM --> ES : publish(sensor_update) -SM --> SD : sample()/config() -ES --> DP : update(state) -API --> ES : command()/subscribe() -OTA --> PI : store(fw)/read() -PT --> NVM : write()/read() -SD --> OSALC : irq / DMA -OSALC --> HAL : system calls -ES ..> DT : emits diagnostics events -LOG ..> ES : log() -@enduml -``` - ---- - -## 2.2 Sensor Data Flow (Sequence Diagram) - -```plantuml -@startuml -@startuml -title Sensor Data Flow -participant Sensor -participant "Sensor Driver" as SD -participant "Sensor Manager" as SM -participant "Event System" as ES -participant "Data Pool" as DP -participant "Sub-Hub APIs" as API -participant "Persistence Task" as PT - -Sensor -> SD : sample() -SD -> SM : raw_data -SM -> SM : validate(); normalize() -SM -> ES : publish(sensor_update) -ES -> DP : update(sensor:value) -ES -> API : notify(subscribers) -ES -> PT : async_persist(sensor:value) -PT -> NVM : write() -API --> ES : read(state) // response flow -@enduml -``` - ---- - -# PART 3 — Review Against IEC 61499 and ISA-95 - ---- - -## 3.1 IEC 61499 Alignment (Distributed Control Systems) - -| IEC 61499 Concept | Sub-Hub Mapping | -| ----------------- | ----------------- | -| Function Block | Sensor Manager | -| Event Interface | Event System | -| Data Interface | Data Pool | -| Resource | RTOS Task | -| Device | Sub-Hub MCU | -| Application | Application Layer | - -**Assessment:** -✔ Strong alignment with IEC 61499 event-driven execution -✔ Sensor Manager ≈ Composite Function Block -✔ Event System ≈ Event connections -⚠ Control FBs intentionally excluded (correct for Sub-Hub role) - ---- - -## 3.2 ISA-95 Alignment (Automation Pyramid) - -| ISA-95 Level | Sub-Hub Role | -| ------------ | ---------------- | -| Level 0 | Physical sensors | -| Level 1 | Data acquisition | -| Level 2 | Local monitoring | -| Level 3 | ❌ Not included | -| Level 4 | ❌ Not included | - -**Assessment:** -✔ Correctly positioned at **Level 1–2** -✔ No violation of ISA-95 separation -✔ Clean handoff to Main Hub (Level 2–3 boundary) - ---- - -## 3.3 Expert Verdict - -✅ Architecture is **fully compliant** with IEC 61499 principles -✅ ISA-95 boundaries are respected -✅ Sub-Hub responsibility is correctly constrained -✅ Architecture is **industrial-grade and scalable** - -This is **exactly how a professional sensor node should be architected** in modern industrial IoT systems. - ---- - -## What we should do next (recommended) - -1. Define **Sub-Hub state machine** -2. Define **communication ICD (Sub-Hub ↔ Main Hub)** -3. Define **sensor abstraction model** -4. Define **fault classification table** -5. Prepare **Main Hub architecture** (next logical step) - -If you want, next I can: - -* Turn this into **ISO/IEC/IEEE 42010 compliant architecture views** -* Write **formal architectural constraints & quality attributes** -* Prepare **Main Hub architecture using the same rigor** -* Align Sub-Hub ↔ Main Hub communication with **IEC 61850 / MQTT Sparkplug concepts** - -Just tell me the next step. diff --git a/draft- to be removed SW/components/drivers/SDcard/CMakeLists.txt b/draft- to be removed SW/components/drivers/SDcard/CMakeLists.txt deleted file mode 100644 index 6c07bca..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/sdcard.cpp" - INCLUDE_DIRS "com" - REQUIRES driver fatfs logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/LICENSE.txt b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/LICENSE.txt deleted file mode 100644 index f288702..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/LICENSE.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/README.adoc b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/README.adoc deleted file mode 100644 index ab370cb..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/README.adoc +++ /dev/null @@ -1,13 +0,0 @@ -:repository-owner: arduino-libraries -:repository-name: SD - -= {repository-name} Library for Arduino = - -image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] -image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] -image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] - -The SD library allows for reading from and writing to SD cards. - -For more information about this library please visit us at -http://www.arduino.cc/en/Reference/{repository-name} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/api.md b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/api.md deleted file mode 100644 index 6cdcab9..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/api.md +++ /dev/null @@ -1,894 +0,0 @@ -# SD library - -## SD class - -The SD class provides functions for accessing the SD card and manipulating its files and directories. - -### `begin()` - -Initializes the SD library and card. This begins use of the SPI bus (digital pins 11, 12, and 13 on most Arduino boards; 50, 51, and 52 on the Mega) and the chip select pin, which defaults to the hardware SS pin (pin 10 on most Arduino boards, 53 on the Mega). Note that even if you use a different chip select pin, **the hardware SS pin must be kept as an output or the SD library functions will not work**. - -#### Syntax - -``` -SD.begin() -SD.begin(cspin) -``` - -#### Parameters - -* `cspin` (optional): the pin connected to the chip select line of the SD card; defaults to the hardware SS line of the SPI bus. - -#### Returns - -1 on success, 0 on failure. - -#### See also - -* [exists()](#exists) -* [mkdir()](#mkdir) -* [open()](#open) -* [remove()](#remove) -* [rmdir()](#rmdir) - -### `exists()` - -Tests whether a file or directory exists on the SD card. - -#### Syntax - -``` -SD.exists(filename) -``` - -#### Parameters - -* `filename`: the name of the file to test for existence, which can include directories (delimited by forward-slashes, /). - -#### Returns - -1 if the file or directory exists, 0 if not. - -#### See also - -* [begin()](#begin) -* [mkdir()](#mkdir) -* [open()](#open) -* [remove()](#remove) -* [rmdir()](#rmdir) - -### `exists()` - -Tests whether a file or directory exists on the SD card. - -#### Syntax - -``` -SD.exists(filename) -``` - -#### Parameters - -* `filename`: the name of the file to test for existence, which can include directories (delimited by forward-slashes, /). - -#### Returns - -1 if the file or directory exists, 0 if not. - -#### See also - -* [begin()](#begin) -* [mkdir()](#mkdir) -* [open()](#open) -* [remove()](#remove) -* [rmdir()](#rmdir) - -### `mkdir()` - -Create a directory on the SD card. This will also create any intermediate directories that don't already exists; e.g. `SD.mkdir("a/b/c")` will create a, b, and c. - -#### Syntax - -``` -SD.mkdir(filename) -``` - -#### Parameters - -* `filename`: the name of the directory to create, with sub-directories separated by forward-slashes, /. - -#### Returns - -1 if the creating of the directory succeeded, 0 if not. - -#### See also - -* [begin()](#begin) -* [exists()](#exists) -* [open()](#open) -* [remove()](#remove) -* [rmdir()](#rmdir) - -### `open()` - -Opens a file on the SD card. If the file is opened for writing, it will be created if it doesn't already exist (but the directory containing it must already exist). - -#### Syntax - -``` -SD.open(filepath) -SD.open(filepath, mode) -``` - -#### Parameters - -* `filepath`: the name of the file to open, which can include directories (delimited by forward-slashes, /). -* `mode` (optional): the mode in which to open the file. Mode can be `FILE_READ` (open the file for reading, starting at the beginning of the file) or `FILE_WRITE` (open the file for reading and writing, starting at the end of the file). - -#### Returns - -A File object referring to the opened file; if the file couldn't be opened, this object will evaluate to false in a boolean context, i.e. you can test the return value with "`if (f)`". - -#### See also - -* [begin()](#begin) -* [exists()](#exists) -* [mkdir()](#mkdir) -* [remove()](#remove) -* [rmdir()](#rmdir) - -### `remove()` - -Remove a file from the SD card. - -#### Syntax - -``` -SD.remove(filename) -``` - -#### Parameters - -* `filename`: the name of the file to remove, which can include directories (delimited by forward-slashes, /). - -#### Returns - -1 if the removal of the file succeeded, 0 if not. - -#### See also - -* [begin()](#begin) -* [exists()](#exists) -* [mkdir()](#mkdir) -* [open()](#open) -* [rmdir()](#rmdir) - -### `rmdir()` - -Remove a directory from the SD card. The directory must be empty. - -#### Syntax - -``` -SD.rmdir(filename) -``` - -#### Parameters - -* `filename`: the name of the directory to remove, with sub-directories separated by forward-slashes, /. - -#### Returns - -1 if the removal of the directory succeeded, 0 if not (if the directory didn't exist, the return value is unspecified). - -#### See also - -* [begin()](#begin) -* [exists()](#exists) -* [mkdir()](#mkdir) -* [open()](#open) -* [remove()](#remove) - -## File class - -The File class allows for reading from and writing to individual files on the SD card. - -### `name()` - -Returns the file name - -#### Syntax - -``` -file.name() -``` - -#### Parameters - -None. - -#### Returns - -The file name. - -#### See also - -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `available()` - -Check if there are any bytes available for reading from the file. `available()` inherits from the [Stream](https://www.arduino.cc/reference/en/language/functions/communication/stream/) utility class. - -#### Syntax - -``` -file.available() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -The number of bytes available as an integer. - -#### See also - -* [name()](#name) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `close()` - -Close the file, and ensure that any data written to it is physically saved to the SD card. - -#### Syntax - -``` -file.close() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -None. - -#### See also - -* [name()](#name) -* [available()](#available) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `flush()` - -Ensures that any bytes written to the file are physically saved to the SD card. This is done automatically when the file is closed. `flush()` inherits from the [Stream](https://www.arduino.cc/reference/en/language/functions/communication/stream/) utility class. - -#### Syntax - -``` -file.flush() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -None. - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `peek()` - -Read a byte from the file without advancing to the next one. That is, successive calls to peek() will return the same value, as will the next call to read(). `peek()` inherits from the [Stream](https://www.arduino.cc/reference/en/language/functions/communication/stream/) utility class. - -#### Syntax - -``` -file.peek() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -The next byte (or character), or -1 if none is available. - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `position()` - -Get the current position within the file (i.e. the location to which the next byte will be read from or written to). - -#### Syntax - -``` -file.position() -file.position(file) -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -The position within the file (unsigned long). - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `print()` - -Print data to the file, which must have been opened for writing. Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3'). - -#### Syntax - -``` -file.print(data) -file.print(data, BASE) -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). -* `data`: the data to print (char, byte, int, long, or string). -* `BASE` (optional): the base in which to print numbers; BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16). - -#### Returns - -The number of bytes written, though reading that number is optional. - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `println()` - -Print data, followed by a carriage return and newline, to the File, which must have been opened for writing. Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3'). - -#### Syntax - -``` -file.println() -file.println(data) -file.println(data, BASE) -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). -* `data`: the data to print (char, byte, int, long, or string). -* `BASE` (optional): the base in which to print numbers; BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16). - -#### Returns - -The number of bytes written, though reading that number is optional. - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `seek()` - -Seek to a new position in the file, which must be between 0 and the size of the file (inclusive). - -#### Syntax - -``` -file.seek(pos) -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). -* `pos`: the position to which to seek (unsigned long). - -#### Returns - -1 on success, 0 on failure. - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `size()` - -Get the size of the file. - -#### Syntax - -``` -file.size() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -The size of the file in bytes (unsigned long). - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `read()` - -Read from the file. read() inherits from the [Stream](https://www.arduino.cc/reference/en/language/functions/communication/stream/) utility class. - -#### Syntax - -``` -file.read() -file.read(buf, len) -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). -* `buf`: an array of characters or bytes. -* `len`: the number of elements in buf. - -#### Returns - -When used as `file.read()`: -The next byte (or character), or -1 if none is available. - -When used as `file.read(buf, len)`: -The amount of bytes read, or -1 if an error occurred. - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `write()` - -Write data to the file. - -#### Syntax - -``` -file.write(data) -file.write(buf, len) -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). -* `data`: the byte, char, or string (char *) to write. -* `buf`: an array of characters or bytes. -* `len`: the number of elements in buf. - -#### Returns - -The number of bytes written, though reading that number is optional. - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `isDirectory()` - -Directories (or folders) are special kinds of files, this function reports if the current file is a directory or not. - -#### Syntax - -``` -file.isDirectory() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -1 if the current file is a directory, 0 if not. - -#### Example - -``` -#include - -File root; - -void setup() { - Serial.begin(9600); - pinMode(10, OUTPUT); - - SD.begin(10); - root = SD.open("/"); - printDirectory(root, 0); - Serial.println("Done!"); -} - -void loop() { - // Nothing happens after setup finishes. -} - -void printDirectory(File dir, int numTabs) { - while (true) { - - File entry = dir.openNextFile(); - if (!entry) { - // No more files - // Serial.println("**nomorefiles**"); - break; - } - - for (uint8_t i = 0; i < numTabs; i++) { - Serial.print('\t'); - } - - Serial.print(entry.name()); - if (entry.isDirectory()) { - Serial.println("/"); - printDirectory(entry, numTabs + 1); - } else { - // Files have sizes, directories do not - Serial.print("\t\t"); - Serial.println(entry.size(), DEC); - } - } -} -``` - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [openNextFile()](#opennextfile) -* [rewindDirectory()](#rewinddirectory) - -### `openNextFile()` - -Reports the next file or folder in a directory. - -#### Syntax - -``` -file.openNextFile() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -The next file or folder in the path (char). - -#### Example - -``` -#include - -File root; -void setup() { - Serial.begin(9600); - pinMode(10, OUTPUT); - SD.begin(10); - root = SD.open("/"); - printDirectory(root, 0); - delay(2000); - - Serial.println(); - Serial.println("Rewinding, and repeating below:"); - Serial.println(); - delay(2000); - - root.rewindDirectory(); - printDirectory(root, 0); - root.close(); -} - -void loop() { - // Nothing happens after setup finishes. -} - -void printDirectory(File dir, int numTabs) { - while (true) { - File entry = dir.openNextFile(); - if (!entry) { - if (numTabs == 0) - Serial.println("** Done **"); - return; - } - - for (uint8_t i = 0; i < numTabs; i++) - Serial.print('\t'); - - Serial.print(entry.name()); - - if (entry.isDirectory()) { - Serial.println("/"); - printDirectory(entry, numTabs + 1); - } else { - Serial.print("\t\t"); - Serial.println(entry.size(), DEC); - } - - entry.close(); - } -} -``` - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [rewindDirectory()](#rewinddirectory) - -### `rewindDirectory()` - -This function will bring you back to the first file in the directory, used in conjunction with [`openNextFile()`](#opennextfile). - -#### Syntax - -``` -file.rewindDirectory() -``` - -#### Parameters - -* `file`: an instance of the File class (returned by [SD.open()](#open)). - -#### Returns - -None. - -#### Example - -``` -#include - -File root; - -void setup() { - Serial.begin(9600); - pinMode(10, OUTPUT); - SD.begin(10); - root = SD.open("/"); - printDirectory(root, 0); - Serial.println(); - - Serial.println("PRINT AGAIN"); - Serial.println("-----------"); - root.rewindDirectory(); // Return to the first file in the directory - printDirectory(root, 0); - - Serial.println("Done!"); -} - -void loop() { - // Nothing happens after setup finishes -} - -void printDirectory(File dir, int numTabs) { - while (true) { - File entry = dir.openNextFile(); - if (!entry) { - // No more files - break; - } - - for (uint8_t i = 0; i < numTabs; i++) { - Serial.print('\t'); - } - - Serial.print(entry.name()); - if (entry.isDirectory()) { - Serial.println("/"); - printDirectory(entry, numTabs + 1); - } else { - // Files have sizes, directories do not - Serial.print("\t\t"); - Serial.println(entry.size(), DEC); - } - } -} -``` - -#### See also - -* [name()](#name) -* [available()](#available) -* [close()](#close) -* [flush()](#flush) -* [peek()](#peek) -* [position()](#position) -* [print()](#print) -* [println()](#println) -* [seek()](#seek) -* [size()](#size) -* [read()](#read) -* [write()](#write) -* [isDirectory()](#isdirectory) -* [openNextFile()](#opennextfile) diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/readme.md b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/readme.md deleted file mode 100644 index c995300..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/docs/readme.md +++ /dev/null @@ -1,23 +0,0 @@ -# SD library - -The SD library allows for reading from and writing to SD cards, e.g. on the Arduino Ethernet Shield. It is built on [sdfatlib](http://code.google.com/p/sdfatlib/) by William Greiman. The library supports FAT16 and FAT32 file systems on standard SD cards and SDHC cards. It uses short 8.3 names for files. The file names passed to the SD library functions can include paths separated by forward-slashes, /, e.g. "directory/filename.txt". Because the working directory is always the root of the SD card, a name refers to the same file whether or not it includes a leading slash (e.g. "/file.txt" is equivalent to "file.txt"). As of version 1.0, the library supports opening multiple files. - -The communication between the microcontroller and the SD card uses [SPI](https://www.arduino.cc/en/Reference/SPI), which takes place on digital pins 11, 12, and 13 (on most Arduino boards) or 50, 51, and 52 (Arduino Mega). Additionally, another pin must be used to select the SD card. This can be the hardware SS pin - pin 10 (on most Arduino boards) or pin 53 (on the Mega) - or another pin specified in the call to SD.begin(). Note that even if you don't use the hardware SS pin, it must be left as an output or the SD library won't work. - -To use this library: - -``` -#include -#include -``` - -[Notes on using the Library and various shields](https://www.arduino.cc/en/Reference/SDCardNotes). - -## Examples - -* [Card Info](https://www.arduino.cc/en/Tutorial/LibraryExamples/CardInfo): Get info about your SD card. -* [Datalogger](https://www.arduino.cc/en/Tutorial/LibraryExamples/Datalogger): Log data from three analog sensors to an SD card. -* [Dump File](https://www.arduino.cc/en/Tutorial/LibraryExamples/DumpFile): Read a file from the SD card. -* [Files](https://www.arduino.cc/en/Tutorial/LibraryExamples/Files): Create and destroy an SD card file. -* [List Files](https://www.arduino.cc/en/Tutorial/LibraryExamples/Listfiles): Print out the files in a directory on a SD card. -* [Read Write](https://www.arduino.cc/en/Tutorial/LibraryExamples/ReadWrite): Read and write data to and from an SD card. diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/CardInfo/CardInfo.ino b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/CardInfo/CardInfo.ino deleted file mode 100644 index ceef52a..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/CardInfo/CardInfo.ino +++ /dev/null @@ -1,118 +0,0 @@ -/* - SD card test - - This example shows how use the utility libraries on which the - SD library is based in order to get info about your SD card. - Very useful for testing a card when you're not sure whether its working or not. - Pin numbers reflect the default SPI pins for Uno and Nano models. - The circuit: - SD card attached to SPI bus as follows: - ** SDO - pin 11 on Arduino Uno/Duemilanove/Diecimila - ** SDI - pin 12 on Arduino Uno/Duemilanove/Diecimila - ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila - ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples - - created 28 Mar 2011 - by Limor Fried - modified 24 July 2020 - by Tom Igoe -*/ -// include the SD library: -#include -#include - -// set up variables using the SD utility library functions: -Sd2Card card; -SdVolume volume; -SdFile root; - -// change this to match your SD shield or module; -// Default SPI on Uno and Nano: pin 10 -// Arduino Ethernet shield: pin 4 -// Adafruit SD shields and modules: pin 10 -// Sparkfun SD shield: pin 8 -// MKR Zero SD: SDCARD_SS_PIN -const int chipSelect = 10; - -void setup() { - // Open serial communications and wait for port to open: - Serial.begin(9600); - while (!Serial) { - ; // wait for serial port to connect. Needed for native USB port only - } - - - Serial.print("\nInitializing SD card..."); - - // we'll use the initialization code from the utility libraries - // since we're just testing if the card is working! - if (!card.init(SPI_HALF_SPEED, chipSelect)) { - Serial.println("initialization failed. Things to check:"); - Serial.println("* is a card inserted?"); - Serial.println("* is your wiring correct?"); - Serial.println("* did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!"); - while (1); - } else { - Serial.println("Wiring is correct and a card is present."); - } - - // print the type of card - Serial.println(); - Serial.print("Card type: "); - switch (card.type()) { - case SD_CARD_TYPE_SD1: - Serial.println("SD1"); - break; - case SD_CARD_TYPE_SD2: - Serial.println("SD2"); - break; - case SD_CARD_TYPE_SDHC: - Serial.println("SDHC"); - break; - default: - Serial.println("Unknown"); - } - - // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 - if (!volume.init(card)) { - Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"); - while (1); - } - - Serial.print("Clusters: "); - Serial.println(volume.clusterCount()); - Serial.print("Blocks x Cluster: "); - Serial.println(volume.blocksPerCluster()); - - Serial.print("Total Blocks: "); - Serial.println(volume.blocksPerCluster() * volume.clusterCount()); - Serial.println(); - - // print the type and size of the first FAT-type volume - uint32_t volumesize; - Serial.print("Volume type is: FAT"); - Serial.println(volume.fatType(), DEC); - - volumesize = volume.blocksPerCluster(); // clusters are collections of blocks - volumesize *= volume.clusterCount(); // we'll have a lot of clusters - volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1 KB) - Serial.print("Volume size (KB): "); - Serial.println(volumesize); - Serial.print("Volume size (MB): "); - volumesize /= 1024; - Serial.println(volumesize); - Serial.print("Volume size (GB): "); - Serial.println((float)volumesize / 1024.0); - - Serial.println("\nFiles found on the card (name, date and size in bytes): "); - root.openRoot(volume); - - // list all files in the card with date and size - root.ls(LS_R | LS_DATE | LS_SIZE); - root.close(); -} - -void loop(void) { -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Datalogger/Datalogger.ino b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Datalogger/Datalogger.ino deleted file mode 100644 index c5a509c..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Datalogger/Datalogger.ino +++ /dev/null @@ -1,79 +0,0 @@ -/* - SD card datalogger - - This example shows how to log data from three analog sensors - to an SD card using the SD library. Pin numbers reflect the default - SPI pins for Uno and Nano models - - The circuit: - analog sensors on analog pins 0, 1, and 2 - SD card attached to SPI bus as follows: - ** SDO - pin 11 - ** SDI - pin 12 - ** CLK - pin 13 - ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples - (for MKR Zero SD: SDCARD_SS_PIN) - - created 24 Nov 2010 - modified 24 July 2020 - by Tom Igoe - - This example code is in the public domain. - -*/ - -#include -#include - -const int chipSelect = 10; - -void setup() { - // Open serial communications and wait for port to open: - Serial.begin(9600); - // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); - - Serial.print("Initializing SD card..."); - - if (!SD.begin(chipSelect)) { - Serial.println("initialization failed. Things to check:"); - Serial.println("1. is a card inserted?"); - Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!"); - while (true); - } - - Serial.println("initialization done."); -} - -void loop() { - // make a string for assembling the data to log: - String dataString = ""; - - // read three sensors and append to the string: - for (int analogPin = 0; analogPin < 3; analogPin++) { - int sensor = analogRead(analogPin); - dataString += String(sensor); - if (analogPin < 2) { - dataString += ","; - } - } - - // open the file. note that only one file can be open at a time, - // so you have to close this one before opening another. - File dataFile = SD.open("datalog.txt", FILE_WRITE); - - // if the file is available, write to it: - if (dataFile) { - dataFile.println(dataString); - dataFile.close(); - // print to the serial port too: - Serial.println(dataString); - } - // if the file isn't open, pop up an error: - else { - Serial.println("error opening datalog.txt"); - } -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/DumpFile/DumpFile.ino b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/DumpFile/DumpFile.ino deleted file mode 100644 index b6e9944..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/DumpFile/DumpFile.ino +++ /dev/null @@ -1,65 +0,0 @@ -/* - SD card file dump - - This example shows how to read a file from the SD card using the - SD library and send it over the serial port. - Pin numbers reflect the default SPI pins for Uno and Nano models. - - The circuit: - SD card attached to SPI bus as follows: - ** SDO - pin 11 - ** SDI - pin 12 - ** CLK - pin 13 - ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples - (for MKR Zero SD: SDCARD_SS_PIN) - - created 22 December 2010 - by Limor Fried - modified 9 Apr 2012 - by Tom Igoe - - This example code is in the public domain. -*/ -#include - -const int chipSelect = 10; - -void setup() { - // Open serial communications and wait for port to open: - Serial.begin(9600); - // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); - - Serial.print("Initializing SD card..."); - - if (!SD.begin(chipSelect)) { - Serial.println("initialization failed. Things to check:"); - Serial.println("1. is a card inserted?"); - Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!"); - while (true); - } - - Serial.println("initialization done."); - - // open the file. note that only one file can be open at a time, - // so you have to close this one before opening another. - File dataFile = SD.open("datalog.txt"); - - // if the file is available, write to it: - if (dataFile) { - while (dataFile.available()) { - Serial.write(dataFile.read()); - } - dataFile.close(); - } - // if the file isn't open, pop up an error: - else { - Serial.println("error opening datalog.txt"); - } -} - -void loop() { -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Files/Files.ino b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Files/Files.ino deleted file mode 100644 index 2df0269..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/Files/Files.ino +++ /dev/null @@ -1,76 +0,0 @@ -/* - SD card basic file example - - This example shows how to create and destroy an SD card file. - The circuit. Pin numbers reflect the default - SPI pins for Uno and Nano models: - SD card attached to SPI bus as follows: - ** SDO - pin 11 - ** SDI - pin 12 - ** CLK - pin 13 - ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples - (for MKR Zero SD: SDCARD_SS_PIN) - - created Nov 2010 - by David A. Mellis - modified 24 July 2020 - by Tom Igoe - - This example code is in the public domain. -*/ -#include - -const int chipSelect = 10; -File myFile; - -void setup() { - // Open serial communications and wait for port to open: - Serial.begin(9600); - // wait for Serial Monitor to connect. Needed for native USB port boards only: -while (!Serial); - - Serial.print("Initializing SD card..."); - - if (!SD.begin(chipSelect)) { - Serial.println("initialization failed. Things to check:"); - Serial.println("1. is a card inserted?"); - Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset button on the board and reopen this serial monitor after fixing your issue!"); - while (1); - } - Serial.println("initialization done."); - - if (SD.exists("example.txt")) { - Serial.println("example.txt exists."); - } else { - Serial.println("example.txt doesn't exist."); - } - - // open a new file and immediately close it: - Serial.println("Creating example.txt..."); - myFile = SD.open("example.txt", FILE_WRITE); - myFile.close(); - - // Check to see if the file exists: - if (SD.exists("example.txt")) { - Serial.println("example.txt exists."); - } else { - Serial.println("example.txt doesn't exist."); - } - - // delete the file: - Serial.println("Removing example.txt..."); - SD.remove("example.txt"); - - if (SD.exists("example.txt")) { - Serial.println("example.txt exists."); - } else { - Serial.println("example.txt doesn't exist."); - } -} - -void loop() { - // nothing happens after setup finishes. -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/NonBlockingWrite/NonBlockingWrite.ino b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/NonBlockingWrite/NonBlockingWrite.ino deleted file mode 100644 index 101bfd0..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/NonBlockingWrite/NonBlockingWrite.ino +++ /dev/null @@ -1,118 +0,0 @@ -/* - Non-blocking Write - - This example demonstrates how to perform non-blocking writes - to a file on a SD card. The file will contain the current millis() - value every 10ms. If the SD card is busy, the data will be dataBuffered - in order to not block the sketch. - - If data is successfully written, the built in LED will flash. After a few - seconds, check the card for a file called datalog.txt - - NOTE: myFile.availableForWrite() will automatically sync the - file contents as needed. You may lose some unsynced data - still if myFile.sync() or myFile.close() is not called. - - Pin numbers reflect the default SPI pins for Uno and Nano models - Updated for clarity and uniformity with other examples - - The circuit: - analog sensors on analog ins 0, 1, and 2 - SD card attached to SPI bus as follows: - ** SDO - pin 11 - ** SDI - pin 12 - ** CLK - pin 13 - ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples - (for MKR Zero SD: SDCARD_SS_PIN) - - modified 24 July 2020 - by Tom Igoe - - This example code is in the public domain. -*/ -#include - -const int chipSelect = 10; - -// file name to use for writing -const char filename[] = "datalog.txt"; - -// File object to represent file -File myFile; -// string to buffer output -String dataBuffer; -// last time data was written to card: -unsigned long lastMillis = 0; - -void setup() { - // Open serial communications and wait for port to open: - Serial.begin(9600); - // reserve 1 kB for String used as a dataBuffer - dataBuffer.reserve(1024); - - // set LED pin to output, used to blink when writing - pinMode(LED_BUILTIN, OUTPUT); - - // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); - - Serial.print("Initializing SD card..."); - - if (!SD.begin(chipSelect)) { - Serial.println("initialization failed. Things to check:"); - Serial.println("1. is a card inserted?"); - Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!"); - while (true); - } - - Serial.println("initialization done."); - - // If you want to start from an empty file, - // uncomment the next line: - // SD.remove(filename); - // try to open the file for writing - - myFile = SD.open(filename, FILE_WRITE); - if (!myFile) { - Serial.print("error opening "); - Serial.println(filename); - while (true); - } - - // add some new lines to start - myFile.println(); - myFile.println("Hello World!"); - Serial.println("Starting to write to file..."); -} - -void loop() { - // check if it's been over 10 ms since the last line added - unsigned long now = millis(); - if ((now - lastMillis) >= 10) { - // add a new line to the dataBuffer - dataBuffer += "Hello "; - dataBuffer += now; - dataBuffer += "\r\n"; - // print the buffer length. This will change depending on when - // data is actually written to the SD card file: - Serial.print("Unsaved data buffer length (in bytes): "); - Serial.println(dataBuffer.length()); - // note the time that the last line was added to the string - lastMillis = now; - } - - // check if the SD card is available to write data without blocking - // and if the dataBuffered data is enough for the full chunk size - unsigned int chunkSize = myFile.availableForWrite(); - if (chunkSize && dataBuffer.length() >= chunkSize) { - // write to file and blink LED - digitalWrite(LED_BUILTIN, HIGH); - myFile.write(dataBuffer.c_str(), chunkSize); - digitalWrite(LED_BUILTIN, LOW); - // remove written data from dataBuffer - dataBuffer.remove(0, chunkSize); - } -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/ReadWrite/ReadWrite.ino b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/ReadWrite/ReadWrite.ino deleted file mode 100644 index b505a27..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/ReadWrite/ReadWrite.ino +++ /dev/null @@ -1,80 +0,0 @@ -/* - SD card read/write - - This example shows how to read and write data to and from an SD card file - The circuit. Pin numbers reflect the default - SPI pins for Uno and Nano models: - SD card attached to SPI bus as follows: - ** SDO - pin 11 - ** SDI - pin 12 - ** CLK - pin 13 - ** CS - pin 4 (For For Uno, Nano: pin 10. For MKR Zero SD: SDCARD_SS_PIN) - - created Nov 2010 - by David A. Mellis - modified 24 July 2020 - by Tom Igoe - - This example code is in the public domain. - -*/ -#include - -const int chipSelect = 10; -File myFile; - -void setup() { - // Open serial communications and wait for port to open: - Serial.begin(9600); - // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); - - Serial.print("Initializing SD card..."); - - if (!SD.begin(chipSelect)) { - Serial.println("initialization failed. Things to check:"); - Serial.println("1. is a card inserted?"); - Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!"); - while (true); - } - - Serial.println("initialization done."); - - // open the file. note that only one file can be open at a time, - // so you have to close this one before opening another. - myFile = SD.open("test.txt", FILE_WRITE); - - // if the file opened okay, write to it: - if (myFile) { - Serial.print("Writing to test.txt..."); - myFile.println("testing 1, 2, 3."); - // close the file: - myFile.close(); - Serial.println("done."); - } else { - // if the file didn't open, print an error: - Serial.println("error opening test.txt"); - } - - // re-open the file for reading: - myFile = SD.open("test.txt"); - if (myFile) { - Serial.println("test.txt:"); - - // read from the file until there's nothing else in it: - while (myFile.available()) { - Serial.write(myFile.read()); - } - // close the file: - myFile.close(); - } else { - // if the file didn't open, print an error: - Serial.println("error opening test.txt"); - } -} - -void loop() { - // nothing happens after setup -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/listfiles/listfiles.ino b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/listfiles/listfiles.ino deleted file mode 100644 index ded9b13..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/examples/listfiles/listfiles.ino +++ /dev/null @@ -1,86 +0,0 @@ -/* - Listfiles - - This example shows how to print out the files in a - directory on a SD card. Pin numbers reflect the default - SPI pins for Uno and Nano models - - The circuit: - SD card attached to SPI bus as follows: - ** SDO - pin 11 - ** SDI - pin 12 - ** CLK - pin 13 - ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples - (for MKR Zero SD: SDCARD_SS_PIN) - - created Nov 2010 - by David A. Mellis - modified 9 Apr 2012 - by Tom Igoe - modified 2 Feb 2014 - by Scott Fitzgerald - modified 24 July 2020 - by Tom Igoe - - This example code is in the public domain. - -*/ -#include - -const int chipSelect = 10; -File root; - -void setup() { - // Open serial communications and wait for port to open: - Serial.begin(9600); - // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); - - Serial.print("Initializing SD card..."); - - if (!SD.begin(chipSelect)) { - Serial.println("initialization failed. Things to check:"); - Serial.println("1. is a card inserted?"); - Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!"); - while (true); - } - - Serial.println("initialization done."); - - root = SD.open("/"); - - printDirectory(root, 0); - - Serial.println("done!"); -} - -void loop() { - // nothing happens after setup finishes. -} - -void printDirectory(File dir, int numTabs) { - while (true) { - - File entry = dir.openNextFile(); - if (! entry) { - // no more files - break; - } - for (uint8_t i = 0; i < numTabs; i++) { - Serial.print('\t'); - } - Serial.print(entry.name()); - if (entry.isDirectory()) { - Serial.println("/"); - printDirectory(entry, numTabs + 1); - } else { - // files have sizes, directories do not - Serial.print("\t\t"); - Serial.println(entry.size(), DEC); - } - entry.close(); - } -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/keywords.txt b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/keywords.txt deleted file mode 100644 index 91e74b8..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/keywords.txt +++ /dev/null @@ -1,31 +0,0 @@ -####################################### -# Syntax Coloring Map SD -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -SD KEYWORD1 SD -File KEYWORD1 SD -SDFile KEYWORD1 SD - -####################################### -# Methods and Functions (KEYWORD2) -####################################### -begin KEYWORD2 -exists KEYWORD2 -mkdir KEYWORD2 -remove KEYWORD2 -rmdir KEYWORD2 -open KEYWORD2 -close KEYWORD2 -seek KEYWORD2 -position KEYWORD2 -size KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### -FILE_READ LITERAL1 -FILE_WRITE LITERAL1 diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/library.properties b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/library.properties deleted file mode 100644 index 9e6d791..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=SD -version=1.3.0 -author=Arduino, SparkFun -maintainer=Arduino -sentence=Enables reading and writing on SD cards. -paragraph=Once an SD memory card is connected to the SPI interface of the Arduino board you can create files and read/write on them. You can also move through directories on the SD card. -category=Data Storage -url=http://www.arduino.cc/en/Reference/SD -architectures=* diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/File.cpp b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/File.cpp deleted file mode 100644 index 3e27fb4..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/File.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - - SD - a slightly more friendly wrapper for sdfatlib - - This library aims to expose a subset of SD card functionality - in the form of a higher level "wrapper" object. - - License: GNU General Public License V3 - (Because sdfatlib is licensed with this.) - - (C) Copyright 2010 SparkFun Electronics - -*/ - -#include - -/* for debugging file open/close leaks - uint8_t nfilecount=0; -*/ - -File::File(SdFile f, const char *n) { - // oh man you are kidding me, new() doesn't exist? Ok we do it by hand! - _file = (SdFile *)malloc(sizeof(SdFile)); - if (_file) { - memcpy(_file, &f, sizeof(SdFile)); - - strncpy(_name, n, 12); - _name[12] = 0; - - /* for debugging file open/close leaks - nfilecount++; - Serial.print("Created \""); - Serial.print(n); - Serial.print("\": "); - Serial.println(nfilecount, DEC); - */ - } -} - -File::File(void) { - _file = 0; - _name[0] = 0; - //Serial.print("Created empty file object"); -} - -// returns a pointer to the file name -char *File::name(void) { - return _name; -} - -// a directory is a special type of file -bool File::isDirectory(void) { - return (_file && _file->isDir()); -} - - -size_t File::write(uint8_t val) { - return write(&val, 1); -} - -size_t File::write(const uint8_t *buf, size_t size) { - size_t t; - if (!_file) { - setWriteError(); - return 0; - } - _file->clearWriteError(); - t = _file->write(buf, size); - if (_file->getWriteError()) { - setWriteError(); - return 0; - } - return t; -} - -int File::availableForWrite() { - if (_file) { - return _file->availableForWrite(); - } - return 0; -} - -int File::peek() { - if (! _file) { - return 0; - } - - int c = _file->read(); - if (c != -1) { - _file->seekCur(-1); - } - return c; -} - -int File::read() { - if (_file) { - return _file->read(); - } - return -1; -} - -// buffered read for more efficient, high speed reading -int File::read(void *buf, uint16_t nbyte) { - if (_file) { - return _file->read(buf, nbyte); - } - return 0; -} - -int File::available() { - if (! _file) { - return 0; - } - - uint32_t n = size() - position(); - - return n > 0X7FFF ? 0X7FFF : n; -} - -void File::flush() { - if (_file) { - _file->sync(); - } -} - -bool File::seek(uint32_t pos) { - if (! _file) { - return false; - } - - return _file->seekSet(pos); -} - -uint32_t File::position() { - if (! _file) { - return -1; - } - return _file->curPosition(); -} - -uint32_t File::size() { - if (! _file) { - return 0; - } - return _file->fileSize(); -} - -void File::close() { - if (_file) { - _file->close(); - free(_file); - _file = 0; - - /* for debugging file open/close leaks - nfilecount--; - Serial.print("Deleted "); - Serial.println(nfilecount, DEC); - */ - } -} - -File::operator bool() { - if (_file) { - return _file->isOpen(); - } - return false; -} - diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/README.txt b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/README.txt deleted file mode 100644 index 495ea4c..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/README.txt +++ /dev/null @@ -1,13 +0,0 @@ - -** SD - a slightly more friendly wrapper for sdfatlib ** - -This library aims to expose a subset of SD card functionality in the -form of a higher level "wrapper" object. - -License: GNU General Public License V3 - (Because sdfatlib is licensed with this.) - -(C) Copyright 2010 SparkFun Electronics - -Now better than ever with optimization, multiple file support, directory handling, etc - ladyada! - diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.cpp b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.cpp deleted file mode 100644 index 423db45..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/* - - SD - a slightly more friendly wrapper for sdfatlib - - This library aims to expose a subset of SD card functionality - in the form of a higher level "wrapper" object. - - License: GNU General Public License V3 - (Because sdfatlib is licensed with this.) - - (C) Copyright 2010 SparkFun Electronics - - - This library provides four key benefits: - - Including `SD.h` automatically creates a global - `SD` object which can be interacted with in a similar - manner to other standard global objects like `Serial` and `Ethernet`. - - Boilerplate initialisation code is contained in one method named - `begin` and no further objects need to be created in order to access - the SD card. - - Calls to `open` can supply a full path name including parent - directories which simplifies interacting with files in subdirectories. - - Utility methods are provided to determine whether a file exists - and to create a directory hierarchy. - - - Note however that not all functionality provided by the underlying - sdfatlib library is exposed. - -*/ - -/* - - Implementation Notes - - In order to handle multi-directory path traversal, functionality that - requires this ability is implemented as callback functions. - - Individual methods call the `walkPath` function which performs the actual - directory traversal (swapping between two different directory/file handles - along the way) and at each level calls the supplied callback function. - - Some types of functionality will take an action at each level (e.g. exists - or make directory) which others will only take an action at the bottom - level (e.g. open). - -*/ - -#include "SD.h" - -namespace SDLib { - -// Used by `getNextPathComponent` -#define MAX_COMPONENT_LEN 12 -#define PATH_COMPONENT_BUFFER_LEN (MAX_COMPONENT_LEN + 1) -// BASENAME:char(8) + '.':char(1) + EXT:char(3) = 12 (a.k.a short 8.3 name) -// And an extra space for '\0' for path buffer - - bool getNextPathComponent(const char *path, unsigned int *p_offset, - char *buffer) { - /* - - Parse individual path components from a path. - - e.g. after repeated calls '/foo/bar/baz' will be split - into 'foo', 'bar', 'baz'. - - This is similar to `strtok()` but copies the component into the - supplied buffer rather than modifying the original string. - - - `buffer` needs to be PATH_COMPONENT_BUFFER_LEN in size. - - `p_offset` needs to point to an integer of the offset at - which the previous path component finished. - - Returns `true` if more components remain. - - Returns `false` if this is the last component. - (This means path ended with 'foo' or 'foo/'.) - - */ - - // TODO: Have buffer local to this function, so we know it's the - // correct length? - - int bufferOffset = 0; - - int offset = *p_offset; - - // Skip root or other separator - if (path[offset] == '/') { - offset++; - } - - // Copy the next next path segment - while (bufferOffset < MAX_COMPONENT_LEN - && (path[offset] != '/') - && (path[offset] != '\0')) { - buffer[bufferOffset++] = path[offset++]; - } - - buffer[bufferOffset] = '\0'; - - // Skip trailing separator so we can determine if this - // is the last component in the path or not. - if (path[offset] == '/') { - offset++; - } - - *p_offset = offset; - - return (path[offset] != '\0'); - } - - - - bool walkPath(const char *filepath, SdFile& parentDir, - bool(*callback)(SdFile& parentDir, - const char *filePathComponent, - bool isLastComponent, - void *object), - void *object = NULL) { - /* - - When given a file path (and parent directory--normally root), - this function traverses the directories in the path and at each - level calls the supplied callback function while also providing - the supplied object for context if required. - - e.g. given the path '/foo/bar/baz' - the callback would be called at the equivalent of - '/foo', '/foo/bar' and '/foo/bar/baz'. - - The implementation swaps between two different directory/file - handles as it traverses the directories and does not use recursion - in an attempt to use memory efficiently. - - If a callback wishes to stop the directory traversal it should - return false--in this case the function will stop the traversal, - tidy up and return false. - - If a directory path doesn't exist at some point this function will - also return false and not subsequently call the callback. - - If a directory path specified is complete, valid and the callback - did not indicate the traversal should be interrupted then this - function will return true. - - */ - - - SdFile subfile1; - SdFile subfile2; - - char buffer[PATH_COMPONENT_BUFFER_LEN]; - - unsigned int offset = 0; - - SdFile *p_parent; - SdFile *p_child; - - SdFile *p_tmp_sdfile; - - p_child = &subfile1; - - p_parent = &parentDir; - - while (true) { - - bool moreComponents = getNextPathComponent(filepath, &offset, buffer); - - bool shouldContinue = callback((*p_parent), buffer, !moreComponents, object); - - if (!shouldContinue) { - // TODO: Don't repeat this code? - // If it's one we've created then we - // don't need the parent handle anymore. - if (p_parent != &parentDir) { - (*p_parent).close(); - } - return false; - } - - if (!moreComponents) { - break; - } - - bool exists = (*p_child).open(*p_parent, buffer, O_RDONLY); - - // If it's one we've created then we - // don't need the parent handle anymore. - if (p_parent != &parentDir) { - (*p_parent).close(); - } - - // Handle case when it doesn't exist and we can't continue... - if (exists) { - // We alternate between two file handles as we go down - // the path. - if (p_parent == &parentDir) { - p_parent = &subfile2; - } - - p_tmp_sdfile = p_parent; - p_parent = p_child; - p_child = p_tmp_sdfile; - } else { - return false; - } - } - - if (p_parent != &parentDir) { - (*p_parent).close(); // TODO: Return/ handle different? - } - - return true; - } - - - - /* - - The callbacks used to implement various functionality follow. - - Each callback is supplied with a parent directory handle, - character string with the name of the current file path component, - a flag indicating if this component is the last in the path and - a pointer to an arbitrary object used for context. - - */ - - bool callback_pathExists(SdFile& parentDir, const char *filePathComponent, - bool /* isLastComponent */, void * /* object */) { - /* - - Callback used to determine if a file/directory exists in parent - directory. - - Returns true if file path exists. - - */ - SdFile child; - - bool exists = child.open(parentDir, filePathComponent, O_RDONLY); - - if (exists) { - child.close(); - } - - return exists; - } - - - - bool callback_makeDirPath(SdFile& parentDir, const char *filePathComponent, - bool isLastComponent, void *object) { - /* - - Callback used to create a directory in the parent directory if - it does not already exist. - - Returns true if a directory was created or it already existed. - - */ - bool result = false; - SdFile child; - - result = callback_pathExists(parentDir, filePathComponent, isLastComponent, object); - if (!result) { - result = child.makeDir(parentDir, filePathComponent); - } - - return result; - } - - - /* - - bool callback_openPath(SdFile& parentDir, char *filePathComponent, - bool isLastComponent, void *object) { - - Callback used to open a file specified by a filepath that may - specify one or more directories above it. - - Expects the context object to be an instance of `SDClass` and - will use the `file` property of the instance to open the requested - file/directory with the associated file open mode property. - - Always returns true if the directory traversal hasn't reached the - bottom of the directory hierarchy. - - Returns false once the file has been opened--to prevent the traversal - from descending further. (This may be unnecessary.) - - if (isLastComponent) { - SDClass *p_SD = static_cast(object); - p_SD->file.open(parentDir, filePathComponent, p_SD->fileOpenMode); - if (p_SD->fileOpenMode == FILE_WRITE) { - p_SD->file.seekSet(p_SD->file.fileSize()); - } - // TODO: Return file open result? - return false; - } - return true; - } - */ - - - - bool callback_remove(SdFile& parentDir, const char *filePathComponent, - bool isLastComponent, void * /* object */) { - if (isLastComponent) { - return SdFile::remove(parentDir, filePathComponent); - } - return true; - } - - bool callback_rmdir(SdFile& parentDir, const char *filePathComponent, - bool isLastComponent, void * /* object */) { - if (isLastComponent) { - SdFile f; - if (!f.open(parentDir, filePathComponent, O_READ)) { - return false; - } - return f.rmDir(); - } - return true; - } - - - - /* Implementation of class used to create `SDCard` object. */ - - - - bool SDClass::begin(uint8_t csPin) { - if (root.isOpen()) { - root.close(); - } - - /* - - Performs the initialisation required by the sdfatlib library. - - Return true if initialization succeeds, false otherwise. - - */ - return card.init(SPI_HALF_SPEED, csPin) && - volume.init(card) && - root.openRoot(volume); - } - - bool SDClass::begin(uint32_t clock, uint8_t csPin) { - if (root.isOpen()) { - root.close(); - } - - return card.init(SPI_HALF_SPEED, csPin) && - card.setSpiClock(clock) && - volume.init(card) && - root.openRoot(volume); - } - - //call this when a card is removed. It will allow you to insert and initialise a new card. - void SDClass::end() { - root.close(); - } - - // this little helper is used to traverse paths - SdFile SDClass::getParentDir(const char *filepath, int *index) { - // get parent directory - SdFile d1; - SdFile d2; - - d1.openRoot(volume); // start with the mostparent, root! - - // we'll use the pointers to swap between the two objects - SdFile *parent = &d1; - SdFile *subdir = &d2; - - const char *origpath = filepath; - - while (strchr(filepath, '/')) { - - // get rid of leading /'s - if (filepath[0] == '/') { - filepath++; - continue; - } - - if (! strchr(filepath, '/')) { - // it was in the root directory, so leave now - break; - } - - // extract just the name of the next subdirectory - uint8_t idx = strchr(filepath, '/') - filepath; - if (idx > 12) { - idx = 12; // don't let them specify long names - } - char subdirname[13]; - strncpy(subdirname, filepath, idx); - subdirname[idx] = 0; - - // close the subdir (we reuse them) if open - subdir->close(); - if (! subdir->open(parent, subdirname, O_READ)) { - // failed to open one of the subdirectories - return SdFile(); - } - // move forward to the next subdirectory - filepath += idx; - - // we reuse the objects, close it. - parent->close(); - - // swap the pointers - SdFile *t = parent; - parent = subdir; - subdir = t; - } - - *index = (int)(filepath - origpath); - // parent is now the parent directory of the file! - return *parent; - } - - - File SDClass::open(const char *filepath, uint8_t mode) { - /* - - Open the supplied file path for reading or writing. - - The file content can be accessed via the `file` property of - the `SDClass` object--this property is currently - a standard `SdFile` object from `sdfatlib`. - - Defaults to read only. - - If `write` is true, default action (when `append` is true) is to - append data to the end of the file. - - If `append` is false then the file will be truncated first. - - If the file does not exist and it is opened for writing the file - will be created. - - An attempt to open a file for reading that does not exist is an - error. - - */ - - int pathidx = 0; - - // do the interactive search - SdFile parentdir = getParentDir(filepath, &pathidx); - // no more subdirs! - - filepath += pathidx; - - if (! filepath[0]) { - // it was the directory itself! - return File(parentdir, "/"); - } - - // Open the file itself - SdFile file; - - // failed to open a subdir! - if (!parentdir.isOpen()) { - return File(); - } - - if (! file.open(parentdir, filepath, mode)) { - return File(); - } - // close the parent - parentdir.close(); - - if ((mode & (O_APPEND | O_WRITE)) == (O_APPEND | O_WRITE)) { - file.seekSet(file.fileSize()); - } - return File(file, filepath); - } - - - /* - File SDClass::open(char *filepath, uint8_t mode) { - // - - Open the supplied file path for reading or writing. - - The file content can be accessed via the `file` property of - the `SDClass` object--this property is currently - a standard `SdFile` object from `sdfatlib`. - - Defaults to read only. - - If `write` is true, default action (when `append` is true) is to - append data to the end of the file. - - If `append` is false then the file will be truncated first. - - If the file does not exist and it is opened for writing the file - will be created. - - An attempt to open a file for reading that does not exist is an - error. - - // - - // TODO: Allow for read&write? (Possibly not, as it requires seek.) - - fileOpenMode = mode; - walkPath(filepath, root, callback_openPath, this); - - return File(); - - } - */ - - - //bool SDClass::close() { - // /* - // - // Closes the file opened by the `open` method. - // - // */ - // file.close(); - //} - - - bool SDClass::exists(const char *filepath) { - /* - - Returns true if the supplied file path exists. - - */ - return walkPath(filepath, root, callback_pathExists); - } - - - //bool SDClass::exists(char *filepath, SdFile& parentDir) { - // /* - // - // Returns true if the supplied file path rooted at `parentDir` - // exists. - // - // */ - // return walkPath(filepath, parentDir, callback_pathExists); - //} - - - bool SDClass::mkdir(const char *filepath) { - /* - - Makes a single directory or a hierarchy of directories. - - A rough equivalent to `mkdir -p`. - - */ - return walkPath(filepath, root, callback_makeDirPath); - } - - bool SDClass::rmdir(const char *filepath) { - /* - - Remove a single directory or a hierarchy of directories. - - A rough equivalent to `rm -rf`. - - */ - return walkPath(filepath, root, callback_rmdir); - } - - bool SDClass::remove(const char *filepath) { - return walkPath(filepath, root, callback_remove); - } - - - // allows you to recurse into a directory - File File::openNextFile(uint8_t mode) { - dir_t p; - - //Serial.print("\t\treading dir..."); - while (_file->readDir(&p) > 0) { - - // done if past last used entry - if (p.name[0] == DIR_NAME_FREE) { - //Serial.println("end"); - return File(); - } - - // skip deleted entry and entries for . and .. - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') { - //Serial.println("dots"); - continue; - } - - // only list subdirectories and files - if (!DIR_IS_FILE_OR_SUBDIR(&p)) { - //Serial.println("notafile"); - continue; - } - - // print file name with possible blank fill - SdFile f; - char name[13]; - _file->dirName(p, name); - //Serial.print("try to open file "); - //Serial.println(name); - - if (f.open(_file, name, mode)) { - //Serial.println("OK!"); - return File(f, name); - } else { - //Serial.println("ugh"); - return File(); - } - } - - //Serial.println("nothing"); - return File(); - } - - void File::rewindDirectory(void) { - if (isDirectory()) { - _file->rewind(); - } - } - - SDClass SD; - -}; diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.h deleted file mode 100644 index c81a7d3..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/SD.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - - SD - a slightly more friendly wrapper for sdfatlib - - This library aims to expose a subset of SD card functionality - in the form of a higher level "wrapper" object. - - License: GNU General Public License V3 - (Because sdfatlib is licensed with this.) - - (C) Copyright 2010 SparkFun Electronics - -*/ - -#ifndef __SD_H__ -#define __SD_H__ - -#include - -#include "utility/SdFat.h" -#include "utility/SdFatUtil.h" - -#define FILE_READ O_READ -#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND) - -namespace SDLib { - - class File : public Stream { - private: - char _name[13]; // our name - SdFile *_file; // underlying file pointer - - public: - File(SdFile f, const char *name); // wraps an underlying SdFile - File(void); // 'empty' constructor - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual int availableForWrite(); - virtual int read(); - virtual int peek(); - virtual int available(); - virtual void flush(); - int read(void *buf, uint16_t nbyte); - bool seek(uint32_t pos); - uint32_t position(); - uint32_t size(); - void close(); - operator bool(); - char * name(); - - bool isDirectory(void); - File openNextFile(uint8_t mode = O_RDONLY); - void rewindDirectory(void); - - using Print::write; - }; - - class SDClass { - - private: - // These are required for initialisation and use of sdfatlib - Sd2Card card; - SdVolume volume; - SdFile root; - - // my quick&dirty iterator, should be replaced - SdFile getParentDir(const char *filepath, int *indx); - public: - // This needs to be called to set up the connection to the SD card - // before other methods are used. - bool begin(uint8_t csPin = SD_CHIP_SELECT_PIN); - bool begin(uint32_t clock, uint8_t csPin); - - //call this when a card is removed. It will allow you to insert and initialise a new card. - void end(); - - // Open the specified file/directory with the supplied mode (e.g. read or - // write, etc). Returns a File object for interacting with the file. - // Note that currently only one file can be open at a time. - File open(const char *filename, uint8_t mode = FILE_READ); - File open(const String &filename, uint8_t mode = FILE_READ) { - return open(filename.c_str(), mode); - } - - // Methods to determine if the requested file path exists. - bool exists(const char *filepath); - bool exists(const String &filepath) { - return exists(filepath.c_str()); - } - - // Create the requested directory heirarchy--if intermediate directories - // do not exist they will be created. - bool mkdir(const char *filepath); - bool mkdir(const String &filepath) { - return mkdir(filepath.c_str()); - } - - // Delete the file. - bool remove(const char *filepath); - bool remove(const String &filepath) { - return remove(filepath.c_str()); - } - - bool rmdir(const char *filepath); - bool rmdir(const String &filepath) { - return rmdir(filepath.c_str()); - } - - private: - - // This is used to determine the mode used to open a file - // it's here because it's the easiest place to pass the - // information through the directory walking function. But - // it's probably not the best place for it. - // It shouldn't be set directly--it is set via the parameters to `open`. - int fileOpenMode; - - friend class File; - friend bool callback_openPath(SdFile&, const char *, bool, void *); - }; - - extern SDClass SD; - -}; - -// We enclose File and SD classes in namespace SDLib to avoid conflicts -// with others legacy libraries that redefines File class. - -// This ensure compatibility with sketches that uses only SD library -using namespace SDLib; - -// This allows sketches to use SDLib::File with other libraries (in the -// sketch you must use SDFile instead of File to disambiguate) -typedef SDLib::File SDFile; -typedef SDLib::SDClass SDFileSystemClass; -#define SDFileSystem SDLib::SD - -#endif diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/FatStructs.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/FatStructs.h deleted file mode 100644 index 8cb0980..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/FatStructs.h +++ /dev/null @@ -1,418 +0,0 @@ -/* Arduino SdFat Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino SdFat Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino SdFat Library. If not, see - . -*/ -#ifndef FatStructs_h -#define FatStructs_h -/** - \file - FAT file structures -*/ -/* - mostly from Microsoft document fatgen103.doc - http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx -*/ -//------------------------------------------------------------------------------ -/** Value for byte 510 of boot block or MBR */ -uint8_t const BOOTSIG0 = 0X55; -/** Value for byte 511 of boot block or MBR */ -uint8_t const BOOTSIG1 = 0XAA; -//------------------------------------------------------------------------------ -/** - \struct partitionTable - \brief MBR partition table entry - - A partition table entry for a MBR formatted storage device. - The MBR partition table has four entries. -*/ -struct partitionTable { - /** - Boot Indicator . Indicates whether the volume is the active - partition. Legal values include: 0X00. Do not use for booting. - 0X80 Active partition. - */ - uint8_t boot; - /** - Head part of Cylinder-head-sector address of the first block in - the partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t beginHead; - /** - Sector part of Cylinder-head-sector address of the first block in - the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned beginSector : 6; - /** High bits cylinder for first block in partition. */ - unsigned beginCylinderHigh : 2; - /** - Combine beginCylinderLow with beginCylinderHigh. Legal values - are 0-1023. Only used in old PC BIOS. - */ - uint8_t beginCylinderLow; - /** - Partition type. See defines that begin with PART_TYPE_ for - some Microsoft partition types. - */ - uint8_t type; - /** - head part of cylinder-head-sector address of the last sector in the - partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t endHead; - /** - Sector part of cylinder-head-sector address of the last sector in - the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned endSector : 6; - /** High bits of end cylinder */ - unsigned endCylinderHigh : 2; - /** - Combine endCylinderLow with endCylinderHigh. Legal values - are 0-1023. Only used in old PC BIOS. - */ - uint8_t endCylinderLow; - /** Logical block address of the first block in the partition. */ - uint32_t firstSector; - /** Length of the partition, in blocks. */ - uint32_t totalSectors; -} __attribute__((packed)); -/** Type name for partitionTable */ -typedef struct partitionTable part_t; -//------------------------------------------------------------------------------ -/** - \struct masterBootRecord - - \brief Master Boot Record - - The first block of a storage device that is formatted with a MBR. -*/ -struct masterBootRecord { - /** Code Area for master boot program. */ - uint8_t codeArea[440]; - /** Optional WindowsNT disk signature. May contain more boot code. */ - uint32_t diskSignature; - /** Usually zero but may be more boot code. */ - uint16_t usuallyZero; - /** Partition tables. */ - part_t part[4]; - /** First MBR signature byte. Must be 0X55 */ - uint8_t mbrSig0; - /** Second MBR signature byte. Must be 0XAA */ - uint8_t mbrSig1; -} __attribute__((packed)); -/** Type name for masterBootRecord */ -typedef struct masterBootRecord mbr_t; -//------------------------------------------------------------------------------ -/** - \struct biosParmBlock - - \brief BIOS parameter block - - The BIOS parameter block describes the physical layout of a FAT volume. -*/ -struct biosParmBlock { - /** - Count of bytes per sector. This value may take on only the - following values: 512, 1024, 2048 or 4096 - */ - uint16_t bytesPerSector; - /** - Number of sectors per allocation unit. This value must be a - power of 2 that is greater than 0. The legal values are - 1, 2, 4, 8, 16, 32, 64, and 128. - */ - uint8_t sectorsPerCluster; - /** - Number of sectors before the first FAT. - This value must not be zero. - */ - uint16_t reservedSectorCount; - /** The count of FAT data structures on the volume. This field should - always contain the value 2 for any FAT volume of any type. - */ - uint8_t fatCount; - /** - For FAT12 and FAT16 volumes, this field contains the count of - 32-byte directory entries in the root directory. For FAT32 volumes, - this field must be set to 0. For FAT12 and FAT16 volumes, this - value should always specify a count that when multiplied by 32 - results in a multiple of bytesPerSector. FAT16 volumes should - use the value 512. - */ - uint16_t rootDirEntryCount; - /** - This field is the old 16-bit total count of sectors on the volume. - This count includes the count of all sectors in all four regions - of the volume. This field can be 0; if it is 0, then totalSectors32 - must be non-zero. For FAT32 volumes, this field must be 0. For - FAT12 and FAT16 volumes, this field contains the sector count, and - totalSectors32 is 0 if the total sector count fits - (is less than 0x10000). - */ - uint16_t totalSectors16; - /** - This dates back to the old MS-DOS 1.x media determination and is - no longer usually used for anything. 0xF8 is the standard value - for fixed (non-removable) media. For removable media, 0xF0 is - frequently used. Legal values are 0xF0 or 0xF8-0xFF. - */ - uint8_t mediaType; - /** - Count of sectors occupied by one FAT on FAT12/FAT16 volumes. - On FAT32 volumes this field must be 0, and sectorsPerFat32 - contains the FAT size count. - */ - uint16_t sectorsPerFat16; - /** Sectors per track for interrupt 0x13. Not used otherwise. */ - uint16_t sectorsPerTrtack; - /** Number of heads for interrupt 0x13. Not used otherwise. */ - uint16_t headCount; - /** - Count of hidden sectors preceding the partition that contains this - FAT volume. This field is generally only relevant for media - visible on interrupt 0x13. - */ - uint32_t hidddenSectors; - /** - This field is the new 32-bit total count of sectors on the volume. - This count includes the count of all sectors in all four regions - of the volume. This field can be 0; if it is 0, then - totalSectors16 must be non-zero. - */ - uint32_t totalSectors32; - /** - Count of sectors occupied by one FAT on FAT32 volumes. - */ - uint32_t sectorsPerFat32; - /** - This field is only defined for FAT32 media and does not exist on - FAT12 and FAT16 media. - Bits 0-3 -- Zero-based number of active FAT. - Only valid if mirroring is disabled. - Bits 4-6 -- Reserved. - Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. - -- 1 means only one FAT is active; it is the one referenced in bits 0-3. - Bits 8-15 -- Reserved. - */ - uint16_t fat32Flags; - /** - FAT32 version. High byte is major revision number. - Low byte is minor revision number. Only 0.0 define. - */ - uint16_t fat32Version; - /** - Cluster number of the first cluster of the root directory for FAT32. - This usually 2 but not required to be 2. - */ - uint32_t fat32RootCluster; - /** - Sector number of FSINFO structure in the reserved area of the - FAT32 volume. Usually 1. - */ - uint16_t fat32FSInfo; - /** - If non-zero, indicates the sector number in the reserved area - of the volume of a copy of the boot record. Usually 6. - No value other than 6 is recommended. - */ - uint16_t fat32BackBootBlock; - /** - Reserved for future expansion. Code that formats FAT32 volumes - should always set all of the bytes of this field to 0. - */ - uint8_t fat32Reserved[12]; -} __attribute__((packed)); -/** Type name for biosParmBlock */ -typedef struct biosParmBlock bpb_t; -//------------------------------------------------------------------------------ -/** - \struct fat32BootSector - - \brief Boot sector for a FAT16 or FAT32 volume. - -*/ -struct fat32BootSector { - /** X86 jmp to boot program */ - uint8_t jmpToBootCode[3]; - /** informational only - don't depend on it */ - char oemName[8]; - /** BIOS Parameter Block */ - bpb_t bpb; - /** for int0x13 use value 0X80 for hard drive */ - uint8_t driveNumber; - /** used by Windows NT - should be zero for FAT */ - uint8_t reserved1; - /** 0X29 if next three fields are valid */ - uint8_t bootSignature; - /** usually generated by combining date and time */ - uint32_t volumeSerialNumber; - /** should match volume label in root dir */ - char volumeLabel[11]; - /** informational only - don't depend on it */ - char fileSystemType[8]; - /** X86 boot code */ - uint8_t bootCode[420]; - /** must be 0X55 */ - uint8_t bootSectorSig0; - /** must be 0XAA */ - uint8_t bootSectorSig1; -} __attribute__((packed)); -//------------------------------------------------------------------------------ -// End Of Chain values for FAT entries -/** FAT16 end of chain value used by Microsoft. */ -uint16_t const FAT16EOC = 0XFFFF; -/** Minimum value for FAT16 EOC. Use to test for EOC. */ -uint16_t const FAT16EOC_MIN = 0XFFF8; -/** FAT32 end of chain value used by Microsoft. */ -uint32_t const FAT32EOC = 0X0FFFFFFF; -/** Minimum value for FAT32 EOC. Use to test for EOC. */ -uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; -/** Mask a for FAT32 entry. Entries are 28 bits. */ -uint32_t const FAT32MASK = 0X0FFFFFFF; - -/** Type name for fat32BootSector */ -typedef struct fat32BootSector fbs_t; -//------------------------------------------------------------------------------ -/** - \struct directoryEntry - \brief FAT short directory entry - - Short means short 8.3 name, not the entry size. - - Date Format. A FAT directory entry date stamp is a 16-bit field that is - basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the - format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the - 16-bit word): - - Bits 9-15: Count of years from 1980, valid value range 0-127 - inclusive (1980-2107). - - Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. - - Bits 0-4: Day of month, valid value range 1-31 inclusive. - - Time Format. A FAT directory entry time stamp is a 16-bit field that has - a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the - 16-bit word, bit 15 is the MSB of the 16-bit word). - - Bits 11-15: Hours, valid value range 0-23 inclusive. - - Bits 5-10: Minutes, valid value range 0-59 inclusive. - - Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). - - The valid time range is from Midnight 00:00:00 to 23:59:58. -*/ -struct directoryEntry { - /** - Short 8.3 name. - The first eight bytes contain the file name with blank fill. - The last three bytes contain the file extension with blank fill. - */ - uint8_t name[11]; - /** Entry attributes. - - The upper two bits of the attribute byte are reserved and should - always be set to 0 when a file is created and never modified or - looked at after that. See defines that begin with DIR_ATT_. - */ - uint8_t attributes; - /** - Reserved for use by Windows NT. Set value to 0 when a file is - created and never modify or look at it after that. - */ - uint8_t reservedNT; - /** - The granularity of the seconds part of creationTime is 2 seconds - so this field is a count of tenths of a second and its valid - value range is 0-199 inclusive. (WHG note - seems to be hundredths) - */ - uint8_t creationTimeTenths; - /** Time file was created. */ - uint16_t creationTime; - /** Date file was created. */ - uint16_t creationDate; - /** - Last access date. Note that there is no last access time, only - a date. This is the date of last read or write. In the case of - a write, this should be set to the same date as lastWriteDate. - */ - uint16_t lastAccessDate; - /** - High word of this entry's first cluster number (always 0 for a - FAT12 or FAT16 volume). - */ - uint16_t firstClusterHigh; - /** Time of last write. File creation is considered a write. */ - uint16_t lastWriteTime; - /** Date of last write. File creation is considered a write. */ - uint16_t lastWriteDate; - /** Low word of this entry's first cluster number. */ - uint16_t firstClusterLow; - /** 32-bit unsigned holding this file's size in bytes. */ - uint32_t fileSize; -} __attribute__((packed)); -//------------------------------------------------------------------------------ -// Definitions for directory entries -// -/** Type name for directoryEntry */ -typedef struct directoryEntry dir_t; -/** escape for name[0] = 0XE5 */ -uint8_t const DIR_NAME_0XE5 = 0X05; -/** name[0] value for entry that is free after being "deleted" */ -uint8_t const DIR_NAME_DELETED = 0XE5; -/** name[0] value for entry that is free and no allocated entries follow */ -uint8_t const DIR_NAME_FREE = 0X00; -/** file is read-only */ -uint8_t const DIR_ATT_READ_ONLY = 0X01; -/** File should hidden in directory listings */ -uint8_t const DIR_ATT_HIDDEN = 0X02; -/** Entry is for a system file */ -uint8_t const DIR_ATT_SYSTEM = 0X04; -/** Directory entry contains the volume label */ -uint8_t const DIR_ATT_VOLUME_ID = 0X08; -/** Entry is for a directory */ -uint8_t const DIR_ATT_DIRECTORY = 0X10; -/** Old DOS archive bit for backup support */ -uint8_t const DIR_ATT_ARCHIVE = 0X20; -/** Test value for long name entry. Test is - (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ -uint8_t const DIR_ATT_LONG_NAME = 0X0F; -/** Test mask for long name entry */ -uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; -/** defined attribute bits */ -uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; -/** Directory entry is part of a long name */ -static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { - return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; -} -/** Mask for file/subdirectory tests */ -uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); -/** Directory entry is for a file */ -static inline uint8_t DIR_IS_FILE(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; -} -/** Directory entry is for a subdirectory */ -static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; -} -/** Directory entry is for a file or subdirectory */ -static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; -} -#endif // FatStructs_h diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.cpp b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.cpp deleted file mode 100644 index fc3d857..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.cpp +++ /dev/null @@ -1,777 +0,0 @@ -/* Arduino Sd2Card Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino Sd2Card Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino Sd2Card Library. If not, see - . -*/ -#define USE_SPI_LIB -#include -#include "Sd2Card.h" -//------------------------------------------------------------------------------ -#ifndef SOFTWARE_SPI -#ifdef USE_SPI_LIB - - #ifndef SDCARD_SPI - #define SDCARD_SPI SPI - #endif - - #include - static SPISettings settings; -#endif -// functions for hardware SPI -/** Send a byte to the card */ -static void spiSend(uint8_t b) { - #ifndef USE_SPI_LIB - SPDR = b; - while (!(SPSR & (1 << SPIF))) - ; - #else - SDCARD_SPI.transfer(b); - #endif -} -/** Receive a byte from the card */ -static uint8_t spiRec(void) { - #ifndef USE_SPI_LIB - spiSend(0XFF); - return SPDR; - #else - return SDCARD_SPI.transfer(0xFF); - #endif -} -#else // SOFTWARE_SPI -//------------------------------------------------------------------------------ -/** nop to tune soft SPI timing */ -#define nop asm volatile ("nop\n\t") -//------------------------------------------------------------------------------ -/** Soft SPI receive */ -uint8_t spiRec(void) { - uint8_t data = 0; - // no interrupts during byte receive - about 8 us - cli(); - // output pin high - like sending 0XFF - fastDigitalWrite(SPI_MOSI_PIN, HIGH); - - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, HIGH); - - // adjust so SCK is nice - nop; - nop; - - data <<= 1; - - if (fastDigitalRead(SPI_MISO_PIN)) { - data |= 1; - } - - fastDigitalWrite(SPI_SCK_PIN, LOW); - } - // enable interrupts - sei(); - return data; -} -//------------------------------------------------------------------------------ -/** Soft SPI send */ -void spiSend(uint8_t data) { - // no interrupts during byte send - about 8 us - cli(); - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, LOW); - - fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); - - data <<= 1; - - fastDigitalWrite(SPI_SCK_PIN, HIGH); - } - // hold SCK high for a few ns - nop; - nop; - nop; - nop; - - fastDigitalWrite(SPI_SCK_PIN, LOW); - // enable interrupts - sei(); -} -#endif // SOFTWARE_SPI -//------------------------------------------------------------------------------ -// send command and return error code. Return zero for OK -uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { - // end read if in partialBlockRead mode - readEnd(); - - // select card - chipSelectLow(); - - // wait up to 300 ms if busy - waitNotBusy(300); - - // send command - spiSend(cmd | 0x40); - - // send argument - for (int8_t s = 24; s >= 0; s -= 8) { - spiSend(arg >> s); - } - - // send CRC - uint8_t crc = 0XFF; - if (cmd == CMD0) { - crc = 0X95; // correct crc for CMD0 with arg 0 - } - if (cmd == CMD8) { - crc = 0X87; // correct crc for CMD8 with arg 0X1AA - } - spiSend(crc); - - // wait for response - for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++) - ; - return status_; -} -//------------------------------------------------------------------------------ -/** - Determine the size of an SD flash memory card. - - \return The number of 512 byte data blocks in the card - or zero if an error occurs. -*/ -uint32_t Sd2Card::cardSize(void) { - csd_t csd; - if (!readCSD(&csd)) { - return 0; - } - if (csd.v1.csd_ver == 0) { - uint8_t read_bl_len = csd.v1.read_bl_len; - uint16_t c_size = (csd.v1.c_size_high << 10) - | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; - uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) - | csd.v1.c_size_mult_low; - return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); - } else if (csd.v2.csd_ver == 1) { - uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) - | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; - return (c_size + 1) << 10; - } else { - error(SD_CARD_ERROR_BAD_CSD); - return 0; - } -} -//------------------------------------------------------------------------------ -static uint8_t chip_select_asserted = 0; - -void Sd2Card::chipSelectHigh(void) { - digitalWrite(chipSelectPin_, HIGH); - #ifdef USE_SPI_LIB - if (chip_select_asserted) { - chip_select_asserted = 0; - SDCARD_SPI.endTransaction(); - } - #endif -} -//------------------------------------------------------------------------------ -void Sd2Card::chipSelectLow(void) { - #ifdef USE_SPI_LIB - if (!chip_select_asserted) { - chip_select_asserted = 1; - SDCARD_SPI.beginTransaction(settings); - } - #endif - digitalWrite(chipSelectPin_, LOW); -} -//------------------------------------------------------------------------------ -/** Erase a range of blocks. - - \param[in] firstBlock The address of the first block in the range. - \param[in] lastBlock The address of the last block in the range. - - \note This function requests the SD card to do a flash erase for a - range of blocks. The data on the card after an erase operation is - either 0 or 1, depends on the card vendor. The card must support - single block erase. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { - if (!eraseSingleBlockEnable()) { - error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); - goto fail; - } - if (type_ != SD_CARD_TYPE_SDHC) { - firstBlock <<= 9; - lastBlock <<= 9; - } - if (cardCommand(CMD32, firstBlock) - || cardCommand(CMD33, lastBlock) - || cardCommand(CMD38, 0)) { - error(SD_CARD_ERROR_ERASE); - goto fail; - } - if (!waitNotBusy(SD_ERASE_TIMEOUT)) { - error(SD_CARD_ERROR_ERASE_TIMEOUT); - goto fail; - } - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Determine if card supports single block erase. - - \return The value one, true, is returned if single block erase is supported. - The value zero, false, is returned if single block erase is not supported. -*/ -uint8_t Sd2Card::eraseSingleBlockEnable(void) { - csd_t csd; - return readCSD(&csd) ? csd.v1.erase_blk_en : 0; -} -//------------------------------------------------------------------------------ -/** - Initialize an SD flash memory card. - - \param[in] sckRateID SPI clock rate selector. See setSckRate(). - \param[in] chipSelectPin SD chip select pin number. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. The reason for failure - can be determined by calling errorCode() and errorData(). -*/ -uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { - errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0; - chipSelectPin_ = chipSelectPin; - // 16-bit init start time allows over a minute - unsigned int t0 = millis(); - uint32_t arg; - - // set pin modes - pinMode(chipSelectPin_, OUTPUT); - digitalWrite(chipSelectPin_, HIGH); - #ifndef USE_SPI_LIB - pinMode(SPI_MISO_PIN, INPUT); - pinMode(SPI_MOSI_PIN, OUTPUT); - pinMode(SPI_SCK_PIN, OUTPUT); - #endif - - #ifndef SOFTWARE_SPI - #ifndef USE_SPI_LIB - // SS must be in output mode even it is not chip select - pinMode(SS_PIN, OUTPUT); - digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin - // Enable SPI, Master, clock rate f_osc/128 - SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); - // clear double speed - SPSR &= ~(1 << SPI2X); - #else // USE_SPI_LIB - SDCARD_SPI.begin(); - settings = SPISettings(250000, MSBFIRST, SPI_MODE0); - #endif // USE_SPI_LIB - #endif // SOFTWARE_SPI - - // must supply min of 74 clock cycles with CS high. - #ifdef USE_SPI_LIB - SDCARD_SPI.beginTransaction(settings); - #endif - for (uint8_t i = 0; i < 10; i++) { - spiSend(0XFF); - } - #ifdef USE_SPI_LIB - SDCARD_SPI.endTransaction(); - #endif - - chipSelectLow(); - - // command to go idle in SPI mode - while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { - unsigned int d = millis() - t0; - if (d > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_CMD0); - goto fail; - } - } - // check SD version - if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { - type(SD_CARD_TYPE_SD1); - } else { - // only need last byte of r7 response - for (uint8_t i = 0; i < 4; i++) { - status_ = spiRec(); - } - if (status_ != 0XAA) { - error(SD_CARD_ERROR_CMD8); - goto fail; - } - type(SD_CARD_TYPE_SD2); - } - // initialize card and send host supports SDHC if SD2 - arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; - - while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { - // check for timeout - unsigned int d = millis() - t0; - if (d > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_ACMD41); - goto fail; - } - } - // if SD2 read OCR register to check for SDHC card - if (type() == SD_CARD_TYPE_SD2) { - if (cardCommand(CMD58, 0)) { - error(SD_CARD_ERROR_CMD58); - goto fail; - } - if ((spiRec() & 0XC0) == 0XC0) { - type(SD_CARD_TYPE_SDHC); - } - // discard rest of ocr - contains allowed voltage range - for (uint8_t i = 0; i < 3; i++) { - spiRec(); - } - } - chipSelectHigh(); - - #ifndef SOFTWARE_SPI - return setSckRate(sckRateID); - #else // SOFTWARE_SPI - return true; - #endif // SOFTWARE_SPI - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - Enable or disable partial block reads. - - Enabling partial block reads improves performance by allowing a block - to be read over the SPI bus as several sub-blocks. Errors may occur - if the time between reads is too long since the SD card may timeout. - The SPI SS line will be held low until the entire block is read or - readEnd() is called. - - Use this for applications like the Adafruit Wave Shield. - - \param[in] value The value TRUE (non-zero) or FALSE (zero).) -*/ -void Sd2Card::partialBlockRead(uint8_t value) { - readEnd(); - partialBlockRead_ = value; -} -//------------------------------------------------------------------------------ -/** - Read a 512 byte block from an SD card device. - - \param[in] block Logical block to be read. - \param[out] dst Pointer to the location that will receive the data. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { - return readData(block, 0, 512, dst); -} -//------------------------------------------------------------------------------ -/** - Read part of a 512 byte block from an SD card. - - \param[in] block Logical block to be read. - \param[in] offset Number of bytes to skip at start of block - \param[out] dst Pointer to the location that will receive the data. - \param[in] count Number of bytes to read - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t Sd2Card::readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst) { - if (count == 0) { - return true; - } - if ((count + offset) > 512) { - goto fail; - } - if (!inBlock_ || block != block_ || offset < offset_) { - block_ = block; - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) { - block <<= 9; - } - if (cardCommand(CMD17, block)) { - error(SD_CARD_ERROR_CMD17); - goto fail; - } - if (!waitStartBlock()) { - goto fail; - } - offset_ = 0; - inBlock_ = 1; - } - - #ifdef OPTIMIZE_HARDWARE_SPI - // start first spi transfer - SPDR = 0XFF; - - // skip data before offset - for (; offset_ < offset; offset_++) { - while (!(SPSR & (1 << SPIF))) - ; - SPDR = 0XFF; - } - // transfer data - n = count - 1; - for (uint16_t i = 0; i < n; i++) { - while (!(SPSR & (1 << SPIF))) - ; - dst[i] = SPDR; - SPDR = 0XFF; - } - // wait for last byte - while (!(SPSR & (1 << SPIF))) - ; - dst[n] = SPDR; - - #else // OPTIMIZE_HARDWARE_SPI - - // skip data before offset - for (; offset_ < offset; offset_++) { - spiRec(); - } - // transfer data - for (uint16_t i = 0; i < count; i++) { - dst[i] = spiRec(); - } - #endif // OPTIMIZE_HARDWARE_SPI - - offset_ += count; - if (!partialBlockRead_ || offset_ >= 512) { - // read rest of data, checksum and set chip select high - readEnd(); - } - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Skip remaining data in a block when in partial block read mode. */ -void Sd2Card::readEnd(void) { - if (inBlock_) { - // skip data and crc - #ifdef OPTIMIZE_HARDWARE_SPI - // optimize skip for hardware - SPDR = 0XFF; - while (offset_++ < 513) { - while (!(SPSR & (1 << SPIF))) - ; - SPDR = 0XFF; - } - // wait for last crc byte - while (!(SPSR & (1 << SPIF))) - ; - #else // OPTIMIZE_HARDWARE_SPI - while (offset_++ < 514) { - spiRec(); - } - #endif // OPTIMIZE_HARDWARE_SPI - chipSelectHigh(); - inBlock_ = 0; - } -} -//------------------------------------------------------------------------------ -/** read CID or CSR register */ -uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { - uint8_t* dst = reinterpret_cast(buf); - if (cardCommand(cmd, 0)) { - error(SD_CARD_ERROR_READ_REG); - goto fail; - } - if (!waitStartBlock()) { - goto fail; - } - // transfer data - for (uint16_t i = 0; i < 16; i++) { - dst[i] = spiRec(); - } - spiRec(); // get first crc byte - spiRec(); // get second crc byte - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - Set the SPI clock rate. - - \param[in] sckRateID A value in the range [0, 6]. - - The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum - SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 - for \a scsRateID = 6. - - \return The value one, true, is returned for success and the value zero, - false, is returned for an invalid value of \a sckRateID. -*/ -uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { - if (sckRateID > 6) { - error(SD_CARD_ERROR_SCK_RATE); - return false; - } - #ifndef USE_SPI_LIB - // see avr processor datasheet for SPI register bit definitions - if ((sckRateID & 1) || sckRateID == 6) { - SPSR &= ~(1 << SPI2X); - } else { - SPSR |= (1 << SPI2X); - } - SPCR &= ~((1 << SPR1) | (1 << SPR0)); - SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0) - | (sckRateID & 2 ? (1 << SPR0) : 0); - #else // USE_SPI_LIB - switch (sckRateID) { - case 0: settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); break; - case 1: settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); break; - case 2: settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); break; - case 3: settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); break; - case 4: settings = SPISettings(500000, MSBFIRST, SPI_MODE0); break; - case 5: settings = SPISettings(250000, MSBFIRST, SPI_MODE0); break; - default: settings = SPISettings(125000, MSBFIRST, SPI_MODE0); - } - #endif // USE_SPI_LIB - return true; -} -#ifdef USE_SPI_LIB -//------------------------------------------------------------------------------ -// set the SPI clock frequency -uint8_t Sd2Card::setSpiClock(uint32_t clock) { - settings = SPISettings(clock, MSBFIRST, SPI_MODE0); - return true; -} -#endif -//------------------------------------------------------------------------------ -// wait for card to go not busy -uint8_t Sd2Card::waitNotBusy(unsigned int timeoutMillis) { - unsigned int t0 = millis(); - unsigned int d; - do { - if (spiRec() == 0XFF) { - return true; - } - d = millis() - t0; - } while (d < timeoutMillis); - return false; -} -//------------------------------------------------------------------------------ -/** Wait for start block token */ -uint8_t Sd2Card::waitStartBlock(void) { - unsigned int t0 = millis(); - while ((status_ = spiRec()) == 0XFF) { - unsigned int d = millis() - t0; - if (d > SD_READ_TIMEOUT) { - error(SD_CARD_ERROR_READ_TIMEOUT); - goto fail; - } - } - if (status_ != DATA_START_BLOCK) { - error(SD_CARD_ERROR_READ); - goto fail; - } - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - Writes a 512 byte block to an SD card. - - \param[in] blockNumber Logical block to be written. - \param[in] src Pointer to the location of the data to be written. - \param[in] blocking If the write should be blocking. - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking) { - #if SD_PROTECT_BLOCK_ZERO - // don't allow write to first block - if (blockNumber == 0) { - error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); - goto fail; - } - #endif // SD_PROTECT_BLOCK_ZERO - - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) { - blockNumber <<= 9; - } - if (cardCommand(CMD24, blockNumber)) { - error(SD_CARD_ERROR_CMD24); - goto fail; - } - if (!writeData(DATA_START_BLOCK, src)) { - goto fail; - } - if (blocking) { - // wait for flash programming to complete - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_TIMEOUT); - goto fail; - } - // response is r2 so get and check two bytes for nonzero - if (cardCommand(CMD13, 0) || spiRec()) { - error(SD_CARD_ERROR_WRITE_PROGRAMMING); - goto fail; - } - } - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Write one data block in a multiple block write sequence */ -uint8_t Sd2Card::writeData(const uint8_t* src) { - // wait for previous write to finish - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_MULTIPLE); - chipSelectHigh(); - return false; - } - return writeData(WRITE_MULTIPLE_TOKEN, src); -} -//------------------------------------------------------------------------------ -// send one block of data for write block or write multiple blocks -uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { - #ifdef OPTIMIZE_HARDWARE_SPI - - // send data - optimized loop - SPDR = token; - - // send two byte per iteration - for (uint16_t i = 0; i < 512; i += 2) { - while (!(SPSR & (1 << SPIF))) - ; - SPDR = src[i]; - while (!(SPSR & (1 << SPIF))) - ; - SPDR = src[i + 1]; - } - - // wait for last data byte - while (!(SPSR & (1 << SPIF))) - ; - - #else // OPTIMIZE_HARDWARE_SPI - spiSend(token); - for (uint16_t i = 0; i < 512; i++) { - spiSend(src[i]); - } - #endif // OPTIMIZE_HARDWARE_SPI - spiSend(0xff); // dummy crc - spiSend(0xff); // dummy crc - - status_ = spiRec(); - if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { - error(SD_CARD_ERROR_WRITE); - chipSelectHigh(); - return false; - } - return true; -} -//------------------------------------------------------------------------------ -/** Start a write multiple blocks sequence. - - \param[in] blockNumber Address of first block in sequence. - \param[in] eraseCount The number of blocks to be pre-erased. - - \note This function is used with writeData() and writeStop() - for optimized multiple block writes. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { - #if SD_PROTECT_BLOCK_ZERO - // don't allow write to first block - if (blockNumber == 0) { - error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); - goto fail; - } - #endif // SD_PROTECT_BLOCK_ZERO - // send pre-erase count - if (cardAcmd(ACMD23, eraseCount)) { - error(SD_CARD_ERROR_ACMD23); - goto fail; - } - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) { - blockNumber <<= 9; - } - if (cardCommand(CMD25, blockNumber)) { - error(SD_CARD_ERROR_CMD25); - goto fail; - } - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** End a write multiple blocks sequence. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t Sd2Card::writeStop(void) { - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - goto fail; - } - spiSend(STOP_TRAN_TOKEN); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - goto fail; - } - chipSelectHigh(); - return true; - -fail: - error(SD_CARD_ERROR_STOP_TRAN); - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Check if the SD card is busy - - \return The value one, true, is returned when is busy and - the value zero, false, is returned for when is NOT busy. -*/ -uint8_t Sd2Card::isBusy(void) { - chipSelectLow(); - byte b = spiRec(); - chipSelectHigh(); - - return (b != 0XFF); -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.h deleted file mode 100644 index 59ec95b..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.h +++ /dev/null @@ -1,273 +0,0 @@ -/* Arduino Sd2Card Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino Sd2Card Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino Sd2Card Library. If not, see - . -*/ -#ifndef Sd2Card_h -#define Sd2Card_h -/** - \file - Sd2Card class -*/ -#include "Sd2PinMap.h" -#include "SdInfo.h" -/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */ -uint8_t const SPI_FULL_SPEED = 0; -/** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */ -uint8_t const SPI_HALF_SPEED = 1; -/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */ -uint8_t const SPI_QUARTER_SPEED = 2; -/** - USE_SPI_LIB: if set, use the SPI library bundled with Arduino IDE, otherwise - run with a standalone driver for AVR. -*/ -#define USE_SPI_LIB -/** - Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos. - Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. - - MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used - on Mega Arduinos. Software SPI works well with GPS Shield V1.1 - but many SD cards will fail with GPS Shield V1.0. -*/ -#define MEGA_SOFT_SPI 0 -//------------------------------------------------------------------------------ -#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) - #define SOFTWARE_SPI -#endif // MEGA_SOFT_SPI -//------------------------------------------------------------------------------ -// SPI pin definitions -// -#ifndef SOFTWARE_SPI - // hardware pin defs - - // include pins_arduino.h or variant.h depending on architecture, via Arduino.h - #include - - /** - SD Chip Select pin - - Warning if this pin is redefined the hardware SS will pin will be enabled - as an output by init(). An avr processor will not function as an SPI - master unless SS is set to output mode. - */ - #ifndef SDCARD_SS_PIN - /** The default chip select pin for the SD card is SS. */ - uint8_t const SD_CHIP_SELECT_PIN = SS; - #else - uint8_t const SD_CHIP_SELECT_PIN = SDCARD_SS_PIN; - #endif - - // The following three pins must not be redefined for hardware SPI, - // so ensure that they are taken from pins_arduino.h or variant.h, depending on architecture. - #ifndef SDCARD_MOSI_PIN - /** SPI Master Out Slave In pin */ - uint8_t const SPI_MOSI_PIN = MOSI; - /** SPI Master In Slave Out pin */ - uint8_t const SPI_MISO_PIN = MISO; - /** SPI Clock pin */ - uint8_t const SPI_SCK_PIN = SCK; - #else - uint8_t const SPI_MOSI_PIN = SDCARD_MOSI_PIN; - uint8_t const SPI_MISO_PIN = SDCARD_MISO_PIN; - uint8_t const SPI_SCK_PIN = SDCARD_SCK_PIN; - #endif - - /** optimize loops for hardware SPI */ - #ifndef USE_SPI_LIB - #define OPTIMIZE_HARDWARE_SPI - #endif - -#else // SOFTWARE_SPI - // define software SPI pins so Mega can use unmodified GPS Shield - /** SPI chip select pin */ - uint8_t const SD_CHIP_SELECT_PIN = 10; - /** SPI Master Out Slave In pin */ - uint8_t const SPI_MOSI_PIN = 11; - /** SPI Master In Slave Out pin */ - uint8_t const SPI_MISO_PIN = 12; - /** SPI Clock pin */ - uint8_t const SPI_SCK_PIN = 13; -#endif // SOFTWARE_SPI -//------------------------------------------------------------------------------ -/** Protect block zero from write if nonzero */ -#define SD_PROTECT_BLOCK_ZERO 1 -/** init timeout ms */ -unsigned int const SD_INIT_TIMEOUT = 2000; -/** erase timeout ms */ -unsigned int const SD_ERASE_TIMEOUT = 10000; -/** read timeout ms */ -unsigned int const SD_READ_TIMEOUT = 300; -/** write time out ms */ -unsigned int const SD_WRITE_TIMEOUT = 600; -//------------------------------------------------------------------------------ -// SD card errors -/** timeout error for command CMD0 */ -uint8_t const SD_CARD_ERROR_CMD0 = 0X1; -/** CMD8 was not accepted - not a valid SD card*/ -uint8_t const SD_CARD_ERROR_CMD8 = 0X2; -/** card returned an error response for CMD17 (read block) */ -uint8_t const SD_CARD_ERROR_CMD17 = 0X3; -/** card returned an error response for CMD24 (write block) */ -uint8_t const SD_CARD_ERROR_CMD24 = 0X4; -/** WRITE_MULTIPLE_BLOCKS command failed */ -uint8_t const SD_CARD_ERROR_CMD25 = 0X05; -/** card returned an error response for CMD58 (read OCR) */ -uint8_t const SD_CARD_ERROR_CMD58 = 0X06; -/** SET_WR_BLK_ERASE_COUNT failed */ -uint8_t const SD_CARD_ERROR_ACMD23 = 0X07; -/** card's ACMD41 initialization process timeout */ -uint8_t const SD_CARD_ERROR_ACMD41 = 0X08; -/** card returned a bad CSR version field */ -uint8_t const SD_CARD_ERROR_BAD_CSD = 0X09; -/** erase block group command failed */ -uint8_t const SD_CARD_ERROR_ERASE = 0X0A; -/** card not capable of single block erase */ -uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B; -/** Erase sequence timed out */ -uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C; -/** card returned an error token instead of read data */ -uint8_t const SD_CARD_ERROR_READ = 0X0D; -/** read CID or CSD failed */ -uint8_t const SD_CARD_ERROR_READ_REG = 0X0E; -/** timeout while waiting for start of read data */ -uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F; -/** card did not accept STOP_TRAN_TOKEN */ -uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10; -/** card returned an error token as a response to a write operation */ -uint8_t const SD_CARD_ERROR_WRITE = 0X11; -/** attempt to write protected block zero */ -uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12; -/** card did not go ready for a multiple block write */ -uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13; -/** card returned an error to a CMD13 status check after a write */ -uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14; -/** timeout occurred during write programming */ -uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15; -/** incorrect rate selected */ -uint8_t const SD_CARD_ERROR_SCK_RATE = 0X16; -//------------------------------------------------------------------------------ -// card types -/** Standard capacity V1 SD card */ -uint8_t const SD_CARD_TYPE_SD1 = 1; -/** Standard capacity V2 SD card */ -uint8_t const SD_CARD_TYPE_SD2 = 2; -/** High Capacity SD card */ -uint8_t const SD_CARD_TYPE_SDHC = 3; -//------------------------------------------------------------------------------ -/** - \class Sd2Card - \brief Raw access to SD and SDHC flash memory cards. -*/ -class Sd2Card { - public: - /** Construct an instance of Sd2Card. */ - Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} - uint32_t cardSize(void); - uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); - uint8_t eraseSingleBlockEnable(void); - /** - \return error code for last error. See Sd2Card.h for a list of error codes. - */ - uint8_t errorCode(void) const { - return errorCode_; - } - /** \return error data for last error. */ - uint8_t errorData(void) const { - return status_; - } - /** - Initialize an SD flash memory card with default clock rate and chip - select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). - */ - uint8_t init(void) { - return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); - } - /** - Initialize an SD flash memory card with the selected SPI clock rate - and the default SD chip select pin. - See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). - */ - uint8_t init(uint8_t sckRateID) { - return init(sckRateID, SD_CHIP_SELECT_PIN); - } - uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); - void partialBlockRead(uint8_t value); - /** Returns the current value, true or false, for partial block read. */ - uint8_t partialBlockRead(void) const { - return partialBlockRead_; - } - uint8_t readBlock(uint32_t block, uint8_t* dst); - uint8_t readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst); - /** - Read a cards CID register. The CID contains card identification - information such as Manufacturer ID, Product name, Product serial - number and Manufacturing date. */ - uint8_t readCID(cid_t* cid) { - return readRegister(CMD10, cid); - } - /** - Read a cards CSD register. The CSD contains Card-Specific Data that - provides information regarding access to the card's contents. */ - uint8_t readCSD(csd_t* csd) { - return readRegister(CMD9, csd); - } - void readEnd(void); - uint8_t setSckRate(uint8_t sckRateID); - #ifdef USE_SPI_LIB - uint8_t setSpiClock(uint32_t clock); - #endif - /** Return the card type: SD V1, SD V2 or SDHC */ - uint8_t type(void) const { - return type_; - } - uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking = 1); - uint8_t writeData(const uint8_t* src); - uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); - uint8_t writeStop(void); - uint8_t isBusy(void); - private: - uint32_t block_; - uint8_t chipSelectPin_; - uint8_t errorCode_; - uint8_t inBlock_; - uint16_t offset_; - uint8_t partialBlockRead_; - uint8_t status_; - uint8_t type_; - // private functions - uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { - cardCommand(CMD55, 0); - return cardCommand(cmd, arg); - } - uint8_t cardCommand(uint8_t cmd, uint32_t arg); - void error(uint8_t code) { - errorCode_ = code; - } - uint8_t readRegister(uint8_t cmd, void* buf); - uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); - void chipSelectHigh(void); - void chipSelectLow(void); - void type(uint8_t value) { - type_ = value; - } - uint8_t waitNotBusy(unsigned int timeoutMillis); - uint8_t writeData(uint8_t token, const uint8_t* src); - uint8_t waitStartBlock(void); -}; -#endif // Sd2Card_h diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2PinMap.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2PinMap.h deleted file mode 100644 index 616813b..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2PinMap.h +++ /dev/null @@ -1,528 +0,0 @@ -/* Arduino SdFat Library - Copyright (C) 2010 by William Greiman - - This file is part of the Arduino SdFat Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino SdFat Library. If not, see - . -*/ -#if defined(__arm__) // Arduino Due Board follows - -#ifndef Sd2PinMap_h - #define Sd2PinMap_h - - #include - - uint8_t const SS_PIN = SS; - uint8_t const MOSI_PIN = MOSI; - uint8_t const MISO_PIN = MISO; - uint8_t const SCK_PIN = SCK; - -#endif // Sd2PinMap_h - -#elif defined(__AVR_ATmega4809__) || defined(__AVR_ATmega4808__) || \ -defined(__AVR_ATmega3209__) || defined(__AVR_ATmega3208__) || \ -defined(__AVR_ATmega1609__) || defined(__AVR_ATmega1608__) || \ -defined(__AVR_ATmega809__) || defined(__AVR_ATmega808__) - -#ifndef Sd2PinMap_h - #define Sd2PinMap_h - - #include - - uint8_t const SS_PIN = SS; - uint8_t const MOSI_PIN = MOSI; - uint8_t const MISO_PIN = MISO; - uint8_t const SCK_PIN = SCK; - -#endif // Sd2PinMap_h - -#elif defined(__AVR__) // Other AVR based Boards follows - -// Warning this file was generated by a program. -#ifndef Sd2PinMap_h -#define Sd2PinMap_h -#include - -//------------------------------------------------------------------------------ -/** struct for mapping digital pins */ -struct pin_map_t { - volatile uint8_t* ddr; - volatile uint8_t* pin; - volatile uint8_t* port; - uint8_t bit; -}; -//------------------------------------------------------------------------------ -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -// Mega - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 20; -uint8_t const SCL_PIN = 21; - -// SPI port -uint8_t const SS_PIN = 53; -uint8_t const MOSI_PIN = 51; -uint8_t const MISO_PIN = 50; -uint8_t const SCK_PIN = 52; - -static const pin_map_t digitalPinMap[] = { - {&DDRE, &PINE, &PORTE, 0}, // E0 0 - {&DDRE, &PINE, &PORTE, 1}, // E1 1 - {&DDRE, &PINE, &PORTE, 4}, // E4 2 - {&DDRE, &PINE, &PORTE, 5}, // E5 3 - {&DDRG, &PING, &PORTG, 5}, // G5 4 - {&DDRE, &PINE, &PORTE, 3}, // E3 5 - {&DDRH, &PINH, &PORTH, 3}, // H3 6 - {&DDRH, &PINH, &PORTH, 4}, // H4 7 - {&DDRH, &PINH, &PORTH, 5}, // H5 8 - {&DDRH, &PINH, &PORTH, 6}, // H6 9 - {&DDRB, &PINB, &PORTB, 4}, // B4 10 - {&DDRB, &PINB, &PORTB, 5}, // B5 11 - {&DDRB, &PINB, &PORTB, 6}, // B6 12 - {&DDRB, &PINB, &PORTB, 7}, // B7 13 - {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 - {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 - {&DDRH, &PINH, &PORTH, 1}, // H1 16 - {&DDRH, &PINH, &PORTH, 0}, // H0 17 - {&DDRD, &PIND, &PORTD, 3}, // D3 18 - {&DDRD, &PIND, &PORTD, 2}, // D2 19 - {&DDRD, &PIND, &PORTD, 1}, // D1 20 - {&DDRD, &PIND, &PORTD, 0}, // D0 21 - {&DDRA, &PINA, &PORTA, 0}, // A0 22 - {&DDRA, &PINA, &PORTA, 1}, // A1 23 - {&DDRA, &PINA, &PORTA, 2}, // A2 24 - {&DDRA, &PINA, &PORTA, 3}, // A3 25 - {&DDRA, &PINA, &PORTA, 4}, // A4 26 - {&DDRA, &PINA, &PORTA, 5}, // A5 27 - {&DDRA, &PINA, &PORTA, 6}, // A6 28 - {&DDRA, &PINA, &PORTA, 7}, // A7 29 - {&DDRC, &PINC, &PORTC, 7}, // C7 30 - {&DDRC, &PINC, &PORTC, 6}, // C6 31 - {&DDRC, &PINC, &PORTC, 5}, // C5 32 - {&DDRC, &PINC, &PORTC, 4}, // C4 33 - {&DDRC, &PINC, &PORTC, 3}, // C3 34 - {&DDRC, &PINC, &PORTC, 2}, // C2 35 - {&DDRC, &PINC, &PORTC, 1}, // C1 36 - {&DDRC, &PINC, &PORTC, 0}, // C0 37 - {&DDRD, &PIND, &PORTD, 7}, // D7 38 - {&DDRG, &PING, &PORTG, 2}, // G2 39 - {&DDRG, &PING, &PORTG, 1}, // G1 40 - {&DDRG, &PING, &PORTG, 0}, // G0 41 - {&DDRL, &PINL, &PORTL, 7}, // L7 42 - {&DDRL, &PINL, &PORTL, 6}, // L6 43 - {&DDRL, &PINL, &PORTL, 5}, // L5 44 - {&DDRL, &PINL, &PORTL, 4}, // L4 45 - {&DDRL, &PINL, &PORTL, 3}, // L3 46 - {&DDRL, &PINL, &PORTL, 2}, // L2 47 - {&DDRL, &PINL, &PORTL, 1}, // L1 48 - {&DDRL, &PINL, &PORTL, 0}, // L0 49 - {&DDRB, &PINB, &PORTB, 3}, // B3 50 - {&DDRB, &PINB, &PORTB, 2}, // B2 51 - {&DDRB, &PINB, &PORTB, 1}, // B1 52 - {&DDRB, &PINB, &PORTB, 0}, // B0 53 - {&DDRF, &PINF, &PORTF, 0}, // F0 54 - {&DDRF, &PINF, &PORTF, 1}, // F1 55 - {&DDRF, &PINF, &PORTF, 2}, // F2 56 - {&DDRF, &PINF, &PORTF, 3}, // F3 57 - {&DDRF, &PINF, &PORTF, 4}, // F4 58 - {&DDRF, &PINF, &PORTF, 5}, // F5 59 - {&DDRF, &PINF, &PORTF, 6}, // F6 60 - {&DDRF, &PINF, &PORTF, 7}, // F7 61 - {&DDRK, &PINK, &PORTK, 0}, // K0 62 - {&DDRK, &PINK, &PORTK, 1}, // K1 63 - {&DDRK, &PINK, &PORTK, 2}, // K2 64 - {&DDRK, &PINK, &PORTK, 3}, // K3 65 - {&DDRK, &PINK, &PORTK, 4}, // K4 66 - {&DDRK, &PINK, &PORTK, 5}, // K5 67 - {&DDRK, &PINK, &PORTK, 6}, // K6 68 - {&DDRK, &PINK, &PORTK, 7} // K7 69 -}; -//------------------------------------------------------------------------------ -#elif (defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && defined(CORE_MICRODUINO) -// Microduino Core+ - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 20; -uint8_t const SCL_PIN = 21; - -// SPI port -uint8_t const SS_PIN = 10; -uint8_t const MOSI_PIN = 11; -uint8_t const MISO_PIN = 12; -uint8_t const SCK_PIN = 13; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 PD0 - {&DDRD, &PIND, &PORTD, 1}, // D1 PD1 - {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 - {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 - {&DDRB, &PINB, &PORTB, 0}, // D4 PB0 - {&DDRB, &PINB, &PORTB, 1}, // D5 PB1 - {&DDRB, &PINB, &PORTB, 2}, // D6 PB2 - {&DDRB, &PINB, &PORTB, 3}, // D7 PB3 - {&DDRD, &PIND, &PORTD, 6}, // D8 PD6 - {&DDRD, &PIND, &PORTD, 5}, // D9 PD5 - {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 - {&DDRB, &PINB, &PORTB, 5}, // D11 PB5 - {&DDRB, &PINB, &PORTB, 6}, // D12 PB6 - {&DDRB, &PINB, &PORTB, 7}, // D13 PB7 - {&DDRC, &PINC, &PORTC, 7}, // D14 PC7 - {&DDRC, &PINC, &PORTC, 6}, // D15 PC6 - {&DDRC, &PINC, &PORTC, 5}, // D16 PC5 - {&DDRC, &PINC, &PORTC, 4}, // D17 PC4 - {&DDRC, &PINC, &PORTC, 3}, // D18 PC3 - {&DDRC, &PINC, &PORTC, 2}, // D19 PC2 - {&DDRC, &PINC, &PORTC, 1}, // D20 PC1 - {&DDRC, &PINC, &PORTC, 0}, // D21 PC0 - {&DDRD, &PIND, &PORTD, 4}, // D22 PD4 - {&DDRD, &PIND, &PORTD, 7}, // D23 PD7 - {&DDRA, &PINA, &PORTA, 7}, // D24 PA7 - {&DDRA, &PINA, &PORTA, 6}, // D25 PA6 - {&DDRA, &PINA, &PORTA, 5}, // D26 PA5 - {&DDRA, &PINA, &PORTA, 4}, // D27 PA4 - {&DDRA, &PINA, &PORTA, 3}, // D28 PA3 - {&DDRA, &PINA, &PORTA, 2}, // D29 PA2 - {&DDRA, &PINA, &PORTA, 1}, // D30 PA1 - {&DDRA, &PINA, &PORTA, 0} // D31 PA0 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega128RFA1__) && defined(CORE_MICRODUINO) -// Microduino Core RF - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 18; -uint8_t const SCL_PIN = 19; - -// SPI port -uint8_t const SS_PIN = 10; -uint8_t const MOSI_PIN = 11; -uint8_t const MISO_PIN = 12; -uint8_t const SCK_PIN = 13; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PINE, &PORTE, 0}, // D0 PE0 - {&DDRD, &PINE, &PORTE, 1}, // D1 PE1 - {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 - {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 - {&DDRB, &PINE, &PORTE, 3}, // D4 PE3 - {&DDRB, &PINE, &PORTE, 4}, // D5 PE4 - {&DDRB, &PINE, &PORTE, 5}, // D6 PE5 - {&DDRB, &PINB, &PORTB, 7}, // D7 PB7 - {&DDRD, &PINB, &PORTB, 6}, // D8 PB6 - {&DDRD, &PINB, &PORTB, 5}, // D9 PB5 - {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 - {&DDRB, &PINB, &PORTB, 2}, // D11 PB2 - {&DDRB, &PINB, &PORTB, 3}, // D12 PB3 - {&DDRB, &PINB, &PORTB, 1}, // D13 PB1 - {&DDRF, &PINF, &PORTF, 7}, // D14 PF7 - {&DDRF, &PINF, &PORTF, 6}, // D15 PF6 - {&DDRF, &PINF, &PORTF, 5}, // D16 PF5 - {&DDRF, &PINF, &PORTF, 4}, // D17 PF4 - {&DDRD, &PIND, &PORTD, 1}, // D18 PD1 - {&DDRD, &PIND, &PORTD, 0}, // D19 PD0 - {&DDRF, &PINF, &PORTF, 3}, // D20 PF3 - {&DDRF, &PINF, &PORTF, 2}, // D21 PF2 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega32U4__) && defined(CORE_MICRODUINO) -// Microduino Core USB - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 18; -uint8_t const SCL_PIN = 19; - -// SPI port -uint8_t const SS_PIN = 10; -uint8_t const MOSI_PIN = 11; -uint8_t const MISO_PIN = 12; -uint8_t const SCK_PIN = 13; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 2}, // D0 - PD2 - {&DDRD, &PIND, &PORTD, 3}, // D1 - PD3 - {&DDRE, &PINE, &PORTE, 6}, // D2 - PE6 - {&DDRD, &PIND, &PORTD, 6}, // D3 - PD6 - {&DDRD, &PIND, &PORTD, 7}, // D4 - PD7 - {&DDRC, &PINC, &PORTC, 6}, // D5 - PC6 - {&DDRC, &PINC, &PORTC, 7}, // D6 - PC7 - {&DDRE, &PINE, &PORTE, 7}, // D7 - PE7 - {&DDRB, &PINB, &PORTB, 6}, // D8 - PB6 - {&DDRB, &PINB, &PORTB, 5}, // D9 - PB5 - {&DDRB, &PINB, &PORTB, 0}, // D10 - PB0 - {&DDRB, &PINB, &PORTB, 2}, // D11 - MOSI - PB2 - {&DDRB, &PINB, &PORTB, 3}, // D12 -MISO - PB3 - {&DDRB, &PINB, &PORTB, 1}, // D13 -SCK - PB1 - {&DDRF, &PINF, &PORTF, 7}, // D14 - A0 - PF7 - {&DDRF, &PINF, &PORTF, 6}, // D15 - A1 - PF6 - {&DDRF, &PINF, &PORTF, 5}, // D16 - A2 - PF5 - {&DDRF, &PINF, &PORTF, 4}, // D17 - A3 - PF4 - {&DDRD, &PIND, &PORTD, 1}, // D18 - PD1 - {&DDRD, &PIND, &PORTD, 0}, // D19 - PD0 - {&DDRF, &PINF, &PORTF, 1}, // D20 - A6 - PF1 - {&DDRF, &PINF, &PORTF, 0}, // D21 - A7 - PF0 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) -// Sanguino - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 17; -uint8_t const SCL_PIN = 18; - -// SPI port -uint8_t const SS_PIN = 4; -uint8_t const MOSI_PIN = 5; -uint8_t const MISO_PIN = 6; -uint8_t const SCK_PIN = 7; - -static const pin_map_t digitalPinMap[] = { - {&DDRB, &PINB, &PORTB, 0}, // B0 0 - {&DDRB, &PINB, &PORTB, 1}, // B1 1 - {&DDRB, &PINB, &PORTB, 2}, // B2 2 - {&DDRB, &PINB, &PORTB, 3}, // B3 3 - {&DDRB, &PINB, &PORTB, 4}, // B4 4 - {&DDRB, &PINB, &PORTB, 5}, // B5 5 - {&DDRB, &PINB, &PORTB, 6}, // B6 6 - {&DDRB, &PINB, &PORTB, 7}, // B7 7 - {&DDRD, &PIND, &PORTD, 0}, // D0 8 - {&DDRD, &PIND, &PORTD, 1}, // D1 9 - {&DDRD, &PIND, &PORTD, 2}, // D2 10 - {&DDRD, &PIND, &PORTD, 3}, // D3 11 - {&DDRD, &PIND, &PORTD, 4}, // D4 12 - {&DDRD, &PIND, &PORTD, 5}, // D5 13 - {&DDRD, &PIND, &PORTD, 6}, // D6 14 - {&DDRD, &PIND, &PORTD, 7}, // D7 15 - {&DDRC, &PINC, &PORTC, 0}, // C0 16 - {&DDRC, &PINC, &PORTC, 1}, // C1 17 - {&DDRC, &PINC, &PORTC, 2}, // C2 18 - {&DDRC, &PINC, &PORTC, 3}, // C3 19 - {&DDRC, &PINC, &PORTC, 4}, // C4 20 - {&DDRC, &PINC, &PORTC, 5}, // C5 21 - {&DDRC, &PINC, &PORTC, 6}, // C6 22 - {&DDRC, &PINC, &PORTC, 7}, // C7 23 - {&DDRA, &PINA, &PORTA, 7}, // A7 24 - {&DDRA, &PINA, &PORTA, 6}, // A6 25 - {&DDRA, &PINA, &PORTA, 5}, // A5 26 - {&DDRA, &PINA, &PORTA, 4}, // A4 27 - {&DDRA, &PINA, &PORTA, 3}, // A3 28 - {&DDRA, &PINA, &PORTA, 2}, // A2 29 - {&DDRA, &PINA, &PORTA, 1}, // A1 30 - {&DDRA, &PINA, &PORTA, 0} // A0 31 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega32U4__) -// Leonardo - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 2; -uint8_t const SCL_PIN = 3; - -// SPI port -uint8_t const SS_PIN = 17; -uint8_t const MOSI_PIN = 16; -uint8_t const MISO_PIN = 14; -uint8_t const SCK_PIN = 15; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 2}, // D2 0 - {&DDRD, &PIND, &PORTD, 3}, // D3 1 - {&DDRD, &PIND, &PORTD, 1}, // D1 2 - {&DDRD, &PIND, &PORTD, 0}, // D0 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRC, &PINC, &PORTC, 6}, // C6 5 - {&DDRD, &PIND, &PORTD, 7}, // D7 6 - {&DDRE, &PINE, &PORTE, 6}, // E6 7 - {&DDRB, &PINB, &PORTB, 4}, // B4 8 - {&DDRB, &PINB, &PORTB, 5}, // B5 9 - {&DDRB, &PINB, &PORTB, 6}, // B6 10 - {&DDRB, &PINB, &PORTB, 7}, // B7 11 - {&DDRD, &PIND, &PORTD, 6}, // D6 12 - {&DDRC, &PINC, &PORTC, 7}, // C7 13 - {&DDRB, &PINB, &PORTB, 3}, // B3 14 - {&DDRB, &PINB, &PORTB, 1}, // B1 15 - {&DDRB, &PINB, &PORTB, 2}, // B2 16 - {&DDRB, &PINB, &PORTB, 0}, // B0 17 - {&DDRF, &PINF, &PORTF, 7}, // F7 18 - {&DDRF, &PINF, &PORTF, 6}, // F6 19 - {&DDRF, &PINF, &PORTF, 5}, // F5 20 - {&DDRF, &PINF, &PORTF, 4}, // F4 21 - {&DDRF, &PINF, &PORTF, 1}, // F1 22 - {&DDRF, &PINF, &PORTF, 0}, // F0 23 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -// Teensy++ 1.0 & 2.0 - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 1; -uint8_t const SCL_PIN = 0; - -// SPI port -uint8_t const SS_PIN = 20; -uint8_t const MOSI_PIN = 22; -uint8_t const MISO_PIN = 23; -uint8_t const SCK_PIN = 21; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRE, &PINE, &PORTE, 0}, // E0 8 - {&DDRE, &PINE, &PORTE, 1}, // E1 9 - {&DDRC, &PINC, &PORTC, 0}, // C0 10 - {&DDRC, &PINC, &PORTC, 1}, // C1 11 - {&DDRC, &PINC, &PORTC, 2}, // C2 12 - {&DDRC, &PINC, &PORTC, 3}, // C3 13 - {&DDRC, &PINC, &PORTC, 4}, // C4 14 - {&DDRC, &PINC, &PORTC, 5}, // C5 15 - {&DDRC, &PINC, &PORTC, 6}, // C6 16 - {&DDRC, &PINC, &PORTC, 7}, // C7 17 - {&DDRE, &PINE, &PORTE, 6}, // E6 18 - {&DDRE, &PINE, &PORTE, 7}, // E7 19 - {&DDRB, &PINB, &PORTB, 0}, // B0 20 - {&DDRB, &PINB, &PORTB, 1}, // B1 21 - {&DDRB, &PINB, &PORTB, 2}, // B2 22 - {&DDRB, &PINB, &PORTB, 3}, // B3 23 - {&DDRB, &PINB, &PORTB, 4}, // B4 24 - {&DDRB, &PINB, &PORTB, 5}, // B5 25 - {&DDRB, &PINB, &PORTB, 6}, // B6 26 - {&DDRB, &PINB, &PORTB, 7}, // B7 27 - {&DDRA, &PINA, &PORTA, 0}, // A0 28 - {&DDRA, &PINA, &PORTA, 1}, // A1 29 - {&DDRA, &PINA, &PORTA, 2}, // A2 30 - {&DDRA, &PINA, &PORTA, 3}, // A3 31 - {&DDRA, &PINA, &PORTA, 4}, // A4 32 - {&DDRA, &PINA, &PORTA, 5}, // A5 33 - {&DDRA, &PINA, &PORTA, 6}, // A6 34 - {&DDRA, &PINA, &PORTA, 7}, // A7 35 - {&DDRE, &PINE, &PORTE, 4}, // E4 36 - {&DDRE, &PINE, &PORTE, 5}, // E5 37 - {&DDRF, &PINF, &PORTF, 0}, // F0 38 - {&DDRF, &PINF, &PORTF, 1}, // F1 39 - {&DDRF, &PINF, &PORTF, 2}, // F2 40 - {&DDRF, &PINF, &PORTF, 3}, // F3 41 - {&DDRF, &PINF, &PORTF, 4}, // F4 42 - {&DDRF, &PINF, &PORTF, 5}, // F5 43 - {&DDRF, &PINF, &PORTF, 6}, // F6 44 - {&DDRF, &PINF, &PORTF, 7} // F7 45 -}; -//------------------------------------------------------------------------------ -#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -// 168 and 328 Arduinos - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 18; -uint8_t const SCL_PIN = 19; - -// SPI port -uint8_t const SS_PIN = 10; -uint8_t const MOSI_PIN = 11; -uint8_t const MISO_PIN = 12; -uint8_t const SCK_PIN = 13; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRB, &PINB, &PORTB, 0}, // B0 8 - {&DDRB, &PINB, &PORTB, 1}, // B1 9 - {&DDRB, &PINB, &PORTB, 2}, // B2 10 - {&DDRB, &PINB, &PORTB, 3}, // B3 11 - {&DDRB, &PINB, &PORTB, 4}, // B4 12 - {&DDRB, &PINB, &PORTB, 5}, // B5 13 - {&DDRC, &PINC, &PORTC, 0}, // C0 14 - {&DDRC, &PINC, &PORTC, 1}, // C1 15 - {&DDRC, &PINC, &PORTC, 2}, // C2 16 - {&DDRC, &PINC, &PORTC, 3}, // C3 17 - {&DDRC, &PINC, &PORTC, 4}, // C4 18 - {&DDRC, &PINC, &PORTC, 5} // C5 19 -}; -#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -//------------------------------------------------------------------------------ -static const uint8_t digitalPinCount = sizeof(digitalPinMap) / sizeof(pin_map_t); - -uint8_t badPinNumber(void) -__attribute__((error("Pin number is too large or not a constant"))); - -static inline __attribute__((always_inline)) -uint8_t getPinMode(uint8_t pin) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1; - } else { - return badPinNumber(); - } -} -static inline __attribute__((always_inline)) -void setPinMode(uint8_t pin, uint8_t mode) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - if (mode) { - *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit; - } else { - *digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit); - } - } else { - badPinNumber(); - } -} -static inline __attribute__((always_inline)) -uint8_t fastDigitalRead(uint8_t pin) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1; - } else { - return badPinNumber(); - } -} -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, uint8_t value) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - if (value) { - *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit; - } else { - *digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit); - } - } else { - badPinNumber(); - } -} -#endif // Sd2PinMap_h - -#elif defined (__CPU_ARC__) - -#if defined (__ARDUINO_ARC__) - // Two Wire (aka I2C) ports - uint8_t const SDA_PIN = 18; - uint8_t const SCL_PIN = 19; - - // SPI port - uint8_t const SS_PIN = 10; - uint8_t const MOSI_PIN = 11; - uint8_t const MISO_PIN = 12; - uint8_t const SCK_PIN = 13; - -#endif // Arduino ARC - -#else -#error Architecture or board not supported. -#endif diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFat.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFat.h deleted file mode 100644 index 1c73615..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFat.h +++ /dev/null @@ -1,641 +0,0 @@ -/* Arduino SdFat Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino SdFat Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino SdFat Library. If not, see - . -*/ -#ifndef SdFat_h -#define SdFat_h -/** - \file - SdFile and SdVolume classes -*/ -#if defined (__AVR__) || defined (__CPU_ARC__) - #include -#endif -#include "Sd2Card.h" -#include "FatStructs.h" -#include -//------------------------------------------------------------------------------ -/** - Allow use of deprecated functions if non-zero -*/ -#define ALLOW_DEPRECATED_FUNCTIONS 1 -//------------------------------------------------------------------------------ -// forward declaration since SdVolume is used in SdFile -class SdVolume; -//============================================================================== -// SdFile class - -#ifdef O_RDONLY //ARDUINO_ARCH_MBED - #undef O_READ - #undef O_RDONLY - #undef O_WRITE - #undef O_WRONLY - #undef O_RDWR - #undef O_ACCMODE - #undef O_APPEND - #undef O_SYNC - #undef O_CREAT - #undef O_EXCL - #undef O_TRUNC -#endif - -// flags for ls() -/** ls() flag to print modify date */ -uint8_t const LS_DATE = 1; -/** ls() flag to print file size */ -uint8_t const LS_SIZE = 2; -/** ls() flag for recursive list of subdirectories */ -uint8_t const LS_R = 4; - -// use the gnu style oflag in open() -/** open() oflag for reading */ -uint8_t const O_READ = 0X01; -/** open() oflag - same as O_READ */ -uint8_t const O_RDONLY = O_READ; -/** open() oflag for write */ -uint8_t const O_WRITE = 0X02; -/** open() oflag - same as O_WRITE */ -uint8_t const O_WRONLY = O_WRITE; -/** open() oflag for reading and writing */ -uint8_t const O_RDWR = (O_READ | O_WRITE); -/** open() oflag mask for access modes */ -uint8_t const O_ACCMODE = (O_READ | O_WRITE); -/** The file offset shall be set to the end of the file prior to each write. */ -uint8_t const O_APPEND = 0X04; -/** synchronous writes - call sync() after each write */ -uint8_t const O_SYNC = 0X08; -/** create the file if nonexistent */ -uint8_t const O_CREAT = 0X10; -/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ -uint8_t const O_EXCL = 0X20; -/** truncate the file to zero length */ -uint8_t const O_TRUNC = 0X40; - -// flags for timestamp -/** set the file's last access date */ -uint8_t const T_ACCESS = 1; -/** set the file's creation date and time */ -uint8_t const T_CREATE = 2; -/** Set the file's write date and time */ -uint8_t const T_WRITE = 4; -// values for type_ -/** This SdFile has not been opened. */ -uint8_t const FAT_FILE_TYPE_CLOSED = 0; -/** SdFile for a file */ -uint8_t const FAT_FILE_TYPE_NORMAL = 1; -/** SdFile for a FAT16 root directory */ -uint8_t const FAT_FILE_TYPE_ROOT16 = 2; -/** SdFile for a FAT32 root directory */ -uint8_t const FAT_FILE_TYPE_ROOT32 = 3; -/** SdFile for a subdirectory */ -uint8_t const FAT_FILE_TYPE_SUBDIR = 4; -/** Test value for directory type */ -uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; - -/** date field for FAT directory entry */ -static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { - return (year - 1980) << 9 | month << 5 | day; -} -/** year part of FAT directory date field */ -static inline uint16_t FAT_YEAR(uint16_t fatDate) { - return 1980 + (fatDate >> 9); -} -/** month part of FAT directory date field */ -static inline uint8_t FAT_MONTH(uint16_t fatDate) { - return (fatDate >> 5) & 0XF; -} -/** day part of FAT directory date field */ -static inline uint8_t FAT_DAY(uint16_t fatDate) { - return fatDate & 0X1F; -} -/** time field for FAT directory entry */ -static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { - return hour << 11 | minute << 5 | second >> 1; -} -/** hour part of FAT directory time field */ -static inline uint8_t FAT_HOUR(uint16_t fatTime) { - return fatTime >> 11; -} -/** minute part of FAT directory time field */ -static inline uint8_t FAT_MINUTE(uint16_t fatTime) { - return (fatTime >> 5) & 0X3F; -} -/** second part of FAT directory time field */ -static inline uint8_t FAT_SECOND(uint16_t fatTime) { - return 2 * (fatTime & 0X1F); -} -/** Default date for file timestamps is 1 Jan 2000 */ -uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; -/** Default time for file timestamp is 1 am */ -uint16_t const FAT_DEFAULT_TIME = (1 << 11); -//------------------------------------------------------------------------------ -/** - \class SdFile - \brief Access FAT16 and FAT32 files on SD and SDHC cards. -*/ -class SdFile : public Print { - public: - /** Create an instance of SdFile. */ - SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} - /** - writeError is set to true if an error occurs during a write(). - Set writeError to false before calling print() and/or write() and check - for true after calls to print() and/or write(). - */ - //bool writeError; - /** - Cancel unbuffered reads for this file. - See setUnbufferedRead() - */ - void clearUnbufferedRead(void) { - flags_ &= ~F_FILE_UNBUFFERED_READ; - } - uint8_t close(void); - uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - uint8_t createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size); - /** \return The current cluster number for a file or directory. */ - uint32_t curCluster(void) const { - return curCluster_; - } - /** \return The current position for a file or directory. */ - uint32_t curPosition(void) const { - return curPosition_; - } - /** - Set the date/time callback function - - \param[in] dateTime The user's call back function. The callback - function is of the form: - - \code - void dateTime(uint16_t* date, uint16_t* time) { - uint16_t year; - uint8_t month, day, hour, minute, second; - - // User gets date and time from GPS or real-time clock here - - // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); - - // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); - } - \endcode - - Sets the function that is called when a file is created or when - a file's directory entry is modified by sync(). All timestamps, - access, creation, and modify, are set when a file is created. - sync() maintains the last access date and last modify date/time. - - See the timestamp() function. - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)) { - dateTime_ = dateTime; - } - /** - Cancel the date/time callback function. - */ - static void dateTimeCallbackCancel(void) { - // use explicit zero since NULL is not defined for Sanguino - dateTime_ = 0; - } - /** \return Address of the block that contains this file's directory. */ - uint32_t dirBlock(void) const { - return dirBlock_; - } - uint8_t dirEntry(dir_t* dir); - /** \return Index of this file's directory in the block dirBlock. */ - uint8_t dirIndex(void) const { - return dirIndex_; - } - static void dirName(const dir_t& dir, char* name); - /** \return The total number of bytes in a file or directory. */ - uint32_t fileSize(void) const { - return fileSize_; - } - /** \return The first cluster number for a file or directory. */ - uint32_t firstCluster(void) const { - return firstCluster_; - } - /** \return True if this is a SdFile for a directory else false. */ - uint8_t isDir(void) const { - return type_ >= FAT_FILE_TYPE_MIN_DIR; - } - /** \return True if this is a SdFile for a file else false. */ - uint8_t isFile(void) const { - return type_ == FAT_FILE_TYPE_NORMAL; - } - /** \return True if this is a SdFile for an open file/directory else false. */ - uint8_t isOpen(void) const { - return type_ != FAT_FILE_TYPE_CLOSED; - } - /** \return True if this is a SdFile for a subdirectory else false. */ - uint8_t isSubDir(void) const { - return type_ == FAT_FILE_TYPE_SUBDIR; - } - /** \return True if this is a SdFile for the root directory. */ - uint8_t isRoot(void) const { - return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; - } - void ls(uint8_t flags = 0, uint8_t indent = 0); - uint8_t makeDir(SdFile* dir, const char* dirName); - uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag); - uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag); - - uint8_t openRoot(SdVolume* vol); - static void printDirName(const dir_t& dir, uint8_t width); - static void printFatDate(uint16_t fatDate); - static void printFatTime(uint16_t fatTime); - static void printTwoDigits(uint8_t v); - /** - Read the next byte from a file. - - \return For success read returns the next byte in the file as an int. - If an error occurs or end of file is reached -1 is returned. - */ - int16_t read(void) { - uint8_t b; - return read(&b, 1) == 1 ? b : -1; - } - int16_t read(void* buf, uint16_t nbyte); - int8_t readDir(dir_t* dir); - static uint8_t remove(SdFile* dirFile, const char* fileName); - uint8_t remove(void); - /** Set the file's current position to zero. */ - void rewind(void) { - curPosition_ = curCluster_ = 0; - } - uint8_t rmDir(void); - uint8_t rmRfStar(void); - /** Set the files position to current position + \a pos. See seekSet(). */ - uint8_t seekCur(uint32_t pos) { - return seekSet(curPosition_ + pos); - } - /** - Set the files current position to end of file. Useful to position - a file for append. See seekSet(). - */ - uint8_t seekEnd(void) { - return seekSet(fileSize_); - } - uint8_t seekSet(uint32_t pos); - /** - Use unbuffered reads to access this file. Used with Wave - Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. - - Not recommended for normal applications. - */ - void setUnbufferedRead(void) { - if (isFile()) { - flags_ |= F_FILE_UNBUFFERED_READ; - } - } - uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, - uint8_t hour, uint8_t minute, uint8_t second); - uint8_t sync(uint8_t blocking = 1); - /** Type of this SdFile. You should use isFile() or isDir() instead of type() - if possible. - - \return The file or directory type. - */ - uint8_t type(void) const { - return type_; - } - uint8_t truncate(uint32_t size); - /** \return Unbuffered read flag. */ - uint8_t unbufferedRead(void) const { - return flags_ & F_FILE_UNBUFFERED_READ; - } - /** \return SdVolume that contains this file. */ - SdVolume* volume(void) const { - return vol_; - } - size_t write(uint8_t b); - size_t write(const void* buf, uint16_t nbyte); - size_t write(const char* str); - #ifdef __AVR__ - void write_P(PGM_P str); - void writeln_P(PGM_P str); - #endif - int availableForWrite(void); - //------------------------------------------------------------------------------ - #if ALLOW_DEPRECATED_FUNCTIONS - // Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: - uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - */ - uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT - return contiguousRange(&bgnBlock, &endBlock); - } - /** \deprecated Use: - uint8_t SdFile::createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size) - */ - uint8_t createContiguous(SdFile& dirFile, // NOLINT - const char* fileName, uint32_t size) { - return createContiguous(&dirFile, fileName, size); - } - - /** - \deprecated Use: - static void SdFile::dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)); - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT - oldDateTime_ = dateTime; - dateTime_ = dateTime ? oldToNew : 0; - } - /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ - uint8_t dirEntry(dir_t& dir) { - return dirEntry(&dir); // NOLINT - } - /** \deprecated Use: - uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); - */ - uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT - return makeDir(&dir, dirName); - } - /** \deprecated Use: - uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, // NOLINT - const char* fileName, uint8_t oflag) { - return open(&dirFile, fileName, oflag); - } - /** \deprecated Do not use in new apps */ - uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT - return open(dirFile, fileName, O_RDWR); - } - /** \deprecated Use: - uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT - return open(&dirFile, index, oflag); - } - /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ - uint8_t openRoot(SdVolume& vol) { - return openRoot(&vol); // NOLINT - } - - /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ - int8_t readDir(dir_t& dir) { - return readDir(&dir); // NOLINT - } - /** \deprecated Use: - static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); - */ - static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT - return remove(&dirFile, fileName); - } - //------------------------------------------------------------------------------ - // rest are private - private: - static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT - static void oldToNew(uint16_t* date, uint16_t* time) { - uint16_t d; - uint16_t t; - oldDateTime_(d, t); - *date = d; - *time = t; - } - #endif // ALLOW_DEPRECATED_FUNCTIONS - private: - // bits defined in flags_ - // should be 0XF - static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); - // available bits - static uint8_t const F_FILE_NON_BLOCKING_WRITE = 0X10; - // a new cluster was added to the file - static uint8_t const F_FILE_CLUSTER_ADDED = 0X20; - // use unbuffered SD read - static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; - // sync of directory entry required - static uint8_t const F_FILE_DIR_DIRTY = 0X80; - - // make sure F_OFLAG is ok - #if ((F_FILE_NON_BLOCKING_WRITE | F_FILE_CLUSTER_ADDED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG) -#error flags_ bits conflict - #endif // flags_ bits - - // private data - uint8_t flags_; // See above for definition of flags_ bits - uint8_t type_; // type of file see above for values - uint32_t curCluster_; // cluster for current file position - uint32_t curPosition_; // current file position in bytes from beginning - uint32_t dirBlock_; // SD block that contains directory entry for file - uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF - uint32_t fileSize_; // file size in bytes - uint32_t firstCluster_; // first cluster of file - SdVolume* vol_; // volume where file is located - - // private functions - uint8_t addCluster(void); - uint8_t addDirCluster(void); - dir_t* cacheDirEntry(uint8_t action); - static void (*dateTime_)(uint16_t* date, uint16_t* time); - static uint8_t make83Name(const char* str, uint8_t* name); - uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); - dir_t* readDirCache(void); -}; -//============================================================================== -// SdVolume class -/** - \brief Cache for an SD data block -*/ -union cache_t { - /** Used to access cached file data blocks. */ - uint8_t data[512]; - /** Used to access cached FAT16 entries. */ - uint16_t fat16[256]; - /** Used to access cached FAT32 entries. */ - uint32_t fat32[128]; - /** Used to access cached directory entries. */ - dir_t dir[16]; - /** Used to access a cached MasterBoot Record. */ - mbr_t mbr; - /** Used to access to a cached FAT boot sector. */ - fbs_t fbs; -}; -//------------------------------------------------------------------------------ -/** - \class SdVolume - \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. -*/ -class SdVolume { - public: - /** Create an instance of SdVolume */ - SdVolume(void) : allocSearchStart_(2), fatType_(0) {} - /** Clear the cache and returns a pointer to the cache. Used by the WaveRP - recorder to do raw write to the SD card. Not for normal apps. - */ - static uint8_t* cacheClear(void) { - cacheFlush(); - cacheBlockNumber_ = 0XFFFFFFFF; - return cacheBuffer_.data; - } - /** - Initialize a FAT volume. Try partition one first then try super - floppy format. - - \param[in] dev The Sd2Card where the volume is located. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. Reasons for - failure include not finding a valid partition, not finding a valid - FAT file system or an I/O error. - */ - uint8_t init(Sd2Card* dev) { - return init(dev, 1) ? true : init(dev, 0); - } - uint8_t init(Sd2Card* dev, uint8_t part); - - // inline functions that return volume info - /** \return The volume's cluster size in blocks. */ - uint8_t blocksPerCluster(void) const { - return blocksPerCluster_; - } - /** \return The number of blocks in one FAT. */ - uint32_t blocksPerFat(void) const { - return blocksPerFat_; - } - /** \return The total number of clusters in the volume. */ - uint32_t clusterCount(void) const { - return clusterCount_; - } - /** \return The shift count required to multiply by blocksPerCluster. */ - uint8_t clusterSizeShift(void) const { - return clusterSizeShift_; - } - /** \return The logical block number for the start of file data. */ - uint32_t dataStartBlock(void) const { - return dataStartBlock_; - } - /** \return The number of FAT structures on the volume. */ - uint8_t fatCount(void) const { - return fatCount_; - } - /** \return The logical block number for the start of the first FAT. */ - uint32_t fatStartBlock(void) const { - return fatStartBlock_; - } - /** \return The FAT type of the volume. Values are 12, 16 or 32. */ - uint8_t fatType(void) const { - return fatType_; - } - /** \return The number of entries in the root directory for FAT16 volumes. */ - uint32_t rootDirEntryCount(void) const { - return rootDirEntryCount_; - } - /** \return The logical block number for the start of the root directory - on FAT16 volumes or the first cluster number on FAT32 volumes. */ - uint32_t rootDirStart(void) const { - return rootDirStart_; - } - /** return a pointer to the Sd2Card object for this volume */ - static Sd2Card* sdCard(void) { - return sdCard_; - } - //------------------------------------------------------------------------------ - #if ALLOW_DEPRECATED_FUNCTIONS - // Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ - uint8_t init(Sd2Card& dev) { - return init(&dev); // NOLINT - } - - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ - uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT - return init(&dev, part); - } - #endif // ALLOW_DEPRECATED_FUNCTIONS - //------------------------------------------------------------------------------ - private: - // Allow SdFile access to SdVolume private data. - friend class SdFile; - - // value for action argument in cacheRawBlock to indicate read from cache - static uint8_t const CACHE_FOR_READ = 0; - // value for action argument in cacheRawBlock to indicate cache dirty - static uint8_t const CACHE_FOR_WRITE = 1; - - static cache_t cacheBuffer_; // 512 byte cache for device blocks - static uint32_t cacheBlockNumber_; // Logical number of block in the cache - static Sd2Card* sdCard_; // Sd2Card object for cache - static uint8_t cacheDirty_; // cacheFlush() will write block if true - static uint32_t cacheMirrorBlock_; // block number for mirror FAT - // - uint32_t allocSearchStart_; // start cluster for alloc search - uint8_t blocksPerCluster_; // cluster size in blocks - uint32_t blocksPerFat_; // FAT size in blocks - uint32_t clusterCount_; // clusters in one FAT - uint8_t clusterSizeShift_; // shift to convert cluster count to block count - uint32_t dataStartBlock_; // first data block number - uint8_t fatCount_; // number of FATs on volume - uint32_t fatStartBlock_; // start block for first FAT - uint8_t fatType_; // volume type (12, 16, OR 32) - uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir - uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 - //---------------------------------------------------------------------------- - uint8_t allocContiguous(uint32_t count, uint32_t* curCluster); - uint8_t blockOfCluster(uint32_t position) const { - return (position >> 9) & (blocksPerCluster_ - 1); - } - uint32_t clusterStartBlock(uint32_t cluster) const { - return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_); - } - uint32_t blockNumber(uint32_t cluster, uint32_t position) const { - return clusterStartBlock(cluster) + blockOfCluster(position); - } - static uint8_t cacheFlush(uint8_t blocking = 1); - static uint8_t cacheMirrorBlockFlush(uint8_t blocking); - static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); - static void cacheSetDirty(void) { - cacheDirty_ |= CACHE_FOR_WRITE; - } - static uint8_t cacheZeroBlock(uint32_t blockNumber); - uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const; - uint8_t fatGet(uint32_t cluster, uint32_t* value) const; - uint8_t fatPut(uint32_t cluster, uint32_t value); - uint8_t fatPutEOC(uint32_t cluster) { - return fatPut(cluster, 0x0FFFFFFF); - } - uint8_t freeChain(uint32_t cluster); - uint8_t isEOC(uint32_t cluster) const { - return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); - } - uint8_t readBlock(uint32_t block, uint8_t* dst) { - return sdCard_->readBlock(block, dst); - } - uint8_t readData(uint32_t block, uint16_t offset, - uint16_t count, uint8_t* dst) { - return sdCard_->readData(block, offset, count, dst); - } - uint8_t writeBlock(uint32_t block, const uint8_t* dst, uint8_t blocking = 1) { - return sdCard_->writeBlock(block, dst, blocking); - } - uint8_t isBusy(void) { - return sdCard_->isBusy(); - } - uint8_t isCacheMirrorBlockDirty(void) { - return (cacheMirrorBlock_ != 0); - } -}; -#endif // SdFat_h diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatUtil.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatUtil.h deleted file mode 100644 index 2fb6289..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatUtil.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Arduino SdFat Library - Copyright (C) 2008 by William Greiman - - This file is part of the Arduino SdFat Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino SdFat Library. If not, see - . -*/ -#ifndef SdFatUtil_h -#define SdFatUtil_h -/** - \file - Useful utility functions. -*/ -#include -#ifdef __AVR__ - #include - /** Store and print a string in flash memory.*/ - #define PgmPrint(x) SerialPrint_P(PSTR(x)) - /** Store and print a string in flash memory followed by a CR/LF.*/ - #define PgmPrintln(x) SerialPrintln_P(PSTR(x)) - /** Defined so doxygen works for function definitions. */ -#endif -#define NOINLINE __attribute__((noinline,unused)) -#define UNUSEDOK __attribute__((unused)) -//------------------------------------------------------------------------------ -/** Return the number of bytes currently free in RAM. */ -static UNUSEDOK int FreeRam(void) { - extern int __bss_end; - extern int* __brkval; - int free_memory; - if (reinterpret_cast(__brkval) == 0) { - // if no heap use from end of bss section - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(&__bss_end); - } else { - // use from top of stack to heap - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(__brkval); - } - return free_memory; -} -#ifdef __AVR__ -//------------------------------------------------------------------------------ -/** - %Print a string in flash memory to the serial port. - - \param[in] str Pointer to string stored in flash memory. -*/ -static NOINLINE void SerialPrint_P(PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) { - Serial.write(c); - } -} -//------------------------------------------------------------------------------ -/** - %Print a string in flash memory followed by a CR/LF. - - \param[in] str Pointer to string stored in flash memory. -*/ -static NOINLINE void SerialPrintln_P(PGM_P str) { - SerialPrint_P(str); - Serial.println(); -} -#endif // __AVR__ -#endif // #define SdFatUtil_h diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatmainpage.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatmainpage.h deleted file mode 100644 index 0a42e85..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatmainpage.h +++ /dev/null @@ -1,202 +0,0 @@ -/* Arduino SdFat Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino SdFat Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino SdFat Library. If not, see - . -*/ - -/** - \mainpage Arduino SdFat Library -
Copyright © 2009 by William Greiman -
- - \section Intro Introduction - The Arduino SdFat Library is a minimal implementation of FAT16 and FAT32 - file systems on SD flash memory cards. Standard SD and high capacity - SDHC cards are supported. - - The SdFat only supports short 8.3 names. - - The main classes in SdFat are Sd2Card, SdVolume, and SdFile. - - The Sd2Card class supports access to standard SD cards and SDHC cards. Most - applications will only need to call the Sd2Card::init() member function. - - The SdVolume class supports FAT16 and FAT32 partitions. Most applications - will only need to call the SdVolume::init() member function. - - The SdFile class provides file access functions such as open(), read(), - remove(), write(), close() and sync(). This class supports access to the root - directory and subdirectories. - - A number of example are provided in the SdFat/examples folder. These were - developed to test SdFat and illustrate its use. - - SdFat was developed for high speed data recording. SdFat was used to implement - an audio record/play class, WaveRP, for the Adafruit Wave Shield. This - application uses special Sd2Card calls to write to contiguous files in raw mode. - These functions reduce write latency so that audio can be recorded with the - small amount of RAM in the Arduino. - - \section SDcard SD\SDHC Cards - - Arduinos access SD cards using the cards SPI protocol. PCs, Macs, and - most consumer devices use the 4-bit parallel SD protocol. A card that - functions well on A PC or Mac may not work well on the Arduino. - - Most cards have good SPI read performance but cards vary widely in SPI - write performance. Write performance is limited by how efficiently the - card manages internal erase/remapping operations. The Arduino cannot - optimize writes to reduce erase operations because of its limit RAM. - - SanDisk cards generally have good write performance. They seem to have - more internal RAM buffering than other cards and therefore can limit - the number of flash erase operations that the Arduino forces due to its - limited RAM. - - \section Hardware Hardware Configuration - - SdFat was developed using an - Adafruit Industries - Wave Shield. - - The hardware interface to the SD card should not use a resistor based level - shifter. SdFat sets the SPI bus frequency to 8 MHz which results in signal - rise times that are too slow for the edge detectors in many newer SD card - controllers when resistor voltage dividers are used. - - The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the - 74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield - uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the - 74LCX245. - - If you are using a resistor based level shifter and are having problems try - setting the SPI bus frequency to 4 MHz. This can be done by using - card.init(SPI_HALF_SPEED) to initialize the SD card. - - \section comment Bugs and Comments - - If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net. - - \section SdFatClass SdFat Usage - - SdFat uses a slightly restricted form of short names. - Only printable ASCII characters are supported. No characters with code point - values greater than 127 are allowed. Space is not allowed even though space - was allowed in the API of early versions of DOS. - - Short names are limited to 8 characters followed by an optional period (.) - and extension of up to 3 characters. The characters may be any combination - of letters and digits. The following special characters are also allowed: - - $ % ' - _ @ ~ ` ! ( ) { } ^ # & - - Short names are always converted to upper case and their original case - value is lost. - - \note - The Arduino Print class uses character - at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink - function to control when data is written to the SD card. - - \par - An application which writes to a file using \link Print::print() print()\endlink, - \link Print::println() println() \endlink - or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink - at the appropriate time to force data and directory information to be written - to the SD Card. Data and directory information are also written to the SD card - when \link SdFile::close() close() \endlink is called. - - \par - Applications must use care calling \link SdFile::sync() sync() \endlink - since 2048 bytes of I/O is required to update file and - directory information. This includes writing the current data block, reading - the block that contains the directory entry for update, writing the directory - block back and reading back the current data block. - - It is possible to open a file with two or more instances of SdFile. A file may - be corrupted if data is written to the file by more than one instance of SdFile. - - \section HowTo How to format SD Cards as FAT Volumes - - You should use a freshly formatted SD card for best performance. FAT - file systems become slower if many files have been created and deleted. - This is because the directory entry for a deleted file is marked as deleted, - but is not deleted. When a new file is created, these entries must be scanned - before creating the file, a flaw in the FAT design. Also files can become - fragmented which causes reads and writes to be slower. - - Microsoft operating systems support removable media formatted with a - Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector - in block zero. - - Microsoft operating systems expect MBR formatted removable media - to have only one partition. The first partition should be used. - - Microsoft operating systems do not support partitioning SD flash cards. - If you erase an SD card with a program like KillDisk, Most versions of - Windows will format the card as a super floppy. - - The best way to restore an SD card's format is to use SDFormatter - which can be downloaded from: - - http://www.sdcard.org/consumers/formatter/ - - SDFormatter aligns flash erase boundaries with file - system structures which reduces write latency and file system overhead. - - SDFormatter does not have an option for FAT type so it may format - small cards as FAT12. - - After the MBR is restored by SDFormatter you may need to reformat small - cards that have been formatted FAT12 to force the volume type to be FAT16. - - If you reformat the SD card with an OS utility, choose a cluster size that - will result in: - - 4084 < CountOfClusters && CountOfClusters < 65525 - - The volume will then be FAT16. - - If you are formatting an SD card on OS X or Linux, be sure to use the first - partition. Format this partition with a cluster count in above range. - - \section References References - - Adafruit Industries: - - http://www.adafruit.com/ - - http://www.ladyada.net/make/waveshield/ - - The Arduino site: - - http://www.arduino.cc/ - - For more information about FAT file systems see: - - http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx - - For information about using SD cards as SPI devices see: - - http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf - - The ATmega328 datasheet: - - http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf - - -*/ diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFile.cpp b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFile.cpp deleted file mode 100644 index 70be4b5..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdFile.cpp +++ /dev/null @@ -1,1527 +0,0 @@ -/* Arduino SdFat Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino SdFat Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino SdFat Library. If not, see - . -*/ -#include "SdFat.h" -#ifdef __AVR__ - #include -#endif -#include -//------------------------------------------------------------------------------ -// callback function for date/time -void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL; - -#if ALLOW_DEPRECATED_FUNCTIONS - // suppress cpplint warnings with NOLINT comment - void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL; // NOLINT -#endif // ALLOW_DEPRECATED_FUNCTIONS -//------------------------------------------------------------------------------ -// add a cluster to a file -uint8_t SdFile::addCluster() { - if (!vol_->allocContiguous(1, &curCluster_)) { - return false; - } - - // if first cluster of file link to directory entry - if (firstCluster_ == 0) { - firstCluster_ = curCluster_; - flags_ |= F_FILE_DIR_DIRTY; - } - flags_ |= F_FILE_CLUSTER_ADDED; - return true; -} -//------------------------------------------------------------------------------ -// Add a cluster to a directory file and zero the cluster. -// return with first block of cluster in the cache -uint8_t SdFile::addDirCluster(void) { - if (!addCluster()) { - return false; - } - - // zero data in cluster insure first cluster is in cache - uint32_t block = vol_->clusterStartBlock(curCluster_); - for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) { - if (!SdVolume::cacheZeroBlock(block + i - 1)) { - return false; - } - } - // Increase directory file size by cluster size - fileSize_ += 512UL << vol_->clusterSizeShift_; - return true; -} -//------------------------------------------------------------------------------ -// cache a file's directory entry -// return pointer to cached entry or null for failure -dir_t* SdFile::cacheDirEntry(uint8_t action) { - if (!SdVolume::cacheRawBlock(dirBlock_, action)) { - return NULL; - } - return SdVolume::cacheBuffer_.dir + dirIndex_; -} -//------------------------------------------------------------------------------ -/** - Close a file and force cached data and directory information - to be written to the storage device. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include no file is open or an I/O error. -*/ -uint8_t SdFile::close(void) { - if (!sync()) { - return false; - } - type_ = FAT_FILE_TYPE_CLOSED; - return true; -} -//------------------------------------------------------------------------------ -/** - Check for contiguous file and return its raw block range. - - \param[out] bgnBlock the first block address for the file. - \param[out] endBlock the last block address for the file. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include file is not contiguous, file has zero length - or an I/O error occurred. -*/ -uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { - // error if no blocks - if (firstCluster_ == 0) { - return false; - } - - for (uint32_t c = firstCluster_; ; c++) { - uint32_t next; - if (!vol_->fatGet(c, &next)) { - return false; - } - - // check for contiguous - if (next != (c + 1)) { - // error if not end of chain - if (!vol_->isEOC(next)) { - return false; - } - *bgnBlock = vol_->clusterStartBlock(firstCluster_); - *endBlock = vol_->clusterStartBlock(c) - + vol_->blocksPerCluster_ - 1; - return true; - } - } -} -//------------------------------------------------------------------------------ -/** - Create and open a new contiguous file of a specified size. - - \note This function only supports short DOS 8.3 names. - See open() for more information. - - \param[in] dirFile The directory where the file will be created. - \param[in] fileName A valid DOS 8.3 file name. - \param[in] size The desired file size. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include \a fileName contains - an invalid DOS 8.3 file name, the FAT volume has not been initialized, - a file is already open, the file already exists, the root - directory is full or an I/O error. - -*/ -uint8_t SdFile::createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size) { - // don't allow zero length file - if (size == 0) { - return false; - } - if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) { - return false; - } - - // calculate number of clusters needed - uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; - - // allocate clusters - if (!vol_->allocContiguous(count, &firstCluster_)) { - remove(); - return false; - } - fileSize_ = size; - - // insure sync() will update dir entry - flags_ |= F_FILE_DIR_DIRTY; - return sync(); -} -//------------------------------------------------------------------------------ -/** - Return a files directory entry - - \param[out] dir Location for return of the files directory entry. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t SdFile::dirEntry(dir_t* dir) { - // make sure fields on SD are correct - if (!sync()) { - return false; - } - - // read entry - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); - if (!p) { - return false; - } - - // copy to caller's struct - memcpy(dir, p, sizeof(dir_t)); - return true; -} -//------------------------------------------------------------------------------ -/** - Format the name field of \a dir into the 13 byte array - \a name in standard 8.3 short name format. - - \param[in] dir The directory structure containing the name. - \param[out] name A 13 byte char array for the formatted name. -*/ -void SdFile::dirName(const dir_t& dir, char* name) { - uint8_t j = 0; - for (uint8_t i = 0; i < 11; i++) { - if (dir.name[i] == ' ') { - continue; - } - if (i == 8) { - name[j++] = '.'; - } - name[j++] = dir.name[i]; - } - name[j] = 0; -} -//------------------------------------------------------------------------------ -/** List directory contents to Serial. - - \param[in] flags The inclusive OR of - - LS_DATE - %Print file modification date - - LS_SIZE - %Print file size. - - LS_R - Recursive list of subdirectories. - - \param[in] indent Amount of space before file name. Used for recursive - list to indicate subdirectory level. -*/ -void SdFile::ls(uint8_t flags, uint8_t indent) { - dir_t* p; - - rewind(); - while ((p = readDirCache())) { - // done if past last used entry - if (p->name[0] == DIR_NAME_FREE) { - break; - } - - // skip deleted entry and entries for . and .. - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { - continue; - } - - // only list subdirectories and files - if (!DIR_IS_FILE_OR_SUBDIR(p)) { - continue; - } - - // print any indent spaces - for (int8_t i = 0; i < indent; i++) { - Serial.print(' '); - } - - // print file name with possible blank fill - printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0); - - // print modify date/time if requested - if (flags & LS_DATE) { - printFatDate(p->lastWriteDate); - Serial.print(' '); - printFatTime(p->lastWriteTime); - } - // print size if requested - if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) { - Serial.print(' '); - Serial.print(p->fileSize); - } - Serial.println(); - - // list subdirectory content if requested - if ((flags & LS_R) && DIR_IS_SUBDIR(p)) { - uint16_t index = curPosition() / 32 - 1; - SdFile s; - if (s.open(this, index, O_READ)) { - s.ls(flags, indent + 2); - } - seekSet(32 * (index + 1)); - } - } -} -//------------------------------------------------------------------------------ -// format directory name field from a 8.3 name string -uint8_t SdFile::make83Name(const char* str, uint8_t* name) { - uint8_t c; - uint8_t n = 7; // max index for part before dot - uint8_t i = 0; - // blank fill name and extension - while (i < 11) { - name[i++] = ' '; - } - i = 0; - while ((c = *str++) != '\0') { - if (c == '.') { - if (n == 10) { - return false; // only one dot allowed - } - n = 10; // max index for full 8.3 name - i = 8; // place for extension - } else { - // illegal FAT characters - uint8_t b; - #if defined(__AVR__) - PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); - while ((b = pgm_read_byte(p++))) if (b == c) { - return false; - } - #elif defined(__arm__) - const uint8_t valid[] = "|<>^+=?/[];,*\"\\"; - const uint8_t *p = valid; - while ((b = *p++)) if (b == c) { - return false; - } - #endif - // check size and only allow ASCII printable characters - if (i > n || c < 0X21 || c > 0X7E) { - return false; - } - // only upper case allowed in 8.3 names - convert lower to upper - name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); - } - } - // must have a file name, extension is optional - return name[0] != ' '; -} -//------------------------------------------------------------------------------ -/** Make a new directory. - - \param[in] dir An open SdFat instance for the directory that will containing - the new directory. - - \param[in] dirName A valid 8.3 DOS name for the new directory. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include this SdFile is already open, \a dir is not a - directory, \a dirName is invalid or already exists in \a dir. -*/ -uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { - dir_t d; - - // create a normal file - if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) { - return false; - } - - // convert SdFile to directory - flags_ = O_READ; - type_ = FAT_FILE_TYPE_SUBDIR; - - // allocate and zero first cluster - if (!addDirCluster()) { - return false; - } - - // force entry to SD - if (!sync()) { - return false; - } - - // cache entry - should already be in cache due to sync() call - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!p) { - return false; - } - - // change directory entry attribute - p->attributes = DIR_ATT_DIRECTORY; - - // make entry for '.' - memcpy(&d, p, sizeof(d)); - for (uint8_t i = 1; i < 11; i++) { - d.name[i] = ' '; - } - d.name[0] = '.'; - - // cache block for '.' and '..' - uint32_t block = vol_->clusterStartBlock(firstCluster_); - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { - return false; - } - - // copy '.' to block - memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d)); - - // make entry for '..' - d.name[1] = '.'; - if (dir->isRoot()) { - d.firstClusterLow = 0; - d.firstClusterHigh = 0; - } else { - d.firstClusterLow = dir->firstCluster_ & 0XFFFF; - d.firstClusterHigh = dir->firstCluster_ >> 16; - } - // copy '..' to block - memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d)); - - // set position after '..' - curPosition_ = 2 * sizeof(d); - - // write first block - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - Open a file or directory by name. - - \param[in] dirFile An open SdFat instance for the directory containing the - file to be opened. - - \param[in] fileName A valid 8.3 DOS name for a file to be opened. - - \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive - OR of flags from the following list - - O_READ - Open for reading. - - O_RDONLY - Same as O_READ. - - O_WRITE - Open for writing. - - O_WRONLY - Same as O_WRITE. - - O_RDWR - Open for reading and writing. - - O_APPEND - If set, the file offset shall be set to the end of the - file prior to each write. - - O_CREAT - If the file exists, this flag has no effect except as noted - under O_EXCL below. Otherwise, the file shall be created - - O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. - - O_SYNC - Call sync() after each write. This flag should not be used with - write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. - These functions do character at a time writes so sync() will be called - after each byte. - - O_TRUNC - If the file exists and is a regular file, and the file is - successfully opened and is not read only, its length shall be truncated to 0. - - \note Directory files must be opened read only. Write and truncation is - not allowed for directory files. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include this SdFile is already open, \a difFile is not - a directory, \a fileName is invalid, the file does not exist - or can't be opened in the access mode specified by oflag. -*/ -uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { - uint8_t dname[11]; - dir_t* p; - - // error if already open - if (isOpen()) { - return false; - } - - if (!make83Name(fileName, dname)) { - return false; - } - vol_ = dirFile->vol_; - dirFile->rewind(); - - // bool for empty entry found - uint8_t emptyFound = false; - - // search for file - while (dirFile->curPosition_ < dirFile->fileSize_) { - uint8_t index = 0XF & (dirFile->curPosition_ >> 5); - p = dirFile->readDirCache(); - if (p == NULL) { - return false; - } - - if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { - // remember first empty slot - if (!emptyFound) { - emptyFound = true; - dirIndex_ = index; - dirBlock_ = SdVolume::cacheBlockNumber_; - } - // done if no entries follow - if (p->name[0] == DIR_NAME_FREE) { - break; - } - } else if (!memcmp(dname, p->name, 11)) { - // don't open existing file if O_CREAT and O_EXCL - if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { - return false; - } - - // open found file - return openCachedEntry(0XF & index, oflag); - } - } - // only create file if O_CREAT and O_WRITE - if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) { - return false; - } - - // cache found slot or add cluster if end of file - if (emptyFound) { - p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!p) { - return false; - } - } else { - if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) { - return false; - } - - // add and zero cluster for dirFile - first cluster is in cache for write - if (!dirFile->addDirCluster()) { - return false; - } - - // use first entry in cluster - dirIndex_ = 0; - p = SdVolume::cacheBuffer_.dir; - } - // initialize as empty file - memset(p, 0, sizeof(dir_t)); - memcpy(p->name, dname, 11); - - // set timestamps - if (dateTime_) { - // call user function - dateTime_(&p->creationDate, &p->creationTime); - } else { - // use default date/time - p->creationDate = FAT_DEFAULT_DATE; - p->creationTime = FAT_DEFAULT_TIME; - } - p->lastAccessDate = p->creationDate; - p->lastWriteDate = p->creationDate; - p->lastWriteTime = p->creationTime; - - // force write of entry to SD - if (!SdVolume::cacheFlush()) { - return false; - } - - // open entry in cache - return openCachedEntry(dirIndex_, oflag); -} -//------------------------------------------------------------------------------ -/** - Open a file by index. - - \param[in] dirFile An open SdFat instance for the directory. - - \param[in] index The \a index of the directory entry for the file to be - opened. The value for \a index is (directory file position)/32. - - \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive - OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. - - See open() by fileName for definition of flags and return values. - -*/ -uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { - // error if already open - if (isOpen()) { - return false; - } - - // don't open existing file if O_CREAT and O_EXCL - user call error - if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { - return false; - } - - vol_ = dirFile->vol_; - - // seek to location of entry - if (!dirFile->seekSet(32 * index)) { - return false; - } - - // read entry into cache - dir_t* p = dirFile->readDirCache(); - if (p == NULL) { - return false; - } - - // error if empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_FREE || - p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { - return false; - } - // open cached entry - return openCachedEntry(index & 0XF, oflag); -} -//------------------------------------------------------------------------------ -// open a cached directory entry. Assumes vol_ is initializes -uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { - // location of entry in cache - dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex; - - // write or truncate is an error for a directory or read-only file - if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { - if (oflag & (O_WRITE | O_TRUNC)) { - return false; - } - } - // remember location of directory entry on SD - dirIndex_ = dirIndex; - dirBlock_ = SdVolume::cacheBlockNumber_; - - // copy first cluster number for directory fields - firstCluster_ = (uint32_t)p->firstClusterHigh << 16; - firstCluster_ |= p->firstClusterLow; - - // make sure it is a normal file or subdirectory - if (DIR_IS_FILE(p)) { - fileSize_ = p->fileSize; - type_ = FAT_FILE_TYPE_NORMAL; - } else if (DIR_IS_SUBDIR(p)) { - if (!vol_->chainSize(firstCluster_, &fileSize_)) { - return false; - } - type_ = FAT_FILE_TYPE_SUBDIR; - } else { - return false; - } - // save open flags for read/write - flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND); - - // set to start of file - curCluster_ = 0; - curPosition_ = 0; - - // truncate file to zero length if requested - if (oflag & O_TRUNC) { - return truncate(0); - } - return true; -} -//------------------------------------------------------------------------------ -/** - Open a volume's root directory. - - \param[in] vol The FAT volume containing the root directory to be opened. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include the FAT volume has not been initialized - or it a FAT12 volume. -*/ -uint8_t SdFile::openRoot(SdVolume* vol) { - // error if file is already open - if (isOpen()) { - return false; - } - - if (vol->fatType() == 16) { - type_ = FAT_FILE_TYPE_ROOT16; - firstCluster_ = 0; - fileSize_ = 32 * vol->rootDirEntryCount(); - } else if (vol->fatType() == 32) { - type_ = FAT_FILE_TYPE_ROOT32; - firstCluster_ = vol->rootDirStart(); - if (!vol->chainSize(firstCluster_, &fileSize_)) { - return false; - } - } else { - // volume is not initialized or FAT12 - return false; - } - vol_ = vol; - // read only - flags_ = O_READ; - - // set to start of file - curCluster_ = 0; - curPosition_ = 0; - - // root has no directory entry - dirBlock_ = 0; - dirIndex_ = 0; - return true; -} -//------------------------------------------------------------------------------ -/** %Print the name field of a directory entry in 8.3 format to Serial. - - \param[in] dir The directory structure containing the name. - \param[in] width Blank fill name if length is less than \a width. -*/ -void SdFile::printDirName(const dir_t& dir, uint8_t width) { - uint8_t w = 0; - for (uint8_t i = 0; i < 11; i++) { - if (dir.name[i] == ' ') { - continue; - } - if (i == 8) { - Serial.print('.'); - w++; - } - Serial.write(dir.name[i]); - w++; - } - if (DIR_IS_SUBDIR(&dir)) { - Serial.print('/'); - w++; - } - while (w < width) { - Serial.print(' '); - w++; - } -} -//------------------------------------------------------------------------------ -/** %Print a directory date field to Serial. - - Format is yyyy-mm-dd. - - \param[in] fatDate The date field from a directory entry. -*/ -void SdFile::printFatDate(uint16_t fatDate) { - Serial.print(FAT_YEAR(fatDate)); - Serial.print('-'); - printTwoDigits(FAT_MONTH(fatDate)); - Serial.print('-'); - printTwoDigits(FAT_DAY(fatDate)); -} -//------------------------------------------------------------------------------ -/** %Print a directory time field to Serial. - - Format is hh:mm:ss. - - \param[in] fatTime The time field from a directory entry. -*/ -void SdFile::printFatTime(uint16_t fatTime) { - printTwoDigits(FAT_HOUR(fatTime)); - Serial.print(':'); - printTwoDigits(FAT_MINUTE(fatTime)); - Serial.print(':'); - printTwoDigits(FAT_SECOND(fatTime)); -} -//------------------------------------------------------------------------------ -/** %Print a value as two digits to Serial. - - \param[in] v Value to be printed, 0 <= \a v <= 99 -*/ -void SdFile::printTwoDigits(uint8_t v) { - char str[3]; - str[0] = '0' + v / 10; - str[1] = '0' + v % 10; - str[2] = 0; - Serial.print(str); -} -//------------------------------------------------------------------------------ -/** - Read data from a file starting at the current position. - - \param[out] buf Pointer to the location that will receive the data. - - \param[in] nbyte Maximum number of bytes to read. - - \return For success read() returns the number of bytes read. - A value less than \a nbyte, including zero, will be returned - if end of file is reached. - If an error occurs, read() returns -1. Possible errors include - read() called before a file has been opened, corrupt file system - or an I/O error occurred. -*/ -int16_t SdFile::read(void* buf, uint16_t nbyte) { - uint8_t* dst = reinterpret_cast(buf); - - // error if not open or write only - if (!isOpen() || !(flags_ & O_READ)) { - return -1; - } - - // max bytes left in file - if (nbyte > (fileSize_ - curPosition_)) { - nbyte = fileSize_ - curPosition_; - } - - // amount left to read - uint16_t toRead = nbyte; - while (toRead > 0) { - uint32_t block; // raw device block number - uint16_t offset = curPosition_ & 0X1FF; // offset in block - if (type_ == FAT_FILE_TYPE_ROOT16) { - block = vol_->rootDirStart() + (curPosition_ >> 9); - } else { - uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); - if (offset == 0 && blockOfCluster == 0) { - // start of new cluster - if (curPosition_ == 0) { - // use first cluster in file - curCluster_ = firstCluster_; - } else { - // get next cluster from FAT - if (!vol_->fatGet(curCluster_, &curCluster_)) { - return -1; - } - } - } - block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; - } - uint16_t n = toRead; - - // amount to be read from current block - if (n > (512 - offset)) { - n = 512 - offset; - } - - // no buffering needed if n == 512 or user requests no buffering - if ((unbufferedRead() || n == 512) && - block != SdVolume::cacheBlockNumber_) { - if (!vol_->readData(block, offset, n, dst)) { - return -1; - } - dst += n; - } else { - // read block to cache and copy data to caller - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) { - return -1; - } - uint8_t* src = SdVolume::cacheBuffer_.data + offset; - uint8_t* end = src + n; - while (src != end) { - *dst++ = *src++; - } - } - curPosition_ += n; - toRead -= n; - } - return nbyte; -} -//------------------------------------------------------------------------------ -/** - Read the next directory entry from a directory file. - - \param[out] dir The dir_t struct that will receive the data. - - \return For success readDir() returns the number of bytes read. - A value of zero will be returned if end of file is reached. - If an error occurs, readDir() returns -1. Possible errors include - readDir() called before a directory has been opened, this is not - a directory file or an I/O error occurred. -*/ -int8_t SdFile::readDir(dir_t* dir) { - int8_t n; - // if not a directory file or miss-positioned return an error - if (!isDir() || (0X1F & curPosition_)) { - return -1; - } - - while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) { - // last entry if DIR_NAME_FREE - if (dir->name[0] == DIR_NAME_FREE) { - break; - } - // skip empty entries and entry for . and .. - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') { - continue; - } - // return if normal file or subdirectory - if (DIR_IS_FILE_OR_SUBDIR(dir)) { - return n; - } - } - // error, end of file, or past last entry - return n < 0 ? -1 : 0; -} -//------------------------------------------------------------------------------ -// Read next directory entry into the cache -// Assumes file is correctly positioned -dir_t* SdFile::readDirCache(void) { - // error if not directory - if (!isDir()) { - return NULL; - } - - // index of entry in cache - uint8_t i = (curPosition_ >> 5) & 0XF; - - // use read to locate and cache block - if (read() < 0) { - return NULL; - } - - // advance to next entry - curPosition_ += 31; - - // return pointer to entry - return (SdVolume::cacheBuffer_.dir + i); -} -//------------------------------------------------------------------------------ -/** - Remove a file. - - The directory entry and all data for the file are deleted. - - \note This function should not be used to delete the 8.3 version of a - file that has a long name. For example if a file has the long name - "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include the file read-only, is a directory, - or an I/O error occurred. -*/ -uint8_t SdFile::remove(void) { - // free any clusters - will fail if read-only or directory - if (!truncate(0)) { - return false; - } - - // cache directory entry - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) { - return false; - } - - // mark entry deleted - d->name[0] = DIR_NAME_DELETED; - - // set this SdFile closed - type_ = FAT_FILE_TYPE_CLOSED; - - // write entry to SD - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - Remove a file. - - The directory entry and all data for the file are deleted. - - \param[in] dirFile The directory that contains the file. - \param[in] fileName The name of the file to be removed. - - \note This function should not be used to delete the 8.3 version of a - file that has a long name. For example if a file has the long name - "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include the file is a directory, is read only, - \a dirFile is not a directory, \a fileName is not found - or an I/O error occurred. -*/ -uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) { - SdFile file; - if (!file.open(dirFile, fileName, O_WRITE)) { - return false; - } - return file.remove(); -} -//------------------------------------------------------------------------------ -/** Remove a directory file. - - The directory file will be removed only if it is empty and is not the - root directory. rmDir() follows DOS and Windows and ignores the - read-only attribute for the directory. - - \note This function should not be used to delete the 8.3 version of a - directory that has a long name. For example if a directory has the - long name "New folder" you should not delete the 8.3 name "NEWFOL~1". - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include the file is not a directory, is the root - directory, is not empty, or an I/O error occurred. -*/ -uint8_t SdFile::rmDir(void) { - // must be open subdirectory - if (!isSubDir()) { - return false; - } - - rewind(); - - // make sure directory is empty - while (curPosition_ < fileSize_) { - dir_t* p = readDirCache(); - if (p == NULL) { - return false; - } - // done if past last used entry - if (p->name[0] == DIR_NAME_FREE) { - break; - } - // skip empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { - continue; - } - // error not empty - if (DIR_IS_FILE_OR_SUBDIR(p)) { - return false; - } - } - // convert empty directory to normal file for remove - type_ = FAT_FILE_TYPE_NORMAL; - flags_ |= O_WRITE; - return remove(); -} -//------------------------------------------------------------------------------ -/** Recursively delete a directory and all contained files. - - This is like the Unix/Linux 'rm -rf *' if called with the root directory - hence the name. - - Warning - This will remove all contents of the directory including - subdirectories. The directory will then be removed if it is not root. - The read-only attribute for files will be ignored. - - \note This function should not be used to delete the 8.3 version of - a directory that has a long name. See remove() and rmDir(). - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t SdFile::rmRfStar(void) { - rewind(); - while (curPosition_ < fileSize_) { - SdFile f; - - // remember position - uint16_t index = curPosition_ / 32; - - dir_t* p = readDirCache(); - if (!p) { - return false; - } - - // done if past last entry - if (p->name[0] == DIR_NAME_FREE) { - break; - } - - // skip empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { - continue; - } - - // skip if part of long file name or volume label in root - if (!DIR_IS_FILE_OR_SUBDIR(p)) { - continue; - } - - if (!f.open(this, index, O_READ)) { - return false; - } - if (f.isSubDir()) { - // recursively delete - if (!f.rmRfStar()) { - return false; - } - } else { - // ignore read-only - f.flags_ |= O_WRITE; - if (!f.remove()) { - return false; - } - } - // position to next entry if required - if (curPosition_ != (32u * (index + 1))) { - if (!seekSet(32u * (index + 1))) { - return false; - } - } - } - // don't try to delete root - if (isRoot()) { - return true; - } - return rmDir(); -} -//------------------------------------------------------------------------------ -/** - Sets a file's position. - - \param[in] pos The new position in bytes from the beginning of the file. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t SdFile::seekSet(uint32_t pos) { - // error if file not open or seek past end of file - if (!isOpen() || pos > fileSize_) { - return false; - } - - if (type_ == FAT_FILE_TYPE_ROOT16) { - curPosition_ = pos; - return true; - } - if (pos == 0) { - // set position to start of file - curCluster_ = 0; - curPosition_ = 0; - return true; - } - // calculate cluster index for cur and new position - uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); - uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); - - if (nNew < nCur || curPosition_ == 0) { - // must follow chain from first cluster - curCluster_ = firstCluster_; - } else { - // advance from curPosition - nNew -= nCur; - } - while (nNew--) { - if (!vol_->fatGet(curCluster_, &curCluster_)) { - return false; - } - } - curPosition_ = pos; - return true; -} -//------------------------------------------------------------------------------ -/** - The sync() call causes all modified data and directory fields - to be written to the storage device. - - \param[in] blocking If the sync should block until fully complete. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include a call to sync() before a file has been - opened or an I/O error. -*/ -uint8_t SdFile::sync(uint8_t blocking) { - // only allow open files and directories - if (!isOpen()) { - return false; - } - - if (flags_ & F_FILE_DIR_DIRTY) { - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) { - return false; - } - - // do not set filesize for dir files - if (!isDir()) { - d->fileSize = fileSize_; - } - - // update first cluster fields - d->firstClusterLow = firstCluster_ & 0XFFFF; - d->firstClusterHigh = firstCluster_ >> 16; - - // set modify time if user supplied a callback date/time function - if (dateTime_) { - dateTime_(&d->lastWriteDate, &d->lastWriteTime); - d->lastAccessDate = d->lastWriteDate; - } - // clear directory dirty - flags_ &= ~F_FILE_DIR_DIRTY; - } - - if (!blocking) { - flags_ &= ~F_FILE_NON_BLOCKING_WRITE; - } - - return SdVolume::cacheFlush(blocking); -} -//------------------------------------------------------------------------------ -/** - Set a file's timestamps in its directory entry. - - \param[in] flags Values for \a flags are constructed by a bitwise-inclusive - OR of flags from the following list - - T_ACCESS - Set the file's last access date. - - T_CREATE - Set the file's creation date and time. - - T_WRITE - Set the file's last write/modification date and time. - - \param[in] year Valid range 1980 - 2107 inclusive. - - \param[in] month Valid range 1 - 12 inclusive. - - \param[in] day Valid range 1 - 31 inclusive. - - \param[in] hour Valid range 0 - 23 inclusive. - - \param[in] minute Valid range 0 - 59 inclusive. - - \param[in] second Valid range 0 - 59 inclusive - - \note It is possible to set an invalid date since there is no check for - the number of days in a month. - - \note - Modify and access timestamps may be overwritten if a date time callback - function has been set by dateTimeCallback(). - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. -*/ -uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { - if (!isOpen() - || year < 1980 - || year > 2107 - || month < 1 - || month > 12 - || day < 1 - || day > 31 - || hour > 23 - || minute > 59 - || second > 59) { - return false; - } - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) { - return false; - } - - uint16_t dirDate = FAT_DATE(year, month, day); - uint16_t dirTime = FAT_TIME(hour, minute, second); - if (flags & T_ACCESS) { - d->lastAccessDate = dirDate; - } - if (flags & T_CREATE) { - d->creationDate = dirDate; - d->creationTime = dirTime; - // seems to be units of 1/100 second not 1/10 as Microsoft states - d->creationTimeTenths = second & 1 ? 100 : 0; - } - if (flags & T_WRITE) { - d->lastWriteDate = dirDate; - d->lastWriteTime = dirTime; - } - SdVolume::cacheSetDirty(); - return sync(); -} -//------------------------------------------------------------------------------ -/** - Truncate a file to a specified length. The current file position - will be maintained if it is less than or equal to \a length otherwise - it will be set to end of file. - - \param[in] length The desired length for the file. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. - Reasons for failure include file is read only, file is a directory, - \a length is greater than the current file size or an I/O error occurs. -*/ -uint8_t SdFile::truncate(uint32_t length) { - // error if not a normal file or read-only - if (!isFile() || !(flags_ & O_WRITE)) { - return false; - } - - // error if length is greater than current size - if (length > fileSize_) { - return false; - } - - // fileSize and length are zero - nothing to do - if (fileSize_ == 0) { - return true; - } - - // remember position for seek after truncation - uint32_t newPos = curPosition_ > length ? length : curPosition_; - - // position to last cluster in truncated file - if (!seekSet(length)) { - return false; - } - - if (length == 0) { - // free all clusters - if (!vol_->freeChain(firstCluster_)) { - return false; - } - firstCluster_ = 0; - } else { - uint32_t toFree; - if (!vol_->fatGet(curCluster_, &toFree)) { - return false; - } - - if (!vol_->isEOC(toFree)) { - // free extra clusters - if (!vol_->freeChain(toFree)) { - return false; - } - - // current cluster is end of chain - if (!vol_->fatPutEOC(curCluster_)) { - return false; - } - } - } - fileSize_ = length; - - // need to update directory entry - flags_ |= F_FILE_DIR_DIRTY; - - if (!sync()) { - return false; - } - - // set file to correct position - return seekSet(newPos); -} -//------------------------------------------------------------------------------ -/** - Write data to an open file. - - \note Data is moved to the cache but may not be written to the - storage device until sync() is called. - - \param[in] buf Pointer to the location of the data to be written. - - \param[in] nbyte Number of bytes to write. - - \return For success write() returns the number of bytes written, always - \a nbyte. If an error occurs, write() returns 0. Possible errors - include write() is called before a file has been opened, write is called - for a read-only file, device is full, a corrupt file system or an I/O error. - -*/ -size_t SdFile::write(const void* buf, uint16_t nbyte) { - // convert void* to uint8_t* - must be before goto statements - const uint8_t* src = reinterpret_cast(buf); - - // number of bytes left to write - must be before goto statements - uint16_t nToWrite = nbyte; - // if blocking writes should be used - uint8_t blocking = (flags_ & F_FILE_NON_BLOCKING_WRITE) == 0x00; - - // error if not a normal file or is read-only - if (!isFile() || !(flags_ & O_WRITE)) { - goto writeErrorReturn; - } - - // seek to end of file if append flag - if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { - if (!seekEnd()) { - goto writeErrorReturn; - } - } - - while (nToWrite > 0) { - uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); - uint16_t blockOffset = curPosition_ & 0X1FF; - if (blockOfCluster == 0 && blockOffset == 0) { - // start of new cluster - if (curCluster_ == 0) { - if (firstCluster_ == 0) { - // allocate first cluster of file - if (!addCluster()) { - goto writeErrorReturn; - } - } else { - curCluster_ = firstCluster_; - } - } else { - uint32_t next; - if (!vol_->fatGet(curCluster_, &next)) { - return false; - } - if (vol_->isEOC(next)) { - // add cluster if at end of chain - if (!addCluster()) { - goto writeErrorReturn; - } - } else { - curCluster_ = next; - } - } - } - // max space in block - uint16_t n = 512 - blockOffset; - - // lesser of space and amount to write - if (n > nToWrite) { - n = nToWrite; - } - - // block for data write - uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; - if (n == 512) { - // full block - don't need to use cache - // invalidate cache if block is in cache - if (SdVolume::cacheBlockNumber_ == block) { - SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; - } - if (!vol_->writeBlock(block, src, blocking)) { - goto writeErrorReturn; - } - src += 512; - } else { - if (blockOffset == 0 && curPosition_ >= fileSize_) { - // start of new block don't need to read into cache - if (!SdVolume::cacheFlush()) { - goto writeErrorReturn; - } - SdVolume::cacheBlockNumber_ = block; - SdVolume::cacheSetDirty(); - } else { - // rewrite part of block - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { - goto writeErrorReturn; - } - } - uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset; - uint8_t* end = dst + n; - while (dst != end) { - *dst++ = *src++; - } - } - nToWrite -= n; - curPosition_ += n; - } - if (curPosition_ > fileSize_) { - // update fileSize and insure sync will update dir entry - fileSize_ = curPosition_; - flags_ |= F_FILE_DIR_DIRTY; - } else if (dateTime_ && nbyte) { - // insure sync will update modified date and time - flags_ |= F_FILE_DIR_DIRTY; - } - - if (flags_ & O_SYNC) { - if (!sync()) { - goto writeErrorReturn; - } - } - return nbyte; - -writeErrorReturn: - // return for write error - //writeError = true; - setWriteError(); - return 0; -} -//------------------------------------------------------------------------------ -/** - Write a byte to a file. Required by the Arduino Print class. - - Use SdFile::writeError to check for errors. -*/ -size_t SdFile::write(uint8_t b) { - return write(&b, 1); -} -//------------------------------------------------------------------------------ -/** - Write a string to a file. Used by the Arduino Print class. - - Use SdFile::writeError to check for errors. -*/ -size_t SdFile::write(const char* str) { - return write(str, strlen(str)); -} -#ifdef __AVR__ -//------------------------------------------------------------------------------ -/** - Write a PROGMEM string to a file. - - Use SdFile::writeError to check for errors. -*/ -void SdFile::write_P(PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) { - write(c); - } -} -//------------------------------------------------------------------------------ -/** - Write a PROGMEM string followed by CR/LF to a file. - - Use SdFile::writeError to check for errors. -*/ -void SdFile::writeln_P(PGM_P str) { - write_P(str); - println(); -} -#endif -//------------------------------------------------------------------------------ -/** - Check how many bytes can be written without blocking. - - \return The number of bytes that can be written without blocking. -*/ -int SdFile::availableForWrite() { - if (!isFile() || !(flags_ & O_WRITE)) { - return 0; - } - - // seek to end of file if append flag - if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { - if (!seekEnd()) { - return 0; - } - } - - if (vol_->isBusy()) { - return 0; - } - - if (flags_ & F_FILE_CLUSTER_ADDED) { - // new cluster added, trigger a non-blocking sync - sync(0); - flags_ &= ~F_FILE_CLUSTER_ADDED; - return 0; - } - - if (vol_->isCacheMirrorBlockDirty()) { - // cache mirror block is dirty, trigger a non-blocking sync - vol_->cacheMirrorBlockFlush(0); - return 0; - } - - flags_ |= F_FILE_NON_BLOCKING_WRITE; - - uint16_t blockOffset = curPosition_ & 0X1FF; - uint16_t n = 512 - blockOffset; - - return n; -} diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdInfo.h b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdInfo.h deleted file mode 100644 index e9c80db..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdInfo.h +++ /dev/null @@ -1,232 +0,0 @@ -/* Arduino Sd2Card Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino Sd2Card Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino Sd2Card Library. If not, see - . -*/ -#ifndef SdInfo_h -#define SdInfo_h -#include -// Based on the document: -// -// SD Specifications -// Part 1 -// Physical Layer -// Simplified Specification -// Version 2.00 -// September 25, 2006 -// -// www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf -//------------------------------------------------------------------------------ -// SD card commands -/** GO_IDLE_STATE - init card in spi mode if CS low */ -uint8_t const CMD0 = 0X00; -/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/ -uint8_t const CMD8 = 0X08; -/** SEND_CSD - read the Card Specific Data (CSD register) */ -uint8_t const CMD9 = 0X09; -/** SEND_CID - read the card identification information (CID register) */ -uint8_t const CMD10 = 0X0A; -/** SEND_STATUS - read the card status register */ -uint8_t const CMD13 = 0X0D; -/** READ_BLOCK - read a single data block from the card */ -uint8_t const CMD17 = 0X11; -/** WRITE_BLOCK - write a single data block to the card */ -uint8_t const CMD24 = 0X18; -/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ -uint8_t const CMD25 = 0X19; -/** ERASE_WR_BLK_START - sets the address of the first block to be erased */ -uint8_t const CMD32 = 0X20; -/** ERASE_WR_BLK_END - sets the address of the last block of the continuous - range to be erased*/ -uint8_t const CMD33 = 0X21; -/** ERASE - erase all previously selected blocks */ -uint8_t const CMD38 = 0X26; -/** APP_CMD - escape for application specific command */ -uint8_t const CMD55 = 0X37; -/** READ_OCR - read the OCR register of a card */ -uint8_t const CMD58 = 0X3A; -/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be - pre-erased before writing */ -uint8_t const ACMD23 = 0X17; -/** SD_SEND_OP_COMD - Sends host capacity support information and - activates the card's initialization process */ -uint8_t const ACMD41 = 0X29; -//------------------------------------------------------------------------------ -/** status for card in the ready state */ -uint8_t const R1_READY_STATE = 0X00; -/** status for card in the idle state */ -uint8_t const R1_IDLE_STATE = 0X01; -/** status bit for illegal command */ -uint8_t const R1_ILLEGAL_COMMAND = 0X04; -/** start data token for read or write single block*/ -uint8_t const DATA_START_BLOCK = 0XFE; -/** stop token for write multiple blocks*/ -uint8_t const STOP_TRAN_TOKEN = 0XFD; -/** start data token for write multiple blocks*/ -uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC; -/** mask for data response tokens after a write block operation */ -uint8_t const DATA_RES_MASK = 0X1F; -/** write data accepted token */ -uint8_t const DATA_RES_ACCEPTED = 0X05; -//------------------------------------------------------------------------------ -typedef struct CID { - // byte 0 - uint8_t mid; // Manufacturer ID - // byte 1-2 - char oid[2]; // OEM/Application ID - // byte 3-7 - char pnm[5]; // Product name - // byte 8 - unsigned prv_m : 4; // Product revision n.m - unsigned prv_n : 4; - // byte 9-12 - uint32_t psn; // Product serial number - // byte 13 - unsigned mdt_year_high : 4; // Manufacturing date - unsigned reserved : 4; - // byte 14 - unsigned mdt_month : 4; - unsigned mdt_year_low : 4; - // byte 15 - unsigned always1 : 1; - unsigned crc : 7; -} cid_t; -//------------------------------------------------------------------------------ -// CSD for version 1.00 cards -typedef struct CSDV1 { - // byte 0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; - // byte 1 - uint8_t taac; - // byte 2 - uint8_t nsac; - // byte 3 - uint8_t tran_speed; - // byte 4 - uint8_t ccc_high; - // byte 5 - unsigned read_bl_len : 4; - unsigned ccc_low : 4; - // byte 6 - unsigned c_size_high : 2; - unsigned reserved2 : 2; - unsigned dsr_imp : 1; - unsigned read_blk_misalign : 1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; - // byte 7 - uint8_t c_size_mid; - // byte 8 - unsigned vdd_r_curr_max : 3; - unsigned vdd_r_curr_min : 3; - unsigned c_size_low : 2; - // byte 9 - unsigned c_size_mult_high : 2; - unsigned vdd_w_cur_max : 3; - unsigned vdd_w_curr_min : 3; - // byte 10 - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned c_size_mult_low : 1; - // byte 11 - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; - // byte 12 - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved3 : 2; - unsigned wp_grp_enable : 1; - // byte 13 - unsigned reserved4 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; - // byte 14 - unsigned reserved5: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; - // byte 15 - unsigned always1 : 1; - unsigned crc : 7; -} csd1_t; -//------------------------------------------------------------------------------ -// CSD for version 2.00 cards -typedef struct CSDV2 { - // byte 0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; - // byte 1 - uint8_t taac; - // byte 2 - uint8_t nsac; - // byte 3 - uint8_t tran_speed; - // byte 4 - uint8_t ccc_high; - // byte 5 - unsigned read_bl_len : 4; - unsigned ccc_low : 4; - // byte 6 - unsigned reserved2 : 4; - unsigned dsr_imp : 1; - unsigned read_blk_misalign : 1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; - // byte 7 - unsigned reserved3 : 2; - unsigned c_size_high : 6; - // byte 8 - uint8_t c_size_mid; - // byte 9 - uint8_t c_size_low; - // byte 10 - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned reserved4 : 1; - // byte 11 - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; - // byte 12 - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved5 : 2; - unsigned wp_grp_enable : 1; - // byte 13 - unsigned reserved6 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; - // byte 14 - unsigned reserved7: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; - // byte 15 - unsigned always1 : 1; - unsigned crc : 7; -} csd2_t; -//------------------------------------------------------------------------------ -// union of old and new style CSD register -union csd_t { - csd1_t v1; - csd2_t v2; -}; -#endif // SdInfo_h diff --git a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdVolume.cpp b/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdVolume.cpp deleted file mode 100644 index b8b6025..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/SD-1.3.0/src/utility/SdVolume.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* Arduino SdFat Library - Copyright (C) 2009 by William Greiman - - This file is part of the Arduino SdFat Library - - This Library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Arduino SdFat Library. If not, see - . -*/ -#include "SdFat.h" -//------------------------------------------------------------------------------ -// raw block cache -// init cacheBlockNumber_to invalid SD block number -uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; -cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card -Sd2Card* SdVolume::sdCard_; // pointer to SD card object -uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true -uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT -//------------------------------------------------------------------------------ -// find a contiguous group of clusters -uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { - // start of group - uint32_t bgnCluster; - - // flag to save place to start next search - uint8_t setStart; - - // set search start cluster - if (*curCluster) { - // try to make file contiguous - bgnCluster = *curCluster + 1; - - // don't save new start location - setStart = false; - } else { - // start at likely place for free cluster - bgnCluster = allocSearchStart_; - - // save next search start if one cluster - setStart = 1 == count; - } - // end of group - uint32_t endCluster = bgnCluster; - - // last cluster of FAT - uint32_t fatEnd = clusterCount_ + 1; - - // search the FAT for free clusters - for (uint32_t n = 0;; n++, endCluster++) { - // can't find space checked all clusters - if (n >= clusterCount_) { - return false; - } - - // past end - start from beginning of FAT - if (endCluster > fatEnd) { - bgnCluster = endCluster = 2; - } - uint32_t f; - if (!fatGet(endCluster, &f)) { - return false; - } - - if (f != 0) { - // cluster in use try next cluster as bgnCluster - bgnCluster = endCluster + 1; - } else if ((endCluster - bgnCluster + 1) == count) { - // done - found space - break; - } - } - // mark end of chain - if (!fatPutEOC(endCluster)) { - return false; - } - - // link clusters - while (endCluster > bgnCluster) { - if (!fatPut(endCluster - 1, endCluster)) { - return false; - } - endCluster--; - } - if (*curCluster != 0) { - // connect chains - if (!fatPut(*curCluster, bgnCluster)) { - return false; - } - } - // return first cluster number to caller - *curCluster = bgnCluster; - - // remember possible next free cluster - if (setStart) { - allocSearchStart_ = bgnCluster + 1; - } - - return true; -} -//------------------------------------------------------------------------------ -uint8_t SdVolume::cacheFlush(uint8_t blocking) { - if (cacheDirty_) { - if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data, blocking)) { - return false; - } - - if (!blocking) { - return true; - } - - // mirror FAT tables - if (!cacheMirrorBlockFlush(blocking)) { - return false; - } - cacheDirty_ = 0; - } - return true; -} -//------------------------------------------------------------------------------ -uint8_t SdVolume::cacheMirrorBlockFlush(uint8_t blocking) { - if (cacheMirrorBlock_) { - if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data, blocking)) { - return false; - } - cacheMirrorBlock_ = 0; - } - return true; -} -//------------------------------------------------------------------------------ -uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) { - if (cacheBlockNumber_ != blockNumber) { - if (!cacheFlush()) { - return false; - } - if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) { - return false; - } - cacheBlockNumber_ = blockNumber; - } - cacheDirty_ |= action; - return true; -} -//------------------------------------------------------------------------------ -// cache a zero block for blockNumber -uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) { - if (!cacheFlush()) { - return false; - } - - // loop take less flash than memset(cacheBuffer_.data, 0, 512); - for (uint16_t i = 0; i < 512; i++) { - cacheBuffer_.data[i] = 0; - } - cacheBlockNumber_ = blockNumber; - cacheSetDirty(); - return true; -} -//------------------------------------------------------------------------------ -// return the size in bytes of a cluster chain -uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { - uint32_t s = 0; - do { - if (!fatGet(cluster, &cluster)) { - return false; - } - s += 512UL << clusterSizeShift_; - } while (!isEOC(cluster)); - *size = s; - return true; -} -//------------------------------------------------------------------------------ -// Fetch a FAT entry -uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { - if (cluster > (clusterCount_ + 1)) { - return false; - } - uint32_t lba = fatStartBlock_; - lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; - if (lba != cacheBlockNumber_) { - if (!cacheRawBlock(lba, CACHE_FOR_READ)) { - return false; - } - } - if (fatType_ == 16) { - *value = cacheBuffer_.fat16[cluster & 0XFF]; - } else { - *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; - } - return true; -} -//------------------------------------------------------------------------------ -// Store a FAT entry -uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) { - // error if reserved cluster - if (cluster < 2) { - return false; - } - - // error if not in FAT - if (cluster > (clusterCount_ + 1)) { - return false; - } - - // calculate block address for entry - uint32_t lba = fatStartBlock_; - lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; - - if (lba != cacheBlockNumber_) { - if (!cacheRawBlock(lba, CACHE_FOR_READ)) { - return false; - } - } - // store entry - if (fatType_ == 16) { - cacheBuffer_.fat16[cluster & 0XFF] = value; - } else { - cacheBuffer_.fat32[cluster & 0X7F] = value; - } - cacheSetDirty(); - - // mirror second FAT - if (fatCount_ > 1) { - cacheMirrorBlock_ = lba + blocksPerFat_; - } - return true; -} -//------------------------------------------------------------------------------ -// free a cluster chain -uint8_t SdVolume::freeChain(uint32_t cluster) { - // clear free cluster location - allocSearchStart_ = 2; - - do { - uint32_t next; - if (!fatGet(cluster, &next)) { - return false; - } - - // free cluster - if (!fatPut(cluster, 0)) { - return false; - } - - cluster = next; - } while (!isEOC(cluster)); - - return true; -} -//------------------------------------------------------------------------------ -/** - Initialize a FAT volume. - - \param[in] dev The SD card where the volume is located. - - \param[in] part The partition to be used. Legal values for \a part are - 1-4 to use the corresponding partition on a device formatted with - a MBR, Master Boot Record, or zero if the device is formatted as - a super floppy with the FAT boot sector in block zero. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. Reasons for - failure include not finding a valid partition, not finding a valid - FAT file system in the specified partition or an I/O error. -*/ -uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { - uint32_t volumeStartBlock = 0; - sdCard_ = dev; - // if part == 0 assume super floppy with FAT boot sector in block zero - // if part > 0 assume mbr volume with partition table - if (part) { - if (part > 4) { - return false; - } - if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) { - return false; - } - part_t* p = &cacheBuffer_.mbr.part[part - 1]; - if ((p->boot & 0X7F) != 0 || - p->totalSectors < 100 || - p->firstSector == 0) { - // not a valid partition - return false; - } - volumeStartBlock = p->firstSector; - } - if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) { - return false; - } - bpb_t* bpb = &cacheBuffer_.fbs.bpb; - if (bpb->bytesPerSector != 512 || - bpb->fatCount == 0 || - bpb->reservedSectorCount == 0 || - bpb->sectorsPerCluster == 0) { - // not valid FAT volume - return false; - } - fatCount_ = bpb->fatCount; - blocksPerCluster_ = bpb->sectorsPerCluster; - - // determine shift that is same as multiply by blocksPerCluster_ - clusterSizeShift_ = 0; - while (blocksPerCluster_ != (1 << clusterSizeShift_)) { - // error if not power of 2 - if (clusterSizeShift_++ > 7) { - return false; - } - } - blocksPerFat_ = bpb->sectorsPerFat16 ? - bpb->sectorsPerFat16 : bpb->sectorsPerFat32; - - fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount; - - // count for FAT16 zero for FAT32 - rootDirEntryCount_ = bpb->rootDirEntryCount; - - // directory start for FAT16 dataStart for FAT32 - rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_; - - // data start for FAT16 and FAT32 - dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511) / 512); - - // total blocks for FAT16 or FAT32 - uint32_t totalBlocks = bpb->totalSectors16 ? - bpb->totalSectors16 : bpb->totalSectors32; - // total data blocks - clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); - - // divide by cluster size to get cluster count - clusterCount_ >>= clusterSizeShift_; - - // FAT type is determined by cluster count - if (clusterCount_ < 4085) { - fatType_ = 12; - } else if (clusterCount_ < 65525) { - fatType_ = 16; - } else { - rootDirStart_ = bpb->fat32RootCluster; - fatType_ = 32; - } - return true; -} diff --git a/draft- to be removed SW/components/drivers/SDcard/com/sdcard.cpp b/draft- to be removed SW/components/drivers/SDcard/com/sdcard.cpp deleted file mode 100644 index 9e170b2..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/com/sdcard.cpp +++ /dev/null @@ -1,1563 +0,0 @@ -/** - * @file sdcard.cpp - * @brief SD Card driver implementation for ESP32 - * @details Ported from Arduino SD library to use ESP-IDF SPI driver - * - * This implementation ports the Arduino SD library's low-level SD card - * communication and FAT filesystem logic to ESP-IDF. - * - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "sdcard.hpp" -#include "esp_log.h" -#include "esp_timer.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include -#include - -static const char* TAG = "SDCard"; - -// SD card commands (from Arduino SdInfo.h) -#define CMD0 0x00 // GO_IDLE_STATE -#define CMD8 0x08 // SEND_IF_COND -#define CMD9 0x09 // SEND_CSD -#define CMD10 0x0A // SEND_CID -#define CMD13 0x0D // SEND_STATUS -#define CMD17 0x11 // READ_BLOCK -#define CMD24 0x18 // WRITE_BLOCK -#define CMD25 0x19 // WRITE_MULTIPLE_BLOCK -#define CMD32 0x20 // ERASE_WR_BLK_START -#define CMD33 0x21 // ERASE_WR_BLK_END -#define CMD38 0x26 // ERASE -#define CMD55 0x37 // APP_CMD -#define CMD58 0x3A // READ_OCR -#define ACMD23 0x17 // SET_WR_BLK_ERASE_COUNT -#define ACMD41 0x29 // SD_SEND_OP_COND - -// SD card responses -#define R1_READY_STATE 0x00 -#define R1_IDLE_STATE 0x01 -#define R1_ILLEGAL_COMMAND 0x04 - -// Data tokens -#define DATA_START_BLOCK 0xFE -#define STOP_TRAN_TOKEN 0xFD -#define WRITE_MULTIPLE_TOKEN 0xFC -#define DATA_RES_MASK 0x1F -#define DATA_RES_ACCEPTED 0x05 - -// Timeouts (milliseconds) -#define SD_INIT_TIMEOUT 2000 -#define SD_READ_TIMEOUT 300 -#define SD_WRITE_TIMEOUT 600 -#define SD_ERASE_TIMEOUT 10000 - -// Error codes -#define SD_CARD_ERROR_CMD0 0x01 -#define SD_CARD_ERROR_CMD8 0x02 -#define SD_CARD_ERROR_CMD17 0x03 -#define SD_CARD_ERROR_CMD24 0x04 -#define SD_CARD_ERROR_CMD25 0x05 -#define SD_CARD_ERROR_CMD58 0x06 -#define SD_CARD_ERROR_ACMD23 0x07 -#define SD_CARD_ERROR_ACMD41 0x08 -#define SD_CARD_ERROR_BAD_CSD 0x09 -#define SD_CARD_ERROR_ERASE 0x0A -#define SD_CARD_ERROR_ERASE_SINGLE_BLOCK 0x0B -#define SD_CARD_ERROR_ERASE_TIMEOUT 0x0C -#define SD_CARD_ERROR_READ 0x0D -#define SD_CARD_ERROR_READ_REG 0x0E -#define SD_CARD_ERROR_READ_TIMEOUT 0x0F -#define SD_CARD_ERROR_STOP_TRAN 0x10 -#define SD_CARD_ERROR_WRITE 0x11 -#define SD_CARD_ERROR_WRITE_BLOCK_ZERO 0x12 -#define SD_CARD_ERROR_WRITE_MULTIPLE 0x13 -#define SD_CARD_ERROR_WRITE_PROGRAMMING 0x14 -#define SD_CARD_ERROR_WRITE_TIMEOUT 0x15 -#define SD_CARD_ERROR_SCK_RATE 0x16 - -// FAT filesystem structures (from Arduino SdFat) -#define FAT16_BOOT_SIGNATURE 0x29 -#define FAT32_BOOT_SIGNATURE 0x29 - -// Cache structure for 512-byte blocks -typedef struct { - uint32_t blockNumber; - uint8_t data[512]; -} cache_t; - -// CSD structure (Card-Specific Data) -typedef struct { - union { - struct { // CSD Version 1.0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; - uint8_t taac; - uint8_t nsac; - uint8_t tran_speed; - uint8_t ccc_high; - unsigned read_bl_len : 4; - unsigned ccc_low : 4; - unsigned c_size_high : 2; - unsigned reserved2 : 2; - unsigned dsr_imp : 1; - unsigned read_blk_misalign : 1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; - uint8_t c_size_mid; - unsigned vdd_r_curr_max : 3; - unsigned vdd_r_curr_min : 3; - unsigned c_size_low : 2; - unsigned c_size_mult_high : 2; - unsigned vdd_w_cur_max : 3; - unsigned vdd_w_curr_min : 3; - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned c_size_mult_low : 1; - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved3 : 2; - unsigned wp_grp_enable : 1; - unsigned reserved4 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; - unsigned reserved5: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; - unsigned always1 : 1; - unsigned crc : 7; - } v1; - struct { // CSD Version 2.0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; - uint8_t taac; - uint8_t nsac; - uint8_t tran_speed; - uint8_t ccc_high; - unsigned read_bl_len : 4; - unsigned ccc_low : 4; - unsigned reserved2 : 4; - unsigned dsr_imp : 1; - unsigned read_blk_misalign : 1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; - unsigned reserved3 : 2; - unsigned c_size_high : 6; - uint8_t c_size_mid; - uint8_t c_size_low; - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned reserved4 : 1; - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved5 : 2; - unsigned wp_grp_enable : 1; - unsigned reserved6 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; - unsigned reserved7: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; - unsigned always1 : 1; - unsigned crc : 7; - } v2; - }; -} csd_t; - -// FAT Boot Sector structure -typedef struct { - uint8_t jump[3]; - char oemName[8]; - uint16_t bytesPerSector; - uint8_t sectorsPerCluster; - uint16_t reservedSectorCount; - uint8_t fatCount; - uint16_t rootDirEntryCount; - uint16_t totalSectors16; - uint8_t mediaType; - uint16_t sectorsPerFat16; - uint16_t sectorsPerTrack; - uint16_t headCount; - uint32_t hiddenSectors; - uint32_t totalSectors32; - union { - struct { // FAT16 - uint8_t driveNumber; - uint8_t reserved1; - uint8_t bootSignature; - uint32_t volumeSerialNumber; - char volumeLabel[11]; - char fileSystemType[8]; - } fat16; - struct { // FAT32 - uint32_t sectorsPerFat32; - uint16_t fatFlags; - uint16_t version; - uint32_t rootCluster; - uint16_t fsInfo; - uint16_t backupBootSector; - uint8_t reserved[12]; - uint8_t driveNumber; - uint8_t reserved1; - uint8_t bootSignature; - uint32_t volumeSerialNumber; - char volumeLabel[11]; - char fileSystemType[8]; - } fat32; - }; -} __attribute__((packed)) fat_boot_t; - -// Directory entry structure -typedef struct { - uint8_t name[11]; // 8.3 filename - uint8_t attributes; // File attributes - uint8_t reserved; - uint8_t creationTimeTenths; - uint16_t creationTime; - uint16_t creationDate; - uint16_t lastAccessDate; - uint16_t firstClusterHigh; // High word of first cluster (FAT32) - uint16_t writeTime; - uint16_t writeDate; - uint16_t firstClusterLow; // Low word of first cluster - uint32_t fileSize; -} __attribute__((packed)) dir_t; - -// File attributes -#define DIR_ATT_READ_ONLY 0x01 -#define DIR_ATT_HIDDEN 0x02 -#define DIR_ATT_SYSTEM 0x04 -#define DIR_ATT_VOLUME_ID 0x08 -#define DIR_ATT_DIRECTORY 0x10 -#define DIR_ATT_ARCHIVE 0x20 -#define DIR_ATT_LONG_NAME 0x0F - -// Special cluster values -#define CLUSTER_FREE 0x0000 -#define CLUSTER_MIN_DATA 0x0002 -#define FAT16_EOC_MIN 0xFFF8 -#define FAT32_EOC_MIN 0x0FFFFFF8 - -//============================================================================== -// Sd2Card class - Low-level SD card SPI communication -//============================================================================== -class SdCardDriver::Sd2Card { -public: - Sd2Card(); - - bool init(spi_device_handle_t spi, uint8_t csPin); - uint8_t type() const { return m_type; } - uint8_t errorCode() const { return m_errorCode; } - uint8_t errorData() const { return m_status; } - uint32_t cardSize(); - - bool readBlock(uint32_t block, uint8_t* dst); - bool writeBlock(uint32_t blockNumber, const uint8_t* src); - bool readData(uint32_t block, uint16_t offset, uint16_t count, uint8_t* dst); - bool readCSD(csd_t* csd); - -private: - spi_device_handle_t m_spi; - uint8_t m_csPin; - uint8_t m_type; - uint8_t m_errorCode; - uint8_t m_status; - uint8_t m_inBlock; - uint16_t m_offset; - uint32_t m_block; - - // Helper methods (ported from Arduino) - void chipSelectLow(); - void chipSelectHigh(); - uint8_t spiSend(uint8_t data); - uint8_t spiRec(); - uint8_t cardCommand(uint8_t cmd, uint32_t arg); - uint8_t cardAcmd(uint8_t cmd, uint32_t arg); - bool waitNotBusy(unsigned int timeoutMillis); - bool waitStartBlock(); - void readEnd(); - uint8_t readRegister(uint8_t cmd, void* buf); - void error(uint8_t code) { m_errorCode = code; } - uint32_t millis() { return (uint32_t)(esp_timer_get_time() / 1000); } -}; - -//============================================================================== -// SdVolume class - FAT filesystem volume management -//============================================================================== -class SdCardDriver::SdVolume { -public: - SdVolume(); - - bool init(Sd2Card* dev); - uint8_t fatType() const { return m_fatType; } - uint32_t blocksPerCluster() const { return m_blocksPerCluster; } - uint32_t blocksPerFat() const { return m_blocksPerFat; } - uint32_t clusterCount() const { return m_clusterCount; } - uint32_t dataStartBlock() const { return m_dataStartBlock; } - uint32_t fatStartBlock() const { return m_fatStartBlock; } - uint32_t rootDirStart() const { return m_rootDirStart; } - - bool cacheRawBlock(uint32_t blockNumber, uint8_t action); - cache_t* cacheBuffer() { return &m_cacheBuffer; } - void cacheDirty() { m_cacheDirty = true; } - bool cacheFlush(); - - bool fatGet(uint32_t cluster, uint32_t* value); - bool fatPut(uint32_t cluster, uint32_t value); - bool freeChain(uint32_t cluster); - bool allocContiguous(uint32_t count, uint32_t* curCluster); - -private: - static Sd2Card* m_sdCard; - static cache_t m_cacheBuffer; - static bool m_cacheDirty; - static uint32_t m_cacheBlockNumber; - - uint8_t m_fatType; - uint8_t m_blocksPerCluster; - uint16_t m_rootDirEntryCount; - uint32_t m_fatCount; - uint32_t m_blocksPerFat; - uint32_t m_clusterCount; - uint32_t m_dataStartBlock; - uint32_t m_fatStartBlock; - uint32_t m_rootDirStart; -}; - -//============================================================================== -// SdFile class - File operations -//============================================================================== -class SdCardDriver::SdFile { -public: - // File open flags - static const uint8_t O_READ = 0x01; - static const uint8_t O_RDWR = 0x02; - static const uint8_t O_WRITE = 0x02; - static const uint8_t O_CREAT = 0x04; - static const uint8_t O_APPEND = 0x08; - static const uint8_t O_TRUNC = 0x10; - static const uint8_t O_DIR = 0x20; - - SdFile(); - - bool open(SdVolume* vol, const char* fileName, uint8_t oflag); - bool isOpen() const { return m_vol != nullptr; } - bool isDir() const { return (m_flags & O_DIR) != 0; } - void close(); - - int read(); - int read(void* buf, uint16_t nbyte); - int write(const void* buf, size_t size); - bool sync(); - - uint32_t fileSize() const { return m_fileSize; } - uint32_t curPosition() const { return m_curPosition; } - bool seekSet(uint32_t pos); - -private: - - SdVolume* m_vol; - uint8_t m_flags; - uint32_t m_fileSize; - uint32_t m_firstCluster; - uint32_t m_curCluster; - uint32_t m_curPosition; - uint16_t m_dirIndex; - uint32_t m_dirBlock; - - bool addCluster(); - bool addDirCluster(); - dir_t* cacheDirEntry(uint8_t action); -}; - -//============================================================================== -// Sd2Card Implementation -//============================================================================== -SdCardDriver::Sd2Card::Sd2Card() - : m_spi(nullptr) - , m_csPin(0) - , m_type(0) - , m_errorCode(0) - , m_status(0) - , m_inBlock(0) - , m_offset(0) - , m_block(0) -{ -} - -void SdCardDriver::Sd2Card::chipSelectLow() { - gpio_set_level((gpio_num_t)m_csPin, 0); -} - -void SdCardDriver::Sd2Card::chipSelectHigh() { - gpio_set_level((gpio_num_t)m_csPin, 1); -} - -uint8_t SdCardDriver::Sd2Card::spiSend(uint8_t data) { - spi_transaction_t trans = {}; - uint8_t rx_data; - - trans.length = 8; // 8 bits - trans.tx_buffer = &data; - trans.rx_buffer = &rx_data; - - esp_err_t ret = spi_device_polling_transmit(m_spi, &trans); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "SPI transmit failed: %s", esp_err_to_name(ret)); - return 0xFF; - } - - return rx_data; -} - -uint8_t SdCardDriver::Sd2Card::spiRec() { - return spiSend(0xFF); -} - -uint8_t SdCardDriver::Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { - // End read if in partial block read mode - readEnd(); - - // Select card - chipSelectLow(); - - // Wait up to 300 ms if busy - waitNotBusy(300); - - // Send command - spiSend(cmd | 0x40); - - // Send argument - for (int8_t s = 24; s >= 0; s -= 8) { - spiSend(arg >> s); - } - - // Send CRC - uint8_t crc = 0xFF; - if (cmd == CMD0) { - crc = 0x95; // Correct CRC for CMD0 with arg 0 - } - if (cmd == CMD8) { - crc = 0x87; // Correct CRC for CMD8 with arg 0x1AA - } - spiSend(crc); - - // Wait for response - for (uint8_t i = 0; ((m_status = spiRec()) & 0x80) && i != 0xFF; i++); - - return m_status; -} - -uint8_t SdCardDriver::Sd2Card::cardAcmd(uint8_t cmd, uint32_t arg) { - cardCommand(CMD55, 0); - return cardCommand(cmd, arg); -} - -bool SdCardDriver::Sd2Card::waitNotBusy(unsigned int timeoutMillis) { - unsigned int t0 = millis(); - unsigned int d; - - do { - if (spiRec() == 0xFF) { - return true; - } - d = millis() - t0; - } while (d < timeoutMillis); - - return false; -} - -bool SdCardDriver::Sd2Card::waitStartBlock() { - unsigned int t0 = millis(); - - while ((m_status = spiRec()) == 0xFF) { - unsigned int d = millis() - t0; - if (d > SD_READ_TIMEOUT) { - error(SD_CARD_ERROR_READ_TIMEOUT); - goto fail; - } - } - - if (m_status != DATA_START_BLOCK) { - error(SD_CARD_ERROR_READ); - goto fail; - } - return true; - -fail: - chipSelectHigh(); - return false; -} - -void SdCardDriver::Sd2Card::readEnd() { - if (m_inBlock) { - // Skip data and CRC - while (m_offset++ < 514) { - spiRec(); - } - chipSelectHigh(); - m_inBlock = 0; - } -} - -uint8_t SdCardDriver::Sd2Card::readRegister(uint8_t cmd, void* buf) { - uint8_t* dst = reinterpret_cast(buf); - - if (cardCommand(cmd, 0)) { - error(SD_CARD_ERROR_READ_REG); - goto fail; - } - - if (!waitStartBlock()) { - goto fail; - } - - // Transfer data - for (uint16_t i = 0; i < 16; i++) { - dst[i] = spiRec(); - } - - spiRec(); // Get first CRC byte - spiRec(); // Get second CRC byte - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} - -bool SdCardDriver::Sd2Card::readCSD(csd_t* csd) { - return readRegister(CMD9, csd); -} - -uint32_t SdCardDriver::Sd2Card::cardSize() { - csd_t csd; - if (!readCSD(&csd)) { - return 0; - } - - if (csd.v1.csd_ver == 0) { - // CSD Version 1.0 - uint8_t read_bl_len = csd.v1.read_bl_len; - uint16_t c_size = (csd.v1.c_size_high << 10) - | (csd.v1.c_size_mid << 2) - | csd.v1.c_size_low; - uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) - | csd.v1.c_size_mult_low; - return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); - } else if (csd.v2.csd_ver == 1) { - // CSD Version 2.0 - uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) - | (csd.v2.c_size_mid << 8) - | csd.v2.c_size_low; - return (c_size + 1) << 10; - } else { - error(SD_CARD_ERROR_BAD_CSD); - return 0; - } -} - -bool SdCardDriver::Sd2Card::init(spi_device_handle_t spi, uint8_t csPin) { - m_spi = spi; - m_csPin = csPin; - m_errorCode = m_inBlock = m_type = 0; - - unsigned int t0 = millis(); - uint32_t arg; - - // Configure CS pin as output with proper GPIO config - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << csPin); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - chipSelectHigh(); - - ESP_LOGI(TAG, "CS pin GPIO%d configured as output", csPin); - - // Must supply min of 74 clock cycles with CS high - vTaskDelay(pdMS_TO_TICKS(10)); // Small delay - for (uint8_t i = 0; i < 10; i++) { - spiSend(0xFF); - } - - chipSelectLow(); - - // Command to go idle in SPI mode - while ((m_status = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { - unsigned int d = millis() - t0; - if (d > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_CMD0); - goto fail; - } - } - - // Check SD version - if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { - m_type = SD_CARD_TYPE_SD1; - } else { - // Only need last byte of r7 response - for (uint8_t i = 0; i < 4; i++) { - m_status = spiRec(); - } - if (m_status != 0xAA) { - error(SD_CARD_ERROR_CMD8); - goto fail; - } - m_type = SD_CARD_TYPE_SD2; - } - - // Initialize card and send host supports SDHC if SD2 - arg = (m_type == SD_CARD_TYPE_SD2) ? 0x40000000 : 0; - - while ((m_status = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { - // Check for timeout - unsigned int d = millis() - t0; - if (d > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_ACMD41); - goto fail; - } - } - - // If SD2 read OCR register to check for SDHC card - if (m_type == SD_CARD_TYPE_SD2) { - if (cardCommand(CMD58, 0)) { - error(SD_CARD_ERROR_CMD58); - goto fail; - } - if ((spiRec() & 0xC0) == 0xC0) { - m_type = SD_CARD_TYPE_SDHC; - } - // Discard rest of OCR - contains allowed voltage range - for (uint8_t i = 0; i < 3; i++) { - spiRec(); - } - } - - chipSelectHigh(); - ESP_LOGI(TAG, "SD card initialized successfully. Type: %d", m_type); - return true; - -fail: - chipSelectHigh(); - ESP_LOGE(TAG, "SD card initialization failed. Error: 0x%02X", m_errorCode); - return false; -} - -bool SdCardDriver::Sd2Card::readBlock(uint32_t block, uint8_t* dst) { - return readData(block, 0, 512, dst); -} - -bool SdCardDriver::Sd2Card::readData(uint32_t block, uint16_t offset, - uint16_t count, uint8_t* dst) { - if (count == 0) { - return true; - } - if ((count + offset) > 512) { - goto fail; - } - - if (!m_inBlock || block != m_block || offset < m_offset) { - m_block = block; - // Use address if not SDHC card - if (m_type != SD_CARD_TYPE_SDHC) { - block <<= 9; - } - if (cardCommand(CMD17, block)) { - error(SD_CARD_ERROR_CMD17); - goto fail; - } - if (!waitStartBlock()) { - goto fail; - } - m_offset = 0; - m_inBlock = 1; - } - - // Skip data before offset - for (; m_offset < offset; m_offset++) { - spiRec(); - } - - // Transfer data - for (uint16_t i = 0; i < count; i++) { - dst[i] = spiRec(); - } - - m_offset += count; - if (m_offset >= 512) { - // Read rest of data, checksum and set chip select high - readEnd(); - } - return true; - -fail: - chipSelectHigh(); - return false; -} - -bool SdCardDriver::Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { - // Use address if not SDHC card - if (m_type != SD_CARD_TYPE_SDHC) { - blockNumber <<= 9; - } - - if (cardCommand(CMD24, blockNumber)) { - error(SD_CARD_ERROR_CMD24); - goto fail; - } - - // Send data token - spiSend(DATA_START_BLOCK); - - // Send data - for (uint16_t i = 0; i < 512; i++) { - spiSend(src[i]); - } - - // Dummy CRC - spiSend(0xFF); - spiSend(0xFF); - - m_status = spiRec(); - if ((m_status & DATA_RES_MASK) != DATA_RES_ACCEPTED) { - error(SD_CARD_ERROR_WRITE); - goto fail; - } - - // Wait for flash programming to complete - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_TIMEOUT); - goto fail; - } - - // Response is r2 so get and check two bytes for nonzero - if (cardCommand(CMD13, 0) || spiRec()) { - error(SD_CARD_ERROR_WRITE_PROGRAMMING); - goto fail; - } - - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} - -//============================================================================== -// SdVolume Implementation -//============================================================================== -SdCardDriver::Sd2Card* SdCardDriver::SdVolume::m_sdCard = nullptr; -cache_t SdCardDriver::SdVolume::m_cacheBuffer; -bool SdCardDriver::SdVolume::m_cacheDirty = false; -uint32_t SdCardDriver::SdVolume::m_cacheBlockNumber = 0xFFFFFFFF; - -SdCardDriver::SdVolume::SdVolume() - : m_fatType(0) - , m_blocksPerCluster(0) - , m_rootDirEntryCount(0) - , m_fatCount(0) - , m_blocksPerFat(0) - , m_clusterCount(0) - , m_dataStartBlock(0) - , m_fatStartBlock(0) - , m_rootDirStart(0) -{ -} - -bool SdCardDriver::SdVolume::cacheFlush() { - if (m_cacheDirty) { - if (!m_sdCard->writeBlock(m_cacheBlockNumber, m_cacheBuffer.data)) { - return false; - } - m_cacheDirty = false; - } - return true; -} - -bool SdCardDriver::SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) { - if (m_cacheBlockNumber != blockNumber) { - if (!cacheFlush()) { - return false; - } - if (!m_sdCard->readBlock(blockNumber, m_cacheBuffer.data)) { - return false; - } - m_cacheBlockNumber = blockNumber; - } - m_cacheDirty |= (action == 1); - return true; -} - -bool SdCardDriver::SdVolume::init(Sd2Card* dev) { - m_sdCard = dev; - - // Read MBR - cache_t* pc = &m_cacheBuffer; - if (!cacheRawBlock(0, 0)) { - ESP_LOGE(TAG, "Failed to read MBR"); - return false; - } - - // Find FAT partition - uint32_t volumeStartBlock = 0; - uint8_t* p = pc->data + 0x1BE; // First partition entry - - for (uint8_t i = 0; i < 4; i++, p += 16) { - uint8_t partType = p[4]; - if (partType == 0x04 || partType == 0x06 || partType == 0x0B || - partType == 0x0C || partType == 0x0E) { - // Found FAT partition - volumeStartBlock = *((uint32_t*)(p + 8)); - break; - } - } - - // If no partition found, try whole device as FAT - if (volumeStartBlock == 0) { - ESP_LOGW(TAG, "No MBR partition found, trying whole device as FAT"); - } - - // Read volume boot record - if (!cacheRawBlock(volumeStartBlock, 0)) { - ESP_LOGE(TAG, "Failed to read volume boot record"); - return false; - } - - fat_boot_t* boot = (fat_boot_t*)pc->data; - - // Validate boot record - if (boot->bytesPerSector != 512) { - ESP_LOGE(TAG, "Invalid sector size: %d", boot->bytesPerSector); - return false; - } - - m_blocksPerCluster = boot->sectorsPerCluster; - m_fatCount = boot->fatCount; - m_blocksPerFat = (boot->sectorsPerFat16 != 0) ? boot->sectorsPerFat16 : - boot->fat32.sectorsPerFat32; - m_rootDirEntryCount = boot->rootDirEntryCount; - - uint32_t totalBlocks = (boot->totalSectors16 != 0) ? boot->totalSectors16 : - boot->totalSectors32; - - m_fatStartBlock = volumeStartBlock + boot->reservedSectorCount; - uint32_t rootDirBlocks = ((m_rootDirEntryCount * 32) + 511) / 512; - m_dataStartBlock = m_fatStartBlock + m_fatCount * m_blocksPerFat + rootDirBlocks; - m_clusterCount = (totalBlocks - (m_dataStartBlock - volumeStartBlock)) / m_blocksPerCluster; - - // Determine FAT type - if (m_clusterCount < 4085) { - m_fatType = 12; // FAT12 (not supported) - ESP_LOGE(TAG, "FAT12 not supported"); - return false; - } else if (m_clusterCount < 65525) { - m_fatType = 16; - m_rootDirStart = m_fatStartBlock + m_fatCount * m_blocksPerFat; - } else { - m_fatType = 32; - m_rootDirStart = m_dataStartBlock + (boot->fat32.rootCluster - 2) * m_blocksPerCluster; - } - - ESP_LOGI(TAG, "FAT%d volume initialized. Clusters: %lu", m_fatType, m_clusterCount); - return true; -} - -bool SdCardDriver::SdVolume::fatGet(uint32_t cluster, uint32_t* value) { - if (cluster > (m_clusterCount + 1)) { - return false; - } - - uint32_t lba; - if (m_fatType == 16) { - lba = m_fatStartBlock + (cluster >> 8); - } else { - lba = m_fatStartBlock + (cluster >> 7); - } - - if (lba != m_cacheBlockNumber) { - if (!cacheRawBlock(lba, 0)) { - return false; - } - } - - if (m_fatType == 16) { - *value = *((uint16_t*)(m_cacheBuffer.data + ((cluster & 0xFF) << 1))); - } else { - *value = *((uint32_t*)(m_cacheBuffer.data + ((cluster & 0x7F) << 2))) & 0x0FFFFFFF; - } - - return true; -} - -bool SdCardDriver::SdVolume::fatPut(uint32_t cluster, uint32_t value) { - if (cluster < 2 || cluster > (m_clusterCount + 1)) { - return false; - } - - uint32_t lba; - if (m_fatType == 16) { - lba = m_fatStartBlock + (cluster >> 8); - } else { - lba = m_fatStartBlock + (cluster >> 7); - } - - if (lba != m_cacheBlockNumber) { - if (!cacheRawBlock(lba, 0)) { - return false; - } - } - - if (m_fatType == 16) { - *((uint16_t*)(m_cacheBuffer.data + ((cluster & 0xFF) << 1))) = value; - } else { - *((uint32_t*)(m_cacheBuffer.data + ((cluster & 0x7F) << 2))) = value; - } - - m_cacheDirty = true; - return true; -} - -bool SdCardDriver::SdVolume::freeChain(uint32_t cluster) { - uint32_t next; - - while (cluster != 0) { - if (!fatGet(cluster, &next)) { - return false; - } - if (!fatPut(cluster, 0)) { - return false; - } - cluster = next; - } - - return true; -} - -bool SdCardDriver::SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { - // Simplified version - find contiguous free clusters - uint32_t start = 0; - uint32_t found = 0; - - for (uint32_t cluster = 2; cluster < m_clusterCount + 2; cluster++) { - uint32_t value; - if (!fatGet(cluster, &value)) { - return false; - } - - if (value == 0) { - if (start == 0) { - start = cluster; - } - found++; - if (found >= count) { - // Allocate clusters - for (uint32_t c = start; c < start + count - 1; c++) { - if (!fatPut(c, c + 1)) { - return false; - } - } - // Mark last cluster as EOC - uint32_t eoc = (m_fatType == 16) ? 0xFFFF : 0x0FFFFFFF; - if (!fatPut(start + count - 1, eoc)) { - return false; - } - *curCluster = start; - return true; - } - } else { - start = 0; - found = 0; - } - } - - return false; -} - -//============================================================================== -// SdFile Implementation -//============================================================================== -SdCardDriver::SdFile::SdFile() - : m_vol(nullptr) - , m_flags(0) - , m_fileSize(0) - , m_firstCluster(0) - , m_curCluster(0) - , m_curPosition(0) - , m_dirIndex(0) - , m_dirBlock(0) -{ -} - -void SdCardDriver::SdFile::close() { - if (m_vol) { - sync(); - m_vol = nullptr; - } -} - -bool SdCardDriver::SdFile::sync() { - if (m_flags & (O_WRITE | O_CREAT)) { - dir_t* d = cacheDirEntry(1); // Write action - if (!d) { - return false; - } - - d->fileSize = m_fileSize; - - // Update timestamps (simplified - use current time) - d->writeTime = 0; - d->writeDate = 0; - - return m_vol->cacheFlush(); - } - return true; -} - -dir_t* SdCardDriver::SdFile::cacheDirEntry(uint8_t action) { - if (!m_vol->cacheRawBlock(m_dirBlock, action)) { - return nullptr; - } - return (dir_t*)(buffer + m_dirIndex * 32); - //return (dir_t*)(m_vol->cacheBuffer()->data + (m_dirIndex & 0x0F) * 32); -} - -bool SdCardDriver::SdFile::seekSet(uint32_t pos) { - if (pos > m_fileSize) { - return false; - } - - m_curPosition = pos; - - // Calculate cluster from position - uint32_t clusterOffset = pos / (m_vol->blocksPerCluster() * 512); - m_curCluster = m_firstCluster; - - for (uint32_t i = 0; i < clusterOffset && m_curCluster != 0; i++) { - uint32_t next; - if (!m_vol->fatGet(m_curCluster, &next)) { - return false; - } - m_curCluster = next; - } - - return true; -} - -int SdCardDriver::SdFile::read() { - uint8_t b; - if (read(&b, 1) == 1) { - return b; - } - return -1; -} - -int SdCardDriver::SdFile::read(void* buf, uint16_t nbyte) { - uint8_t* dst = (uint8_t*)buf; - uint16_t count = 0; - - while (count < nbyte && m_curPosition < m_fileSize) { - uint32_t blockOffset = m_curPosition % 512; - uint32_t toRead = 512 - blockOffset; - if (toRead > (nbyte - count)) { - toRead = nbyte - count; - } - if (toRead > (m_fileSize - m_curPosition)) { - toRead = m_fileSize - m_curPosition; - } - - // Calculate block number - uint32_t clusterOffset = (m_curPosition / 512) % m_vol->blocksPerCluster(); - uint32_t blockNumber = m_vol->dataStartBlock() + - (m_curCluster - 2) * m_vol->blocksPerCluster() + - clusterOffset; - - if (!m_vol->cacheRawBlock(blockNumber, 0)) { - return -1; - } - - memcpy(dst + count, m_vol->cacheBuffer()->data + blockOffset, toRead); - count += toRead; - m_curPosition += toRead; - - // Move to next cluster if needed - if ((m_curPosition % (m_vol->blocksPerCluster() * 512)) == 0) { - uint32_t next; - if (!m_vol->fatGet(m_curCluster, &next)) { - return -1; - } - m_curCluster = next; - } - } - - return count; -} - -int SdCardDriver::SdFile::write(const void* buf, size_t size) { - const uint8_t* src = (const uint8_t*)buf; - size_t count = 0; - - while (count < size) { - uint32_t blockOffset = m_curPosition % 512; - uint32_t toWrite = 512 - blockOffset; - if (toWrite > (size - count)) { - toWrite = size - count; - } - - // Calculate block number - uint32_t clusterOffset = (m_curPosition / 512) % m_vol->blocksPerCluster(); - uint32_t blockNumber = m_vol->dataStartBlock() + - (m_curCluster - 2) * m_vol->blocksPerCluster() + - clusterOffset; - - // Read block first if partial write - if (blockOffset != 0 || toWrite != 512) { - if (!m_vol->cacheRawBlock(blockNumber, 0)) { - return -1; - } - } - - // Copy data to cache - memcpy(m_vol->cacheBuffer()->data + blockOffset, src + count, toWrite); - m_vol->cacheDirty(); - - count += toWrite; - m_curPosition += toWrite; - if (m_curPosition > m_fileSize) { - m_fileSize = m_curPosition; - } - - // Move to next cluster if needed - if ((m_curPosition % (m_vol->blocksPerCluster() * 512)) == 0) { - uint32_t next; - if (!m_vol->fatGet(m_curCluster, &next)) { - // Allocate new cluster - if (!addCluster()) { - return -1; - } - } else { - m_curCluster = next; - } - } - } - - return count; -} - -bool SdCardDriver::SdFile::addCluster() { - uint32_t newCluster; - - // Find free cluster (simplified - just find next free) - for (newCluster = 2; newCluster < m_vol->clusterCount() + 2; newCluster++) { - uint32_t value; - if (!m_vol->fatGet(newCluster, &value)) { - return false; - } - if (value == 0) { - break; - } - } - - if (newCluster >= m_vol->clusterCount() + 2) { - return false; // Disk full - } - - // Link current cluster to new cluster - if (!m_vol->fatPut(m_curCluster, newCluster)) { - return false; - } - - // Mark new cluster as EOC - uint32_t eoc = (m_vol->fatType() == 16) ? 0xFFFF : 0x0FFFFFFF; - if (!m_vol->fatPut(newCluster, eoc)) { - return false; - } - - m_curCluster = newCluster; - return true; -} - -bool SdCardDriver::SdFile::open(SdVolume* vol, const char* fileName, uint8_t oflag) { - m_vol = vol; - m_flags = oflag; - - // Simplified: only support root directory and 8.3 filenames - // Open root directory - uint32_t cluster = vol->rootDirStartCluster(); // store this - - // Search for file - bool found = false; - uint32_t dirIndex = 0; - - // Parse filename to 8.3 format - char name83[11]; - memset(name83, ' ', 11); - - const char* dot = strchr(fileName, '.'); - size_t nameLen = dot ? (dot - fileName) : strlen(fileName); - if (nameLen > 8) nameLen = 8; - memcpy(name83, fileName, nameLen); - - if (dot && strlen(dot + 1) > 0) { - size_t extLen = strlen(dot + 1); - if (extLen > 3) extLen = 3; - memcpy(name83 + 8, dot + 1, extLen); - } - - // Convert to uppercase - for (int i = 0; i < 11; i++) { - if (name83[i] >= 'a' && name83[i] <= 'z') { - name83[i] -= 32; - } - } - - // Search directory - while (cluster >= CLUSTER_MIN_DATA) { - - for (uint32_t block = 0; block < vol->blocksPerCluster(); block++) { - uint32_t lba = vol->dataStartBlock() + - (cluster - 2) * vol->blocksPerCluster() + - block; - - if (!vol->cacheRawBlock(lba, 0)) return false; - - // scan 16 directory entries here - } - - uint32_t next; - if (!vol->fatGet(cluster, &next)) return false; - if (next >= FAT32_EOC_MIN) break; - - cluster = next; - } - - dir_t* dir = (dir_t*)vol->cacheBuffer()->data; - for (uint8_t i = 0; i < 16; i++, dirIndex++) { - if (dir[i].name[0] == 0x00) { - // End of directory - break; - } - if (dir[i].name[0] == 0xE5) { - // Deleted entry - continue; - } - if (dir[i].attributes & (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY)) { - // Skip volumes and directories - continue; - } - - if (memcmp(dir[i].name, name83, 11) == 0) { - // Found file - found = true; - m_dirBlock = dirBlock + block; - m_dirIndex = i; - m_fileSize = dir[i].fileSize; - m_firstCluster = ((uint32_t)dir[i].firstClusterHigh << 16) | - dir[i].firstClusterLow; - m_curCluster = m_firstCluster; - m_curPosition = 0; - - if (oflag & O_TRUNC) { - m_fileSize = 0; - if (m_firstCluster != 0) { - vol->freeChain(m_firstCluster); - m_firstCluster = 0; - m_curCluster = 0; - } - } - - if (oflag & O_APPEND) { - seekSet(m_fileSize); - } - - return true; - } - } - } - - // File not found - create if O_CREAT - if (!found && (oflag & O_CREAT)) { - // Find free directory entry - dirIndex = 0; - for (uint32_t block = 0; block < 32; block++) { - if (!vol->cacheRawBlock(dirBlock + block, 0)) { - return false; - } - - dir_t* dir = (dir_t*)vol->cacheBuffer()->data; - for (uint8_t i = 0; i < 16; i++, dirIndex++) { - if (dir[i].name[0] == 0x00 || dir[i].name[0] == 0xE5) { - // Found free entry - memset(&dir[i], 0, sizeof(dir_t)); - memcpy(dir[i].name, name83, 11); - dir[i].attributes = DIR_ATT_ARCHIVE; - - // Allocate first cluster - if (!vol->allocContiguous(1, &m_firstCluster)) { - return false; - } - - dir[i].firstClusterHigh = m_firstCluster >> 16; - dir[i].firstClusterLow = m_firstCluster & 0xFFFF; - dir[i].fileSize = 0; - - m_dirBlock = dirBlock + block; - m_dirIndex = i; - m_fileSize = 0; - m_curCluster = m_firstCluster; - m_curPosition = 0; - - vol->cacheDirty(); - vol->cacheFlush(); - - ESP_LOGI(TAG, "Created file: %s", fileName); - return true; - } - } - } - - ESP_LOGE(TAG, "Directory full"); - return false; - } - - ESP_LOGE(TAG, "File not found: %s", fileName); - return false; -} - -//============================================================================== -// SdCardDriver Implementation -//============================================================================== -SdCardDriver::SdCardDriver() - : m_mounted(false) - , m_spiHost(SPI3_HOST) - , m_csPin(0) - , m_spiDevice(nullptr) - , m_card(nullptr) - , m_volume(nullptr) -{ - memset(m_mountPoint, 0, sizeof(m_mountPoint)); -} - -SdCardDriver::~SdCardDriver() { - unmount(); -} - -bool SdCardDriver::initializeSpi() { - // SPI device configuration for SD card - // Start with slow clock (400kHz) for initialization - spi_device_interface_config_t dev_cfg = {}; - dev_cfg.command_bits = 0; - dev_cfg.address_bits = 0; - dev_cfg.dummy_bits = 0; - dev_cfg.mode = 0; // SPI_MODE0 - dev_cfg.clock_speed_hz = 400000; // 400 kHz for initialization - dev_cfg.spics_io_num = -1; // Manual CS control - dev_cfg.queue_size = 1; - dev_cfg.flags = 0; - - esp_err_t ret = spi_bus_add_device(m_spiHost, &dev_cfg, &m_spiDevice); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to add SPI device: %s", esp_err_to_name(ret)); - return false; - } - - return true; -} - -void SdCardDriver::deinitializeSpi() { - if (m_spiDevice) { - spi_bus_remove_device(m_spiDevice); - m_spiDevice = nullptr; - } -} - -bool SdCardDriver::mount(const char* mount_point, spi_host_device_t spi_host, uint8_t cs_pin) { - if (m_mounted) { - ESP_LOGW(TAG, "SD card already mounted"); - return true; - } - - m_spiHost = spi_host; - m_csPin = cs_pin; - strncpy(m_mountPoint, mount_point, sizeof(m_mountPoint) - 1); - - ESP_LOGI(TAG, "Mounting SD card on %s (CS: GPIO%d)", mount_point, cs_pin); - - // Initialize SPI device - if (!initializeSpi()) { - return false; - } - - // Create and initialize SD card - m_card = new Sd2Card(); - if (!m_card->init(m_spiDevice, cs_pin)) { - ESP_LOGE(TAG, "SD card initialization failed"); - delete m_card; - m_card = nullptr; - deinitializeSpi(); - return false; - } - - // Create and initialize volume - m_volume = new SdVolume(); - if (!m_volume->init(m_card)) { - ESP_LOGE(TAG, "Failed to initialize FAT volume"); - delete m_volume; - delete m_card; - m_volume = nullptr; - m_card = nullptr; - deinitializeSpi(); - return false; - } - - m_mounted = true; - ESP_LOGI(TAG, "SD card mounted successfully"); - return true; -} - -void SdCardDriver::unmount() { - if (m_mounted) { - if (m_volume) { - m_volume->cacheFlush(); - delete m_volume; - m_volume = nullptr; - } - - if (m_card) { - delete m_card; - m_card = nullptr; - } - - deinitializeSpi(); - m_mounted = false; - ESP_LOGI(TAG, "SD card unmounted"); - } -} - -uint8_t SdCardDriver::getCardType() const { - return m_card ? m_card->type() : 0; -} - -uint64_t SdCardDriver::getCardSize() const { - if (!m_card) { - return 0; - } - return (uint64_t)m_card->cardSize() * 512; -} - -int SdCardDriver::open(const char* filepath, uint8_t mode) { - if (!m_mounted) { - ESP_LOGE(TAG, "SD card not mounted"); - return -1; - } - - // Create file object - SdFile* file = new SdFile(); - - // Convert mode - uint8_t oflag = 0; - if (mode & SD_FILE_READ) { - oflag |= SdFile::O_READ; - } - if (mode & SD_FILE_WRITE) { - oflag |= SdFile::O_WRITE | SdFile::O_CREAT | SdFile::O_APPEND; - } - - // Skip mount point from filepath - const char* filename = filepath; - if (strncmp(filepath, m_mountPoint, strlen(m_mountPoint)) == 0) { - filename = filepath + strlen(m_mountPoint); - if (filename[0] == '/') { - filename++; - } - } - - if (!file->open(m_volume, filename, oflag)) { - delete file; - return -1; - } - - // Return file pointer as descriptor (simplified) - return (int)file; -} - -bool SdCardDriver::close(int fd) { - if (fd < 0) { - return false; - } - - SdFile* file = (SdFile*)fd; - file->close(); - - // Flush volume cache to ensure all data is written to SD card - if (m_volume) { - m_volume->cacheFlush(); - } - - delete file; - return true; -} - -int SdCardDriver::write(int fd, const void* data, size_t size) { - if (fd < 0) { - return -1; - } - - SdFile* file = (SdFile*)fd; - return file->write(data, size); -} - -int SdCardDriver::read(int fd, void* buffer, size_t size) { - if (fd < 0) { - return -1; - } - - SdFile* file = (SdFile*)fd; - return file->read(buffer, (uint16_t)size); -} - -bool SdCardDriver::exists(const char* filepath) { - // Simplified: try to open file for reading - int fd = open(filepath, SD_FILE_READ); - if (fd >= 0) { - close(fd); - return true; - } - return false; -} - -bool SdCardDriver::mkdir(const char* dirpath) { - // Not implemented in this simplified version - ESP_LOGW(TAG, "mkdir not implemented"); - return false; -} - -bool SdCardDriver::remove(const char* filepath) { - // Not implemented in this simplified version - ESP_LOGW(TAG, "remove not implemented"); - return false; -} - -bool SdCardDriver::rmdir(const char* dirpath) { - // Not implemented in this simplified version - ESP_LOGW(TAG, "rmdir not implemented"); - return false; -} diff --git a/draft- to be removed SW/components/drivers/SDcard/com/sdcard.hpp b/draft- to be removed SW/components/drivers/SDcard/com/sdcard.hpp deleted file mode 100644 index c29df6c..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/com/sdcard.hpp +++ /dev/null @@ -1,161 +0,0 @@ -/** - * @file sdcard.hpp - * @brief SD Card driver for ESP32 using SPI interface - * @details Ported from Arduino SD library to use ESP-IDF SPI driver - * - * This driver implements SD card functionality using ESP-IDF's SPI master - * driver while maintaining the file system logic from the Arduino SD library. - * - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#pragma once - -#include -#include -#include "driver/spi_master.h" -#include "driver/gpio.h" - -// File open modes (compatible with Arduino SD library) -#define SD_FILE_READ 0x01 -#define SD_FILE_WRITE 0x02 - -// SD card types -#define SD_CARD_TYPE_SD1 1 // Standard capacity V1 SD card -#define SD_CARD_TYPE_SD2 2 // Standard capacity V2 SD card -#define SD_CARD_TYPE_SDHC 3 // High Capacity SD card - -/** - * @class SdCardDriver - * @brief High-level SD card driver interface - */ -class SdCardDriver { -public: - /** - * @brief Constructor - */ - SdCardDriver(); - - /** - * @brief Destructor - */ - ~SdCardDriver(); - - /** - * @brief Mount SD card on SPI bus - * @param mount_point Mount point path (e.g., "/ESP") - * @param spi_host SPI host device (e.g., SPI3_HOST) - * @param cs_pin Chip select GPIO pin number - * @return true if mount successful, false otherwise - */ - bool mount(const char* mount_point, spi_host_device_t spi_host, uint8_t cs_pin); - - /** - * @brief Unmount SD card - */ - void unmount(); - - /** - * @brief Check if SD card is mounted - * @return true if mounted, false otherwise - */ - bool isMounted() const { return m_mounted; } - - /** - * @brief Get card type - * @return Card type (SD_CARD_TYPE_SD1, SD_CARD_TYPE_SD2, SD_CARD_TYPE_SDHC) - */ - uint8_t getCardType() const; - - /** - * @brief Get card size in bytes - * @return Card size in bytes (0 if error) - */ - uint64_t getCardSize() const; - - // File operations - /** - * @brief Open a file - * @param filepath Path to file - * @param mode Open mode (SD_FILE_READ or SD_FILE_WRITE) - * @return File descriptor (negative if error) - */ - int open(const char* filepath, uint8_t mode); - - /** - * @brief Close a file - * @param fd File descriptor - * @return true if successful, false otherwise - */ - bool close(int fd); - - /** - * @brief Write data to file - * @param fd File descriptor - * @param data Data buffer - * @param size Number of bytes to write - * @return Number of bytes written (negative if error) - */ - int write(int fd, const void* data, size_t size); - - /** - * @brief Read data from file - * @param fd File descriptor - * @param buffer Buffer to read into - * @param size Number of bytes to read - * @return Number of bytes read (negative if error) - */ - int read(int fd, void* buffer, size_t size); - - /** - * @brief Check if file exists - * @param filepath Path to file - * @return true if exists, false otherwise - */ - bool exists(const char* filepath); - - /** - * @brief Create directory - * @param dirpath Path to directory - * @return true if successful, false otherwise - */ - bool mkdir(const char* dirpath); - - /** - * @brief Remove file - * @param filepath Path to file - * @return true if successful, false otherwise - */ - bool remove(const char* filepath); - - /** - * @brief Remove directory - * @param dirpath Path to directory - * @return true if successful, false otherwise - */ - bool rmdir(const char* dirpath); - -private: - // Forward declarations of internal classes - class Sd2Card; - class SdVolume; - class SdFile; - - // Member variables - bool m_mounted; - char m_mountPoint[32]; - spi_host_device_t m_spiHost; - uint8_t m_csPin; - spi_device_handle_t m_spiDevice; - - // Internal driver components - Sd2Card* m_card; - SdVolume* m_volume; - - // Helper methods - bool initializeSpi(); - void deinitializeSpi(); -}; - diff --git a/draft- to be removed SW/components/drivers/SDcard/logging_data.csv b/draft- to be removed SW/components/drivers/SDcard/logging_data.csv deleted file mode 100644 index ff85762..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3000,SDcard,INFO,Low,SD card mounted successfully diff --git a/draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.py b/draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.py deleted file mode 100644 index 0c891e7..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_sdcard_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "SD card mounted successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_sdcard_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.test_scenario.xml deleted file mode 100644 index 2ff5459..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/test/sdcard_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - SDCARD_INIT_TEST - - python components/drivers/SDcard/test/sdcard_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/SDcard/test/test_sdcard.cpp b/draft- to be removed SW/components/drivers/SDcard/test/test_sdcard.cpp deleted file mode 100644 index 1d4273f..0000000 --- a/draft- to be removed SW/components/drivers/SDcard/test/test_sdcard.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file test_sdcard.cpp - * @brief Unit tests for SD Card driver component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "sdcard.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_sdcard_mount(void) -{ - SdCardDriver sdcard; - bool result = sdcard.mount(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(sdcard.isMounted()); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/drivers/diag_protocol_stack/CMakeLists.txt b/draft- to be removed SW/components/drivers/diag_protocol_stack/CMakeLists.txt deleted file mode 100644 index 4fe1f10..0000000 --- a/draft- to be removed SW/components/drivers/diag_protocol_stack/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/diag_protocol_stack.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.cpp b/draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.cpp deleted file mode 100644 index 9c8b6f1..0000000 --- a/draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file diag_protocol_stack.cpp - * @brief DiagProtocolStack component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "diag_protocol_stack.hpp" -#include "logger.hpp" - -static const char* TAG = "DiagProtocolStack"; - -DiagProtocolStack::DiagProtocolStack() - : m_isInitialized(false) -{ -} - -DiagProtocolStack::~DiagProtocolStack() -{ - deinitialize(); -} - -bool DiagProtocolStack::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3300, asf::logger::Criticality::LOW, "DiagProtocolStack initialized successfully"); - return true; -} - -bool DiagProtocolStack::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool DiagProtocolStack::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.hpp b/draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.hpp deleted file mode 100644 index a12db34..0000000 --- a/draft- to be removed SW/components/drivers/diag_protocol_stack/com/diag_protocol_stack.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file diag_protocol_stack.hpp - * @brief DiagProtocolStack component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef DIAG_PROTOCOL_STACK_HPP -#define DIAG_PROTOCOL_STACK_HPP - -#include - -/** - * @brief DiagProtocolStack class - * - * Component description goes here. - */ -class DiagProtocolStack -{ -public: - DiagProtocolStack(); - ~DiagProtocolStack(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // DIAG_PROTOCOL_STACK_HPP diff --git a/draft- to be removed SW/components/drivers/diag_protocol_stack/logging_data.csv b/draft- to be removed SW/components/drivers/diag_protocol_stack/logging_data.csv deleted file mode 100644 index 3f885ad..0000000 --- a/draft- to be removed SW/components/drivers/diag_protocol_stack/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3300,DiagProtocolStack,INFO,Low,DiagProtocolStack initialized successfully diff --git a/draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.py b/draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.py deleted file mode 100644 index 85d7dba..0000000 --- a/draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_diag_protocol_stack_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "DiagProtocolStack initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_diag_protocol_stack_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.test_scenario.xml deleted file mode 100644 index 44e412c..0000000 --- a/draft- to be removed SW/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - DIAG_PROTOCOL_STACK_INIT_TEST - - python components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/diag_protocol_stack/test/test_diag_protocol_stack.cpp b/draft- to be removed SW/components/drivers/diag_protocol_stack/test/test_diag_protocol_stack.cpp deleted file mode 100644 index 7e0bccd..0000000 --- a/draft- to be removed SW/components/drivers/diag_protocol_stack/test/test_diag_protocol_stack.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_diag_protocol_stack.cpp - * @brief Unit tests for DiagProtocolStack component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "diag_protocol_stack.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_diag_protocol_stack_initialize(void) -{ - DiagProtocolStack comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_diag_protocol_stack_deinitialize(void) -{ - DiagProtocolStack comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/network_stack/CMakeLists.txt b/draft- to be removed SW/components/drivers/network_stack/CMakeLists.txt deleted file mode 100644 index 7e36f8d..0000000 --- a/draft- to be removed SW/components/drivers/network_stack/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/network_stack.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/network_stack/com/network_stack.cpp b/draft- to be removed SW/components/drivers/network_stack/com/network_stack.cpp deleted file mode 100644 index c66760a..0000000 --- a/draft- to be removed SW/components/drivers/network_stack/com/network_stack.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file network_stack.cpp - * @brief NetworkStack component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "network_stack.hpp" -#include "logger.hpp" - -static const char* TAG = "NetworkStack"; - -NetworkStack::NetworkStack() - : m_isInitialized(false) -{ -} - -NetworkStack::~NetworkStack() -{ - deinitialize(); -} - -bool NetworkStack::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3100, asf::logger::Criticality::LOW, "NetworkStack initialized successfully"); - return true; -} - -bool NetworkStack::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool NetworkStack::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/network_stack/com/network_stack.hpp b/draft- to be removed SW/components/drivers/network_stack/com/network_stack.hpp deleted file mode 100644 index 1b384cf..0000000 --- a/draft- to be removed SW/components/drivers/network_stack/com/network_stack.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file network_stack.hpp - * @brief NetworkStack component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef NETWORK_STACK_HPP -#define NETWORK_STACK_HPP - -#include - -/** - * @brief NetworkStack class - * - * Component description goes here. - */ -class NetworkStack -{ -public: - NetworkStack(); - ~NetworkStack(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // NETWORK_STACK_HPP diff --git a/draft- to be removed SW/components/drivers/network_stack/logging_data.csv b/draft- to be removed SW/components/drivers/network_stack/logging_data.csv deleted file mode 100644 index 800cdf9..0000000 --- a/draft- to be removed SW/components/drivers/network_stack/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3100,NetworkStack,INFO,Low,NetworkStack initialized successfully diff --git a/draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.py b/draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.py deleted file mode 100644 index 40f0e71..0000000 --- a/draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_network_stack_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "NetworkStack initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_network_stack_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.test_scenario.xml deleted file mode 100644 index e8a5f90..0000000 --- a/draft- to be removed SW/components/drivers/network_stack/test/network_stack_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - NETWORK_STACK_INIT_TEST - - python components/drivers/network_stack/test/network_stack_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/network_stack/test/test_network_stack.cpp b/draft- to be removed SW/components/drivers/network_stack/test/test_network_stack.cpp deleted file mode 100644 index 175da76..0000000 --- a/draft- to be removed SW/components/drivers/network_stack/test/test_network_stack.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_network_stack.cpp - * @brief Unit tests for NetworkStack component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "network_stack.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_network_stack_initialize(void) -{ - NetworkStack comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_network_stack_deinitialize(void) -{ - NetworkStack comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/nvm/CMakeLists.txt b/draft- to be removed SW/components/drivers/nvm/CMakeLists.txt deleted file mode 100644 index 24b9217..0000000 --- a/draft- to be removed SW/components/drivers/nvm/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/nvm.cpp" - INCLUDE_DIRS "com" - REQUIRES nvs_flash logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/drivers/nvm/com/nvm.cpp b/draft- to be removed SW/components/drivers/nvm/com/nvm.cpp deleted file mode 100644 index e51a134..0000000 --- a/draft- to be removed SW/components/drivers/nvm/com/nvm.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file nvm.cpp - * @brief NVM driver component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "nvm.hpp" -#include "logger.hpp" - -static const char* TAG = "NvmDriver"; - -NvmDriver::NvmDriver() - : m_isInitialized(false) -{ -} - -NvmDriver::~NvmDriver() -{ - deinitialize(); -} - -bool NvmDriver::initialize() -{ - // TODO: Implement NVM initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3200, asf::logger::Criticality::LOW, "NVM driver initialized successfully"); - return true; -} - -bool NvmDriver::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement NVM deinitialization - m_isInitialized = false; - return true; -} - -NvmResult NvmDriver::read(const char* key, void* value, size_t* length) -{ - if (!m_isInitialized || key == nullptr || value == nullptr || length == nullptr) - { - return NvmResult::ERROR_INVALID_PARAM; - } - - // TODO: Implement NVM read - (void)key; - (void)value; - (void)length; - return NvmResult::OK; -} - -NvmResult NvmDriver::write(const char* key, const void* value, size_t length) -{ - if (!m_isInitialized || key == nullptr || value == nullptr) - { - return NvmResult::ERROR_INVALID_PARAM; - } - - // TODO: Implement NVM write - (void)key; - (void)value; - (void)length; - return NvmResult::OK; -} - -NvmResult NvmDriver::erase(const char* key) -{ - if (!m_isInitialized || key == nullptr) - { - return NvmResult::ERROR_INVALID_PARAM; - } - - // TODO: Implement NVM erase - (void)key; - return NvmResult::OK; -} - -bool NvmDriver::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/nvm/com/nvm.hpp b/draft- to be removed SW/components/drivers/nvm/com/nvm.hpp deleted file mode 100644 index db9ce33..0000000 --- a/draft- to be removed SW/components/drivers/nvm/com/nvm.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @file nvm.hpp - * @brief NVM driver component header - Non-volatile memory management - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef NVM_HPP -#define NVM_HPP - -#include -#include - -/** - * @brief NVM result enumeration - */ -enum class NvmResult -{ - OK, - ERROR_INVALID_PARAM, - ERROR_NOT_FOUND, - ERROR_FAIL -}; - -/** - * @brief NVM driver class - * - * Provides non-volatile memory management functionality. - */ -class NvmDriver -{ -public: - NvmDriver(); - ~NvmDriver(); - - bool initialize(); - bool deinitialize(); - NvmResult read(const char* key, void* value, size_t* length); - NvmResult write(const char* key, const void* value, size_t length); - NvmResult erase(const char* key); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // NVM_HPP - diff --git a/draft- to be removed SW/components/drivers/nvm/logging_data.csv b/draft- to be removed SW/components/drivers/nvm/logging_data.csv deleted file mode 100644 index 7fee445..0000000 --- a/draft- to be removed SW/components/drivers/nvm/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3200,NVM,INFO,Low,NVM driver initialized successfully diff --git a/draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.py b/draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.py deleted file mode 100644 index cadc818..0000000 --- a/draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_nvm_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "NVM driver initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_nvm_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.test_scenario.xml deleted file mode 100644 index 207d2a1..0000000 --- a/draft- to be removed SW/components/drivers/nvm/test/nvm_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - NVM_INIT_TEST - - python components/drivers/nvm/test/nvm_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/nvm/test/test_nvm.cpp b/draft- to be removed SW/components/drivers/nvm/test/test_nvm.cpp deleted file mode 100644 index 9068cf4..0000000 --- a/draft- to be removed SW/components/drivers/nvm/test/test_nvm.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file test_nvm.cpp - * @brief Unit tests for NVM driver component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "nvm.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_nvm_initialize(void) -{ - NvmDriver nvm; - bool result = nvm.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(nvm.isInitialized()); -} - -void test_nvm_read_write(void) -{ - NvmDriver nvm; - nvm.initialize(); - - uint32_t writeValue = 12345; - size_t length = sizeof(writeValue); - - NvmResult result = nvm.write("test_key", &writeValue, length); - TEST_ASSERT_EQUAL(NvmResult::OK, result); - - uint32_t readValue = 0; - result = nvm.read("test_key", &readValue, &length); - TEST_ASSERT_EQUAL(NvmResult::OK, result); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/drivers/sensors/ammonia/CMakeLists.txt b/draft- to be removed SW/components/drivers/sensors/ammonia/CMakeLists.txt deleted file mode 100644 index 24e75bd..0000000 --- a/draft- to be removed SW/components/drivers/sensors/ammonia/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/ammonia.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.cpp b/draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.cpp deleted file mode 100644 index 58730c6..0000000 --- a/draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file ammonia.cpp - * @brief Ammonia component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "ammonia.hpp" -#include "logger.hpp" - -static const char* TAG = "Ammonia"; - -Ammonia::Ammonia() - : m_isInitialized(false) -{ -} - -Ammonia::~Ammonia() -{ - deinitialize(); -} - -bool Ammonia::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3400, asf::logger::Criticality::LOW, "Ammonia initialized successfully"); - return true; -} - -bool Ammonia::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Ammonia::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.hpp b/draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.hpp deleted file mode 100644 index 27bfd67..0000000 --- a/draft- to be removed SW/components/drivers/sensors/ammonia/com/ammonia.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file ammonia.hpp - * @brief Ammonia component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef AMMONIA_HPP -#define AMMONIA_HPP - -#include - -/** - * @brief Ammonia class - * - * Component description goes here. - */ -class Ammonia -{ -public: - Ammonia(); - ~Ammonia(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // AMMONIA_HPP diff --git a/draft- to be removed SW/components/drivers/sensors/ammonia/logging_data.csv b/draft- to be removed SW/components/drivers/sensors/ammonia/logging_data.csv deleted file mode 100644 index 3deaea7..0000000 --- a/draft- to be removed SW/components/drivers/sensors/ammonia/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3400,Ammonia,INFO,Low,Ammonia initialized successfully diff --git a/draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.py b/draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.py deleted file mode 100644 index 80bbb0e..0000000 --- a/draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_ammonia_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Ammonia initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_ammonia_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.test_scenario.xml deleted file mode 100644 index 317b929..0000000 --- a/draft- to be removed SW/components/drivers/sensors/ammonia/test/ammonia_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - AMMONIA_INIT_TEST - - python components/drivers/sensors/ammonia/test/ammonia_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/sensors/ammonia/test/test_ammonia.cpp b/draft- to be removed SW/components/drivers/sensors/ammonia/test/test_ammonia.cpp deleted file mode 100644 index fbe5233..0000000 --- a/draft- to be removed SW/components/drivers/sensors/ammonia/test/test_ammonia.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_ammonia.cpp - * @brief Unit tests for Ammonia component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "ammonia.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_ammonia_initialize(void) -{ - Ammonia comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_ammonia_deinitialize(void) -{ - Ammonia comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/sensors/co2/CMakeLists.txt b/draft- to be removed SW/components/drivers/sensors/co2/CMakeLists.txt deleted file mode 100644 index b8a97d9..0000000 --- a/draft- to be removed SW/components/drivers/sensors/co2/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/co2.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/sensors/co2/com/co2.cpp b/draft- to be removed SW/components/drivers/sensors/co2/com/co2.cpp deleted file mode 100644 index 198682e..0000000 --- a/draft- to be removed SW/components/drivers/sensors/co2/com/co2.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file co2.cpp - * @brief Co2 component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "co2.hpp" -#include "logger.hpp" - -static const char* TAG = "Co2"; - -Co2::Co2() - : m_isInitialized(false) -{ -} - -Co2::~Co2() -{ - deinitialize(); -} - -bool Co2::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3500, asf::logger::Criticality::LOW, "Co2 initialized successfully"); - return true; -} - -bool Co2::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Co2::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/sensors/co2/com/co2.hpp b/draft- to be removed SW/components/drivers/sensors/co2/com/co2.hpp deleted file mode 100644 index 96c3c05..0000000 --- a/draft- to be removed SW/components/drivers/sensors/co2/com/co2.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file co2.hpp - * @brief Co2 component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef CO2_HPP -#define CO2_HPP - -#include - -/** - * @brief Co2 class - * - * Component description goes here. - */ -class Co2 -{ -public: - Co2(); - ~Co2(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // CO2_HPP diff --git a/draft- to be removed SW/components/drivers/sensors/co2/logging_data.csv b/draft- to be removed SW/components/drivers/sensors/co2/logging_data.csv deleted file mode 100644 index 0909b5f..0000000 --- a/draft- to be removed SW/components/drivers/sensors/co2/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3500,Co2,INFO,Low,Co2 initialized successfully diff --git a/draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.py b/draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.py deleted file mode 100644 index 6497e1f..0000000 --- a/draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_co2_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Co2 initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_co2_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.test_scenario.xml deleted file mode 100644 index cd3eab2..0000000 --- a/draft- to be removed SW/components/drivers/sensors/co2/test/co2_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - CO2_INIT_TEST - - python components/drivers/sensors/co2/test/co2_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/sensors/co2/test/test_co2.cpp b/draft- to be removed SW/components/drivers/sensors/co2/test/test_co2.cpp deleted file mode 100644 index fa340ac..0000000 --- a/draft- to be removed SW/components/drivers/sensors/co2/test/test_co2.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_co2.cpp - * @brief Unit tests for Co2 component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "co2.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_co2_initialize(void) -{ - Co2 comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_co2_deinitialize(void) -{ - Co2 comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/sensors/humidity/CMakeLists.txt b/draft- to be removed SW/components/drivers/sensors/humidity/CMakeLists.txt deleted file mode 100644 index 59327d7..0000000 --- a/draft- to be removed SW/components/drivers/sensors/humidity/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/humidity.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.cpp b/draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.cpp deleted file mode 100644 index f2c4305..0000000 --- a/draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file humidity.cpp - * @brief Humidity component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "humidity.hpp" -#include "logger.hpp" - -static const char* TAG = "Humidity"; - -Humidity::Humidity() - : m_isInitialized(false) -{ -} - -Humidity::~Humidity() -{ - deinitialize(); -} - -bool Humidity::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3600, asf::logger::Criticality::LOW, "Humidity initialized successfully"); - return true; -} - -bool Humidity::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Humidity::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.hpp b/draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.hpp deleted file mode 100644 index 936b0e8..0000000 --- a/draft- to be removed SW/components/drivers/sensors/humidity/com/humidity.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file humidity.hpp - * @brief Humidity component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef HUMIDITY_HPP -#define HUMIDITY_HPP - -#include - -/** - * @brief Humidity class - * - * Component description goes here. - */ -class Humidity -{ -public: - Humidity(); - ~Humidity(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // HUMIDITY_HPP diff --git a/draft- to be removed SW/components/drivers/sensors/humidity/logging_data.csv b/draft- to be removed SW/components/drivers/sensors/humidity/logging_data.csv deleted file mode 100644 index 10bf6c3..0000000 --- a/draft- to be removed SW/components/drivers/sensors/humidity/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3600,Humidity,INFO,Low,Humidity initialized successfully diff --git a/draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.py b/draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.py deleted file mode 100644 index a2b11fa..0000000 --- a/draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_humidity_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Humidity initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_humidity_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.test_scenario.xml deleted file mode 100644 index 9f9a7e3..0000000 --- a/draft- to be removed SW/components/drivers/sensors/humidity/test/humidity_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - HUMIDITY_INIT_TEST - - python components/drivers/sensors/humidity/test/humidity_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/sensors/humidity/test/test_humidity.cpp b/draft- to be removed SW/components/drivers/sensors/humidity/test/test_humidity.cpp deleted file mode 100644 index 4d5fb6f..0000000 --- a/draft- to be removed SW/components/drivers/sensors/humidity/test/test_humidity.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_humidity.cpp - * @brief Unit tests for Humidity component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "humidity.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_humidity_initialize(void) -{ - Humidity comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_humidity_deinitialize(void) -{ - Humidity comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/sensors/light/CMakeLists.txt b/draft- to be removed SW/components/drivers/sensors/light/CMakeLists.txt deleted file mode 100644 index 8aff0da..0000000 --- a/draft- to be removed SW/components/drivers/sensors/light/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/light.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/sensors/light/com/light.cpp b/draft- to be removed SW/components/drivers/sensors/light/com/light.cpp deleted file mode 100644 index 06b4b1a..0000000 --- a/draft- to be removed SW/components/drivers/sensors/light/com/light.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file light.cpp - * @brief Light component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "light.hpp" -#include "logger.hpp" - -static const char* TAG = "Light"; - -Light::Light() - : m_isInitialized(false) -{ -} - -Light::~Light() -{ - deinitialize(); -} - -bool Light::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3700, asf::logger::Criticality::LOW, "Light initialized successfully"); - return true; -} - -bool Light::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Light::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/sensors/light/com/light.hpp b/draft- to be removed SW/components/drivers/sensors/light/com/light.hpp deleted file mode 100644 index 9a4c949..0000000 --- a/draft- to be removed SW/components/drivers/sensors/light/com/light.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file light.hpp - * @brief Light component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef LIGHT_HPP -#define LIGHT_HPP - -#include - -/** - * @brief Light class - * - * Component description goes here. - */ -class Light -{ -public: - Light(); - ~Light(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // LIGHT_HPP diff --git a/draft- to be removed SW/components/drivers/sensors/light/logging_data.csv b/draft- to be removed SW/components/drivers/sensors/light/logging_data.csv deleted file mode 100644 index a307163..0000000 --- a/draft- to be removed SW/components/drivers/sensors/light/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3700,Light,INFO,Low,Light initialized successfully diff --git a/draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.py b/draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.py deleted file mode 100644 index d2267f7..0000000 --- a/draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_light_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Light initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_light_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.test_scenario.xml deleted file mode 100644 index 0413d94..0000000 --- a/draft- to be removed SW/components/drivers/sensors/light/test/light_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - LIGHT_INIT_TEST - - python components/drivers/sensors/light/test/light_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/sensors/light/test/test_light.cpp b/draft- to be removed SW/components/drivers/sensors/light/test/test_light.cpp deleted file mode 100644 index bd8b4c3..0000000 --- a/draft- to be removed SW/components/drivers/sensors/light/test/test_light.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_light.cpp - * @brief Unit tests for Light component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "light.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_light_initialize(void) -{ - Light comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_light_deinitialize(void) -{ - Light comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/sensors/temprature/CMakeLists.txt b/draft- to be removed SW/components/drivers/sensors/temprature/CMakeLists.txt deleted file mode 100644 index fba2eed..0000000 --- a/draft- to be removed SW/components/drivers/sensors/temprature/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/temprature.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.cpp b/draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.cpp deleted file mode 100644 index 931a036..0000000 --- a/draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file temprature.cpp - * @brief Temperature component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "temprature.hpp" -#include "logger.hpp" - -static const char* TAG = "Temperature"; - -Temperature::Temperature() - : m_isInitialized(false) -{ -} - -Temperature::~Temperature() -{ - deinitialize(); -} - -bool Temperature::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3800, asf::logger::Criticality::LOW, "Temperature initialized successfully"); - return true; -} - -bool Temperature::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Temperature::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.hpp b/draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.hpp deleted file mode 100644 index e9cf997..0000000 --- a/draft- to be removed SW/components/drivers/sensors/temprature/com/temprature.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file temprature.hpp - * @brief Temperature component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef TEMPRATURE_HPP -#define TEMPRATURE_HPP - -#include - -/** - * @brief Temperature class - * - * Component description goes here. - */ -class Temperature -{ -public: - Temperature(); - ~Temperature(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // TEMPRATURE_HPP diff --git a/draft- to be removed SW/components/drivers/sensors/temprature/logging_data.csv b/draft- to be removed SW/components/drivers/sensors/temprature/logging_data.csv deleted file mode 100644 index 6b5d499..0000000 --- a/draft- to be removed SW/components/drivers/sensors/temprature/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3800,Temperature,INFO,Low,Temperature initialized successfully diff --git a/draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.py b/draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.py deleted file mode 100644 index b02592c..0000000 --- a/draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_temperature_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Temperature initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_temperature_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.test_scenario.xml deleted file mode 100644 index 70cb4fa..0000000 --- a/draft- to be removed SW/components/drivers/sensors/temprature/test/temprature_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - TEMPRATURE_INIT_TEST - - python components/drivers/sensors/temprature/test/temprature_init_test.py - - - - diff --git a/draft- to be removed SW/components/drivers/sensors/temprature/test/test_temprature.cpp b/draft- to be removed SW/components/drivers/sensors/temprature/test/test_temprature.cpp deleted file mode 100644 index fdcdae6..0000000 --- a/draft- to be removed SW/components/drivers/sensors/temprature/test/test_temprature.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_temprature.cpp - * @brief Unit tests for Temperature component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "temprature.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_temprature_initialize(void) -{ - Temperature comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_temprature_deinitialize(void) -{ - Temperature comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/sensors/voc/CMakeLists.txt b/draft- to be removed SW/components/drivers/sensors/voc/CMakeLists.txt deleted file mode 100644 index 541c8bf..0000000 --- a/draft- to be removed SW/components/drivers/sensors/voc/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/voc.cpp" - INCLUDE_DIRS "com" - REQUIRES logger -) diff --git a/draft- to be removed SW/components/drivers/sensors/voc/com/voc.cpp b/draft- to be removed SW/components/drivers/sensors/voc/com/voc.cpp deleted file mode 100644 index a3d682a..0000000 --- a/draft- to be removed SW/components/drivers/sensors/voc/com/voc.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file voc.cpp - * @brief Voc component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "voc.hpp" -#include "logger.hpp" - -static const char* TAG = "Voc"; - -Voc::Voc() - : m_isInitialized(false) -{ -} - -Voc::~Voc() -{ - deinitialize(); -} - -bool Voc::initialize() -{ - // TODO: Implement initialization - m_isInitialized = true; - ASF_LOGI(TAG, 3900, asf::logger::Criticality::LOW, "Voc initialized successfully"); - return true; -} - -bool Voc::deinitialize() -{ - if (!m_isInitialized) - { - return false; - } - - // TODO: Implement deinitialization - m_isInitialized = false; - return true; -} - -bool Voc::isInitialized() const -{ - return m_isInitialized; -} diff --git a/draft- to be removed SW/components/drivers/sensors/voc/com/voc.hpp b/draft- to be removed SW/components/drivers/sensors/voc/com/voc.hpp deleted file mode 100644 index e2f7143..0000000 --- a/draft- to be removed SW/components/drivers/sensors/voc/com/voc.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file voc.hpp - * @brief Voc component header - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef VOC_HPP -#define VOC_HPP - -#include - -/** - * @brief Voc class - * - * Component description goes here. - */ -class Voc -{ -public: - Voc(); - ~Voc(); - - bool initialize(); - bool deinitialize(); - bool isInitialized() const; - -private: - bool m_isInitialized; -}; - -#endif // VOC_HPP diff --git a/draft- to be removed SW/components/drivers/sensors/voc/logging_data.csv b/draft- to be removed SW/components/drivers/sensors/voc/logging_data.csv deleted file mode 100644 index ba3a97d..0000000 --- a/draft- to be removed SW/components/drivers/sensors/voc/logging_data.csv +++ /dev/null @@ -1,2 +0,0 @@ -ID,Component,Level,Criticality,Message -3900,Voc,INFO,Low,Voc initialized successfully diff --git a/draft- to be removed SW/components/drivers/sensors/voc/test/test_voc.cpp b/draft- to be removed SW/components/drivers/sensors/voc/test/test_voc.cpp deleted file mode 100644 index 1e33186..0000000 --- a/draft- to be removed SW/components/drivers/sensors/voc/test/test_voc.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file test_voc.cpp - * @brief Unit tests for Voc component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "voc.hpp" - -extern "C" { - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_voc_initialize(void) -{ - Voc comp; - bool result = comp.initialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(comp.isInitialized()); -} - -void test_voc_deinitialize(void) -{ - Voc comp; - comp.initialize(); - - bool result = comp.deinitialize(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(comp.isInitialized()); -} - -} // extern "C" diff --git a/draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.py b/draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.py deleted file mode 100644 index 39ba265..0000000 --- a/draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys -import os -import time - -folder_path = os.path.abspath(os.path.join("components", "system_tests")) -if folder_path not in sys.path: - sys.path.append(folder_path) - -from scan_serial import ESP32Runner - -def test_voc_initialize(): - runner = ESP32Runner(mode="SIM", port="COM9") - runner.start() - print("--- QEMU Runner Started ---", flush=True) - try: - start_time = time.time() - while time.time() - start_time < 30: - line = runner.get_line(timeout=1.0) - if line: - print(line, flush=True) - if "Voc initialized successfully" in line: - print("SUCCESS CRITERIA MET!", flush=True) - return 0 - if runner.process.poll() is not None: - print(f"Process exited with code: {runner.process.returncode}", flush=True) - return 1 - finally: - runner.stop() - print("Done.", flush=True) - return 1 - -if __name__ == "__main__": - exit_code = test_voc_initialize() - sys.exit(exit_code) diff --git a/draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.test_scenario.xml b/draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.test_scenario.xml deleted file mode 100644 index 7a70d3d..0000000 --- a/draft- to be removed SW/components/drivers/sensors/voc/test/voc_init_test.test_scenario.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SIMULATE - - - VOC_INIT_TEST - - python components/drivers/sensors/voc/test/voc_init_test.py - - - - diff --git a/draft- to be removed SW/components/os/swtimer/CMakeLists.txt b/draft- to be removed SW/components/os/swtimer/CMakeLists.txt deleted file mode 100644 index c2e6759..0000000 --- a/draft- to be removed SW/components/os/swtimer/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register( - SRCS "com/swtimer.cpp" - INCLUDE_DIRS "com" -) diff --git a/draft- to be removed SW/components/os/swtimer/com/swtimer.cpp b/draft- to be removed SW/components/os/swtimer/com/swtimer.cpp deleted file mode 100644 index bae9087..0000000 --- a/draft- to be removed SW/components/os/swtimer/com/swtimer.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @file swtimer.cpp - * @brief Software Timer component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "swtimer.hpp" - -SoftwareTimer::SoftwareTimer() - : m_isActive(false) - , m_interval(0) - , m_type(TimerType::ONE_SHOT) -{ -} - -SoftwareTimer::~SoftwareTimer() -{ - stop(); -} - -bool SoftwareTimer::create(uint32_t interval_ms, TimerType type, TimerCallback callback) -{ - if (interval_ms == 0) - { - return false; - } - - m_interval = interval_ms; - m_type = type; - m_callback = callback; - - return true; -} - -bool SoftwareTimer::start() -{ - if (m_callback == nullptr) - { - return false; - } - - m_isActive = true; - // TODO: Implement actual timer start logic - return true; -} - -bool SoftwareTimer::stop() -{ - if (!m_isActive) - { - return false; - } - - m_isActive = false; - // TODO: Implement actual timer stop logic - return true; -} - -bool SoftwareTimer::reset() -{ - if (!m_isActive) - { - return false; - } - - stop(); - return start(); -} - -bool SoftwareTimer::isActive() const -{ - return m_isActive; -} - -uint32_t SoftwareTimer::getInterval() const -{ - return m_interval; -} - diff --git a/draft- to be removed SW/components/os/swtimer/com/swtimer.hpp b/draft- to be removed SW/components/os/swtimer/com/swtimer.hpp deleted file mode 100644 index 61b361c..0000000 --- a/draft- to be removed SW/components/os/swtimer/com/swtimer.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file swtimer.hpp - * @brief Software Timer component header - Manages time-based events and scheduling - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef SWTIMER_HPP -#define SWTIMER_HPP - -#include -#include - -/** - * @brief Timer type enumeration - */ -enum class TimerType -{ - ONE_SHOT, ///< Timer expires once and stops - PERIODIC ///< Timer repeats until stopped -}; - -/** - * @brief Timer callback function type - */ -using TimerCallback = std::function; - -/** - * @brief Software Timer class - * - * Provides functionality to create, start, stop, and manage timers - * that can trigger callbacks after specified intervals. - */ -class SoftwareTimer -{ -public: - /** - * @brief Constructor - */ - SoftwareTimer(); - - /** - * @brief Destructor - */ - ~SoftwareTimer(); - - /** - * @brief Create a new timer - * @param interval_ms Timer interval in milliseconds - * @param type Timer type (ONE_SHOT or PERIODIC) - * @param callback Function to call when timer expires - * @return true if timer created successfully, false otherwise - */ - bool create(uint32_t interval_ms, TimerType type, TimerCallback callback); - - /** - * @brief Start the timer - * @return true if started successfully, false otherwise - */ - bool start(); - - /** - * @brief Stop the timer - * @return true if stopped successfully, false otherwise - */ - bool stop(); - - /** - * @brief Reset the timer - * @return true if reset successfully, false otherwise - */ - bool reset(); - - /** - * @brief Check if timer is active - * @return true if timer is running, false otherwise - */ - bool isActive() const; - - /** - * @brief Get the timer interval - * @return Timer interval in milliseconds - */ - uint32_t getInterval() const; - -private: - bool m_isActive; ///< Timer active state - uint32_t m_interval; ///< Timer interval in milliseconds - TimerType m_type; ///< Timer type - TimerCallback m_callback; ///< Callback function -}; - -#endif // SWTIMER_HPP - diff --git a/draft- to be removed SW/components/os/swtimer/test/test_swtimer.cpp b/draft- to be removed SW/components/os/swtimer/test/test_swtimer.cpp deleted file mode 100644 index 076a4ed..0000000 --- a/draft- to be removed SW/components/os/swtimer/test/test_swtimer.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file test_swtimer.cpp - * @brief Unit tests for Software Timer component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "swtimer.hpp" - -extern "C" { - -void setUp(void) -{ - // Set up test fixtures before each test -} - -void tearDown(void) -{ - // Clean up test fixtures after each test -} - -/** - * @brief Test timer creation with valid parameters - */ -void test_swtimer_create_valid(void) -{ - SoftwareTimer timer; - bool result = timer.create(1000, TimerType::ONE_SHOT, [](){}); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(timer.isActive()); - TEST_ASSERT_EQUAL(1000, timer.getInterval()); -} - -/** - * @brief Test timer creation with zero interval - */ -void test_swtimer_create_zero_interval(void) -{ - SoftwareTimer timer; - bool result = timer.create(0, TimerType::ONE_SHOT, [](){}); - TEST_ASSERT_FALSE(result); -} - -/** - * @brief Test timer start - */ -void test_swtimer_start(void) -{ - SoftwareTimer timer; - timer.create(1000, TimerType::ONE_SHOT, [](){}); - - bool result = timer.start(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(timer.isActive()); -} - -/** - * @brief Test timer stop - */ -void test_swtimer_stop(void) -{ - SoftwareTimer timer; - timer.create(1000, TimerType::ONE_SHOT, [](){}); - timer.start(); - - bool result = timer.stop(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_FALSE(timer.isActive()); -} - -/** - * @brief Test timer reset - */ -void test_swtimer_reset(void) -{ - SoftwareTimer timer; - timer.create(1000, TimerType::ONE_SHOT, [](){}); - timer.start(); - - bool result = timer.reset(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_TRUE(timer.isActive()); -} - -/** - * @brief Test timer one-shot type - */ -void test_swtimer_one_shot(void) -{ - SoftwareTimer timer; - timer.create(1000, TimerType::ONE_SHOT, [](){}); - TEST_ASSERT_TRUE(timer.start()); -} - -/** - * @brief Test timer periodic type - */ -void test_swtimer_periodic(void) -{ - SoftwareTimer timer; - timer.create(500, TimerType::PERIODIC, [](){}); - TEST_ASSERT_TRUE(timer.start()); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/os/task/CMakeLists.txt b/draft- to be removed SW/components/os/task/CMakeLists.txt deleted file mode 100644 index 5774f34..0000000 --- a/draft- to be removed SW/components/os/task/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register( - SRCS "com/task.cpp" - INCLUDE_DIRS "com" -) diff --git a/draft- to be removed SW/components/os/task/com/task.cpp b/draft- to be removed SW/components/os/task/com/task.cpp deleted file mode 100644 index 31141cd..0000000 --- a/draft- to be removed SW/components/os/task/com/task.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file task.cpp - * @brief Task component implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "task.hpp" - -Task::Task() - : m_state(TaskState::CREATED) - , m_priority(TaskPriority::NORMAL) - , m_handle(nullptr) -{ -} - -Task::~Task() -{ - destroy(); -} - -bool Task::create(const TaskConfig& config, void (*taskFunction)(void*), void* arg) -{ - if (config.name == nullptr || taskFunction == nullptr) - { - return false; - } - - if (config.stackSize < 2048) // Minimum stack size - { - return false; - } - - m_priority = config.priority; - m_state = TaskState::CREATED; - // TODO: Implement actual task creation logic - m_handle = (void*)1; // Placeholder - - return true; -} - -bool Task::destroy() -{ - if (m_state == TaskState::DELETED) - { - return false; - } - - // TODO: Implement actual task deletion logic - m_state = TaskState::DELETED; - m_handle = nullptr; - - return true; -} - -bool Task::suspend() -{ - if (m_state != TaskState::RUNNING && m_state != TaskState::READY) - { - return false; - } - - // TODO: Implement actual task suspension logic - m_state = TaskState::SUSPENDED; - - return true; -} - -bool Task::resume() -{ - if (m_state != TaskState::SUSPENDED) - { - return false; - } - - // TODO: Implement actual task resumption logic - m_state = TaskState::READY; - - return true; -} - -TaskState Task::getState() const -{ - return m_state; -} - -TaskPriority Task::getPriority() const -{ - return m_priority; -} - -bool Task::setPriority(TaskPriority priority) -{ - m_priority = priority; - // TODO: Implement actual priority change logic - return true; -} - -void Task::delay(uint32_t delayMs) -{ - // TODO: Implement actual delay logic - (void)delayMs; -} - -Task* Task::getCurrentTask() -{ - // TODO: Implement actual current task retrieval - return nullptr; -} - diff --git a/draft- to be removed SW/components/os/task/com/task.hpp b/draft- to be removed SW/components/os/task/com/task.hpp deleted file mode 100644 index 092710d..0000000 --- a/draft- to be removed SW/components/os/task/com/task.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @file task.hpp - * @brief Task component header - Manages system tasks and their lifecycle - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#ifndef TASK_HPP -#define TASK_HPP - -#include -#include - -/** - * @brief Task priority levels - */ -enum class TaskPriority -{ - LOW = 1, - NORMAL = 5, - HIGH = 10, - CRITICAL = 20 -}; - -/** - * @brief Task state enumeration - */ -enum class TaskState -{ - CREATED, - READY, - RUNNING, - BLOCKED, - SUSPENDED, - DELETED -}; - -/** - * @brief Task configuration structure - */ -struct TaskConfig -{ - const char* name; ///< Task name - uint32_t stackSize; ///< Stack size in bytes - TaskPriority priority; ///< Task priority - uint32_t coreId; ///< CPU core ID (0 or 1 for ESP32) -}; - -/** - * @brief Task class - * - * Provides functionality to create, manage, and control tasks - * with scheduling, prioritization, and resource management. - */ -class Task -{ -public: - /** - * @brief Constructor - */ - Task(); - - /** - * @brief Destructor - */ - ~Task(); - - /** - * @brief Create a new task - * @param config Task configuration - * @param taskFunction Function to run in the task - * @param arg Argument to pass to task function - * @return true if task created successfully, false otherwise - */ - bool create(const TaskConfig& config, void (*taskFunction)(void*), void* arg); - - /** - * @brief Delete the task - * @return true if deleted successfully, false otherwise - */ - bool destroy(); - - /** - * @brief Suspend the task - * @return true if suspended successfully, false otherwise - */ - bool suspend(); - - /** - * @brief Resume the task - * @return true if resumed successfully, false otherwise - */ - bool resume(); - - /** - * @brief Get the current task state - * @return Current task state - */ - TaskState getState() const; - - /** - * @brief Get the task priority - * @return Task priority level - */ - TaskPriority getPriority() const; - - /** - * @brief Set the task priority - * @param priority New priority level - * @return true if priority set successfully, false otherwise - */ - bool setPriority(TaskPriority priority); - - /** - * @brief Delay task execution - * @param delayMs Delay in milliseconds - */ - static void delay(uint32_t delayMs); - - /** - * @brief Get current running task handle - * @return Task handle or nullptr if not running - */ - static Task* getCurrentTask(); - -private: - TaskState m_state; - TaskPriority m_priority; - void* m_handle; -}; - -#endif // TASK_HPP - diff --git a/draft- to be removed SW/components/os/task/test/test_task.cpp b/draft- to be removed SW/components/os/task/test/test_task.cpp deleted file mode 100644 index d075797..0000000 --- a/draft- to be removed SW/components/os/task/test/test_task.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file test_task.cpp - * @brief Unit tests for Task component - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "task.hpp" - -extern "C" { - -void setUp(void) -{ - // Set up test fixtures before each test -} - -void tearDown(void) -{ - // Clean up test fixtures after each test -} - -/** - * @brief Test task creation with valid parameters - */ -void test_task_create_valid(void) -{ - Task task; - TaskConfig config = {"test_task", 4096, TaskPriority::NORMAL, 0}; - bool result = task.create(config, [](void* arg){(void)arg;}, nullptr); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_EQUAL(TaskState::CREATED, task.getState()); -} - -/** - * @brief Test task creation with invalid parameters - */ -void test_task_create_invalid_name(void) -{ - Task task; - TaskConfig config = {nullptr, 4096, TaskPriority::NORMAL, 0}; - bool result = task.create(config, [](void* arg){(void)arg;}, nullptr); - TEST_ASSERT_FALSE(result); -} - -/** - * @brief Test task creation with small stack size - */ -void test_task_create_small_stack(void) -{ - Task task; - TaskConfig config = {"test_task", 1024, TaskPriority::NORMAL, 0}; - bool result = task.create(config, [](void* arg){(void)arg;}, nullptr); - TEST_ASSERT_FALSE(result); -} - -/** - * @brief Test task destroy - */ -void test_task_destroy(void) -{ - Task task; - TaskConfig config = {"test_task", 4096, TaskPriority::NORMAL, 0}; - task.create(config, [](void* arg){(void)arg;}, nullptr); - - bool result = task.destroy(); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_EQUAL(TaskState::DELETED, task.getState()); -} - -/** - * @brief Test task suspend - */ -void test_task_suspend(void) -{ - Task task; - TaskConfig config = {"test_task", 4096, TaskPriority::NORMAL, 0}; - task.create(config, [](void* arg){(void)arg;}, nullptr); - // TODO: Set task to running state for proper suspend test - - // For now, test will likely fail as task is in CREATED state - // This is expected until proper state management is implemented -} - -/** - * @brief Test task resume - */ -void test_task_resume(void) -{ - Task task; - TaskConfig config = {"test_task", 4096, TaskPriority::NORMAL, 0}; - task.create(config, [](void* arg){(void)arg;}, nullptr); - // TODO: Suspend task first, then resume -} - -/** - * @brief Test task priority get and set - */ -void test_task_priority(void) -{ - Task task; - TaskConfig config = {"test_task", 4096, TaskPriority::NORMAL, 0}; - task.create(config, [](void* arg){(void)arg;}, nullptr); - - TEST_ASSERT_EQUAL(TaskPriority::NORMAL, task.getPriority()); - - bool result = task.setPriority(TaskPriority::HIGH); - TEST_ASSERT_TRUE(result); - TEST_ASSERT_EQUAL(TaskPriority::HIGH, task.getPriority()); -} - -} // extern "C" - diff --git a/draft- to be removed SW/components/perf_tests/CMakeLists.txt b/draft- to be removed SW/components/perf_tests/CMakeLists.txt deleted file mode 100644 index 98afec2..0000000 --- a/draft- to be removed SW/components/perf_tests/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# components/perf_tests/CMakeLists.txt - -cmake_minimum_required(VERSION 3.16) - -# Build lists conditionally depending on Kconfig -set(PERF_SRCS "") -# Dependencies needed by external components that link to perf_tests (public) -set(PERF_PUBLIC_REQUIRES freertos esp_timer esp_system heap log) -# Dependencies needed only for compiling perf_tests's own sources (private) -# Always include unity since the source file includes it conditionally -set(PERF_PRIVATE_REQUIRES unity) - -if(CONFIG_ENABLE_PERF_TESTS) - list(APPEND PERF_SRCS "test/perf_tests.cpp") -endif() - -# Single registration call -idf_component_register( - SRCS ${PERF_SRCS} - INCLUDE_DIRS "." - REQUIRES ${PERF_PUBLIC_REQUIRES} # Public dependencies - PRIV_REQUIRES ${PERF_PRIVATE_REQUIRES} # Private dependencies -) \ No newline at end of file diff --git a/draft- to be removed SW/components/perf_tests/ESP32_Performance_Tests_Documentation.md b/draft- to be removed SW/components/perf_tests/ESP32_Performance_Tests_Documentation.md deleted file mode 100644 index e3e8aa7..0000000 --- a/draft- to be removed SW/components/perf_tests/ESP32_Performance_Tests_Documentation.md +++ /dev/null @@ -1,708 +0,0 @@ -# ESP32 Performance Tests - Complete Technical Documentation - -## Table of Contents -1. [Overview](#overview) -2. [System Architecture](#system-architecture) -3. [Configuration System](#configuration-system) -4. [Test Functions Detailed Analysis](#test-functions-detailed-analysis) -5. [Unity Test Framework Integration](#unity-test-framework-integration) -6. [Memory Management Analysis](#memory-management-analysis) -7. [Stack Usage Monitoring](#stack-usage-monitoring) -8. [CPU Load Analysis](#cpu-load-analysis) -9. [Build System Integration](#build-system-integration) -10. [Troubleshooting Guide](#troubleshooting-guide) - ---- - -## Overview - -The ESP32 Performance Tests system is a comprehensive monitoring solution that evaluates three critical aspects of embedded system health: - -- **Memory Consumption**: Monitors heap usage and availability -- **Stack Usage**: Tracks stack utilization for tasks -- **CPU Load**: Analyzes processor utilization across cores - -### Key Features -- **Real-time Monitoring**: Live system performance analysis -- **Multi-core Support**: Handles ESP32's dual-core architecture -- **Configurable Thresholds**: Adjustable limits for different environments -- **Unity Integration**: Professional test framework with detailed reporting -- **Conditional Compilation**: Tests only compile when enabled - ---- - -## System Architecture - -### File Structure -``` -components/perf_tests/ -├── CMakeLists.txt # Build configuration -├── test/ -│ └── perf_tests.cpp # Main test implementation -└── Kconfig # Configuration options - -main/ -├── main.cpp # Application entry point -└── CMakeLists.txt # Main component build config -``` - -### Compilation Flow -```mermaid -graph TD - A[sdkconfig] --> B[CONFIG_ENABLE_PERF_TESTS] - B --> C{Tests Enabled?} - C -->|Yes| D[Include Unity Framework] - C -->|No| E[Normal Application Mode] - D --> F[Compile Test Functions] - F --> G[Register Tests with Unity] - G --> H[Run Performance Tests] -``` - ---- - -## Configuration System - -### Primary Configuration Flags - -#### `CONFIG_ENABLE_PERF_TESTS` -- **Purpose**: Master switch for performance testing -- **Location**: `sdkconfig` -- **Effect**: When enabled, replaces normal application with test suite -- **Default**: `y` (enabled) - -#### `CONFIG_ENABLE_MEMORY_TEST` -- **Purpose**: Controls memory consumption testing -- **Tests**: Heap usage, DMA memory, SPIRAM (if available) -- **Default**: `y` - -#### `CONFIG_ENABLE_STACK_USAGE_TEST` -- **Purpose**: Controls stack monitoring tests -- **Tests**: Current task stack, idle task stacks -- **Default**: `y` - -#### `CONFIG_ENABLE_CPU_LOAD_TEST` -- **Purpose**: Controls CPU utilization analysis -- **Requirements**: `configGENERATE_RUN_TIME_STATS=1` -- **Default**: `y` - -### Threshold Configuration - -```cpp -// Memory threshold - minimum free heap considered healthy -#define PERF_MIN_HEAP_BYTES (1024U) - -// Stack thresholds - minimum unused stack (in words, not bytes) -#define PERF_MIN_STACK_WORDS_CURRENT (100U) // Current task -#define PERF_MIN_STACK_WORDS_IDLE (50U) // Idle tasks - -// CPU load tolerance - acceptable deviation from 100% -#define PERF_RUNTIME_PERCENT_TOLERANCE (20.0f) -``` - ---- - -## Test Functions Detailed Analysis - -### 1. Memory Consumption Test (`test_memory_consumption_basic`) - -#### Purpose -Validates that the system has sufficient free memory for stable operation. - -#### Step-by-Step Execution - -**Step 1: Check 8-bit Heap** -```cpp -size_t free_now_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); -size_t free_min_8bit = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT); -``` -- `heap_caps_get_free_size()`: Returns current free memory in bytes -- `MALLOC_CAP_8BIT`: Specifies 8-bit accessible memory (most common) -- `heap_caps_get_minimum_free_size()`: Returns lowest free memory since boot -- **Why Important**: Shows both current state and worst-case scenario - -**Step 2: Validate 8-bit Heap** -```cpp -TEST_ASSERT_MESSAGE(free_now_8bit >= PERF_MIN_HEAP_BYTES, - "Not enough free 8-bit heap; increase RAM or lower threshold"); -``` -- Ensures minimum threshold is met -- Fails test if memory is critically low -- Provides actionable error message - -**Step 3: Check DMA-Capable Heap** -```cpp -size_t free_now_dma = heap_caps_get_free_size(MALLOC_CAP_DMA); -size_t free_min_dma = heap_caps_get_minimum_free_size(MALLOC_CAP_DMA); -``` -- `MALLOC_CAP_DMA`: Memory accessible by DMA controllers -- Critical for peripherals like SPI, I2C, WiFi -- May overlap with 8-bit heap on some configurations - -**Step 4: SPIRAM Check (Optional)** -```cpp -#if CONFIG_SPIRAM_SUPPORT -if (esp_spiram_is_initialized()) { - size_t free_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - // ... validation -} -#endif -``` -- Only runs if SPIRAM (external RAM) is configured -- `esp_spiram_is_initialized()`: Checks if SPIRAM is available -- `MALLOC_CAP_SPIRAM`: Targets external SPIRAM memory - -#### Expected Results -- **Healthy System**: >200KB free heap -- **Warning Level**: 50-200KB free heap -- **Critical Level**: <50KB free heap - ---- - -### 2. Stack Usage Test (`test_stack_usage_current_task`) - -#### Purpose -Monitors stack consumption to prevent stack overflow crashes. - -#### Understanding Stack Monitoring - -**What is Stack High Water Mark?** -- The "high water mark" is the maximum stack usage since task creation -- Measured in "words" (typically 4 bytes each on ESP32) -- Lower values indicate higher stack usage (less remaining) - -**Step-by-Step Execution** - -**Step 1: Get Current Task Stack Info** -```cpp -UBaseType_t high_water_words = uxTaskGetStackHighWaterMark(NULL); -``` -- `NULL` parameter means "current task" -- Returns unused stack space in words -- **Critical**: This is REMAINING stack, not USED stack - -**Step 2: Convert to Human-Readable Format** -```cpp -size_t high_water_bytes = stack_words_to_bytes(high_water_words); -``` -- Converts words to bytes for easier understanding -- `sizeof(StackType_t)` accounts for platform differences - -**Step 3: Validate Stack Health** -```cpp -TEST_ASSERT_MESSAGE(high_water_words >= PERF_MIN_STACK_WORDS_CURRENT, - "Current task stack high-water too low; consider increasing stack size"); -``` -- Ensures sufficient stack remains -- Prevents stack overflow crashes -- Suggests solution in error message - -#### Stack Usage Interpretation -- **High Water Mark = 1000 words**: 1000 words (4KB) unused - GOOD -- **High Water Mark = 100 words**: 100 words (400 bytes) unused - WARNING -- **High Water Mark = 10 words**: 10 words (40 bytes) unused - CRITICAL - ---- - -### 3. Idle Task Stack Test (`test_stack_usage_idle_tasks`) - -#### Purpose -Monitors system-critical idle task stacks across all CPU cores. - -#### Multi-Core Considerations - -**Why Monitor Idle Tasks?** -- Idle tasks run when no other tasks are active -- Stack overflow in idle tasks crashes the entire system -- Each CPU core has its own idle task - -**Step-by-Step Execution** - -**Step 1: Iterate Through CPU Cores** -```cpp -for (int cpu = 0; cpu < configNUM_CORES; ++cpu) { -``` -- `configNUM_CORES`: Compile-time constant (2 for ESP32) -- Ensures all cores are checked - -**Step 2: Get Idle Task Handle** -```cpp -TaskHandle_t idle = xTaskGetIdleTaskHandleForCore(cpu); -``` -- `xTaskGetIdleTaskHandleForCore()`: Gets idle task for specific core -- Returns handle to system-managed idle task -- **Note**: Uses newer API (old `xTaskGetIdleTaskHandleForCPU` deprecated) - -**Step 3: Check Stack Usage** -```cpp -UBaseType_t hw = uxTaskGetStackHighWaterMark(idle); -``` -- Same principle as current task check -- Applied to system idle task - -**Step 4: Validate Each Idle Task** -```cpp -TEST_ASSERT_MESSAGE(hw >= PERF_MIN_STACK_WORDS_IDLE, - "Idle task stack high-water too low; increase idle task stack for CPU"); -``` -- Lower threshold than user tasks (idle tasks do less work) -- Critical for system stability - -#### Single-Core Fallback -```cpp -#else -void test_stack_usage_idle_task(void) { - TaskHandle_t idle = xTaskGetIdleTaskHandle(); - // ... same validation logic -} -#endif -``` -- Handles single-core ESP32 variants -- Uses simpler API without core specification - ---- - -### 4. CPU Load Test (`test_cpu_load_estimation`) - -#### Purpose -Analyzes CPU utilization across all cores and tasks to identify performance bottlenecks. - -#### Prerequisites -```cpp -#if ( configGENERATE_RUN_TIME_STATS == 1 ) -``` -- Requires FreeRTOS runtime statistics enabled -- Must be configured in `sdkconfig`: `CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y` -- Uses high-resolution timer for accurate measurements - -#### Step-by-Step Execution - -**Step 1: Stabilization Period** -```cpp -wait_ms(1000); // Increased wait time for more stable measurements -``` -- Allows system to reach steady state -- Accumulates meaningful runtime statistics -- Longer period = more accurate measurements - -**Step 2: Get Task Count** -```cpp -UBaseType_t num_tasks = uxTaskGetNumberOfTasks(); -TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(0, num_tasks, "No tasks reported"); -``` -- Counts all active tasks in system -- Validates FreeRTOS is functioning -- Used to allocate appropriate array size - -**Step 3: Allocate Task Array** -```cpp -const UBaseType_t margin = 4; -TaskStatus_t *task_array = (TaskStatus_t *)malloc(sizeof(TaskStatus_t) * (num_tasks + margin)); -``` -- `TaskStatus_t`: FreeRTOS structure containing task information -- `margin`: Extra space in case tasks are created during measurement -- Heap allocation safer than stack for large arrays - -**Step 4: Capture System State** -```cpp -unsigned long total_run_time = 0; -UBaseType_t fetched = uxTaskGetSystemState(task_array, num_tasks + margin, &total_run_time); -``` -- `uxTaskGetSystemState()`: Atomic snapshot of all task states -- `total_run_time`: Total CPU time across all cores since boot -- `fetched`: Actual number of tasks captured - -**Step 5: Validate Data Quality** -```cpp -TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(0, fetched, "uxTaskGetSystemState returned no tasks"); -TEST_ASSERT_GREATER_THAN_MESSAGE(0UL, total_run_time, "Total run time is zero"); -``` -- Ensures data capture succeeded -- Validates runtime statistics are working -- Prevents division by zero errors - -**Step 6: Multi-Core Awareness** -```cpp -#if (configNUM_CORES > 1) -ESP_LOGI(TAG, "Multi-core system detected, using adjusted calculation"); -#endif -``` -- Acknowledges dual-core complexity -- Runtime statistics behave differently on multi-core systems -- Each core contributes to total runtime independently - -**Step 7: Calculate Task Percentages** -```cpp -for (UBaseType_t i = 0; i < fetched; ++i) { - unsigned long run = task_array[i].ulRunTimeCounter; - double pct = ((double)run * 100.0) / (double)total_run_time; -``` -- `ulRunTimeCounter`: CPU time consumed by this task -- Percentage calculation: (task_time / total_time) × 100 -- Double precision for accuracy - -**Step 8: Identify Idle Tasks** -```cpp -if (task_array[i].pcTaskName != NULL && - (strcasecmp(task_array[i].pcTaskName, "IDLE0") == 0 || - strcasecmp(task_array[i].pcTaskName, "IDLE1") == 0 || - strstr(task_array[i].pcTaskName, "IDLE") != NULL)) -``` -- `pcTaskName`: Task name string -- `strcasecmp()`: Case-insensitive string comparison -- `strstr()`: Substring search for "IDLE" -- Handles both "IDLE0", "IDLE1" and generic "IDLE" names - -**Step 9: Separate Idle vs Active Tasks** -```cpp -// Only count non-idle tasks for the sum check -if (task_array[i].pcTaskName == NULL || - (strstr(task_array[i].pcTaskName, "IDLE") == NULL)) { - percent_sum += pct; -} -``` -- Idle tasks run when nothing else needs CPU -- Active task percentage shows actual system load -- Idle percentage shows available capacity - -**Step 10: System Health Validation** -```cpp -TEST_ASSERT_MESSAGE(idle_task_count > 0, "No idle tasks found"); -TEST_ASSERT_MESSAGE(percent_sum < 150.0, "System appears overloaded"); -``` -- Ensures idle tasks exist (system sanity check) -- Validates reasonable CPU usage levels -- Relaxed thresholds for multi-core systems - -#### CPU Load Interpretation - -**Typical Results:** -- **Idle Tasks**: 85-95% (system mostly idle) -- **Active Tasks**: 5-15% (normal background activity) -- **Unity Test**: 3-8% (test execution overhead) -- **IPC Tasks**: 1-3% (inter-processor communication) - -**Warning Signs:** -- **No Idle Time**: System overloaded -- **>50% Active Load**: High CPU usage -- **Unbalanced Cores**: One core much busier than other - ---- - -## Unity Test Framework Integration - -### Test Registration System - -#### Unity Task Function -```cpp -extern "C" void unity_task(void *pvParameters) -{ - vTaskDelay(2); // Allow system to settle - - UNITY_BEGIN(); - - // Run individual tests - RUN_TEST(test_memory_consumption_basic); - RUN_TEST(test_stack_usage_current_task); - // ... more tests - - UNITY_END(); - - // Keep task alive - while(1) { - vTaskDelay(1000 / portTICK_PERIOD_MS); - } -} -``` - -**Step-by-Step Execution:** - -1. **Task Delay**: `vTaskDelay(2)` allows system initialization to complete -2. **Unity Begin**: `UNITY_BEGIN()` initializes test framework -3. **Test Execution**: `RUN_TEST()` macro executes each test function -4. **Unity End**: `UNITY_END()` prints final results and statistics -5. **Task Persistence**: Infinite loop keeps task alive for system stability - -#### Main Application Integration -```cpp -extern "C" void app_main(void) -{ - ESP_LOGI(TAG, "Performance tests enabled - starting Unity test suite"); - - // Create Unity test task - xTaskCreate(unity_task, "unity", 8192, NULL, 5, NULL); - - // Keep main task alive - while (1) { - vTaskDelay(pdMS_TO_TICKS(1000)); - } -} -``` - -**Parameters Explained:** -- `unity_task`: Function to execute -- `"unity"`: Task name (for debugging) -- `8192`: Stack size in bytes (8KB) -- `NULL`: No parameters passed to task -- `5`: Task priority (medium priority) -- `NULL`: No task handle returned - ---- - -## Memory Management Analysis - -### ESP32 Memory Architecture - -#### Internal RAM Types -1. **DRAM (Data RAM)**: General purpose data storage -2. **IRAM (Instruction RAM)**: Code execution, interrupt handlers -3. **RTC RAM**: Retains data during deep sleep - -#### Memory Capabilities -- `MALLOC_CAP_8BIT`: 8-bit accessible memory (most common) -- `MALLOC_CAP_32BIT`: 32-bit aligned memory (faster access) -- `MALLOC_CAP_DMA`: DMA controller accessible memory -- `MALLOC_CAP_SPIRAM`: External SPIRAM memory - -### Memory Test Deep Dive - -#### Heap Fragmentation Considerations -```cpp -size_t free_now = heap_caps_get_free_size(MALLOC_CAP_8BIT); -size_t free_min = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT); -``` - -**Key Insights:** -- `free_now > free_min`: Memory was more fragmented earlier -- `free_now == free_min`: Current state is worst case -- Large difference suggests memory fragmentation issues - -#### SPIRAM Integration -```cpp -if (esp_spiram_is_initialized()) { - size_t free_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); -} -``` - -**SPIRAM Benefits:** -- Expands available memory from ~300KB to several MB -- Slower access than internal RAM -- Ideal for large buffers, images, audio data - ---- - -## Stack Usage Monitoring - -### FreeRTOS Stack Management - -#### Stack Growth Direction -- ESP32 stacks grow downward (high to low addresses) -- Stack pointer starts at high address, decreases with usage -- Stack overflow occurs when pointer goes below allocated region - -#### High Water Mark Calculation -```cpp -UBaseType_t high_water_words = uxTaskGetStackHighWaterMark(NULL); -``` - -**Internal Process:** -1. FreeRTOS fills unused stack with pattern (0xa5a5a5a5) -2. Periodically scans from stack bottom upward -3. Finds first non-pattern word (maximum usage point) -4. Returns remaining unused words - -#### Stack Size Recommendations -- **Minimal Tasks**: 2KB (512 words) -- **Standard Tasks**: 4KB (1024 words) -- **Complex Tasks**: 8KB+ (2048+ words) -- **Unity Test Task**: 8KB (handles test framework overhead) - ---- - -## CPU Load Analysis - -### FreeRTOS Runtime Statistics - -#### Timer Configuration -```cpp -CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y -``` - -**Timer Options:** -- **ESP Timer**: High-resolution microsecond timer -- **CPU Clock**: Cycle-accurate but overflow-prone -- **Custom Timer**: User-defined timer source - -#### Multi-Core Considerations - -**Dual-Core Behavior:** -- Each core runs independently -- Idle tasks per core (IDLE0, IDLE1) -- Runtime statistics accumulate per core -- Total runtime = sum of both cores - -**Percentage Calculation Challenges:** -- Single-core: percentages sum to ~100% -- Dual-core: percentages can sum to ~200% -- Our solution: separate idle vs active task analysis - -#### Task Types Analysis - -**System Tasks:** -- `IDLE0/IDLE1`: Core idle tasks (run when nothing else active) -- `main`: Main application task -- `unity`: Test execution task -- `ipc0/ipc1`: Inter-processor communication - -**Typical Load Distribution:** -``` -IDLE0: 91.94% (CPU0 mostly idle) -IDLE1: 97.26% (CPU1 mostly idle) -unity: 5.14% (test execution) -main: 1.09% (minimal main task work) -ipc0: 1.77% (core communication) -ipc1: 1.83% (core communication) -``` - ---- - -## Build System Integration - -### CMakeLists.txt Configuration - -#### Component Registration -```cmake -# Set up dependencies conditionally -set(PERF_SRCS "") -set(PERF_PUBLIC_REQUIRES freertos esp_timer esp_system heap log) -set(PERF_PRIVATE_REQUIRES unity) # Always include unity - -if(CONFIG_ENABLE_PERF_TESTS) - list(APPEND PERF_SRCS "test/perf_tests.cpp") -endif() - -idf_component_register( - SRCS ${PERF_SRCS} - INCLUDE_DIRS "." - REQUIRES ${PERF_PUBLIC_REQUIRES} - PRIV_REQUIRES ${PERF_PRIVATE_REQUIRES} -) -``` - -**Key Points:** -- `PERF_SRCS`: Source files (conditional) -- `REQUIRES`: Public dependencies (always available) -- `PRIV_REQUIRES`: Private dependencies (internal use only) -- Unity always included to avoid compilation issues - -#### Main Component Integration -```cmake -set(MAIN_REQUIRES sensor_manager actuator_manager event_system) -set(MAIN_PRIV_REQUIRES esp_common unity) - -if(CONFIG_ENABLE_PERF_TESTS) - # Unity dependency already included above -endif() -``` - -### Conditional Compilation Strategy - -#### Preprocessor Guards -```cpp -#if CONFIG_ENABLE_PERF_TESTS -// Test code only compiled when enabled -#include "unity.h" -// ... test functions -#endif -``` - -**Benefits:** -- Zero overhead when tests disabled -- Clean separation of test vs production code -- Compile-time optimization - ---- - -## Troubleshooting Guide - -### Common Issues and Solutions - -#### 1. "unity.h: No such file or directory" -**Cause**: Unity component not properly linked -**Solution**: -```cmake -# In CMakeLists.txt -PRIV_REQUIRES unity -``` - -#### 2. "0 Tests 0 Failures 0 Ignored" -**Cause**: Tests not registered with Unity framework -**Solution**: Ensure `unity_task()` function calls `RUN_TEST()` macros - -#### 3. CPU Load Test Fails with >100% Usage -**Cause**: Multi-core runtime statistics accumulation -**Solution**: Use separate idle vs active task analysis (already implemented) - -#### 4. Stack Overflow in Tests -**Cause**: Insufficient stack size for Unity test task -**Solution**: -```cpp -xTaskCreate(unity_task, "unity", 8192, NULL, 5, NULL); -// ^^^^ Increase this value -``` - -#### 5. Memory Test Fails Immediately -**Cause**: System already low on memory -**Solutions**: -- Reduce `PERF_MIN_HEAP_BYTES` threshold -- Optimize application memory usage -- Enable SPIRAM if available - -#### 6. Runtime Statistics Not Working -**Cause**: FreeRTOS runtime stats disabled -**Solution**: -``` -CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y -CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y -``` - -### Performance Optimization Tips - -#### Memory Optimization -1. **Use SPIRAM**: For large data structures -2. **Optimize Heap Usage**: Avoid frequent malloc/free -3. **Static Allocation**: Use static variables when possible -4. **Memory Pools**: Pre-allocate fixed-size blocks - -#### Stack Optimization -1. **Right-Size Stacks**: Don't over-allocate -2. **Monitor Usage**: Regular high water mark checks -3. **Avoid Deep Recursion**: Use iteration instead -4. **Local Variable Management**: Minimize large local arrays - -#### CPU Optimization -1. **Task Priorities**: Balance workload across cores -2. **Yield Points**: Add `vTaskDelay()` in long loops -3. **Interrupt Efficiency**: Keep ISRs short -4. **Core Affinity**: Pin tasks to specific cores when beneficial - ---- - -## Conclusion - -This performance testing system provides comprehensive monitoring of ESP32 system health. The tests are designed to catch issues early in development and provide actionable feedback for optimization. - -### Key Benefits -- **Proactive Monitoring**: Catch issues before they cause crashes -- **Quantitative Analysis**: Precise measurements vs. guesswork -- **Multi-Core Awareness**: Proper handling of ESP32's dual-core architecture -- **Professional Framework**: Unity provides industry-standard test reporting -- **Configurable Thresholds**: Adaptable to different application requirements - -### Best Practices -1. **Run Tests Regularly**: Include in CI/CD pipeline -2. **Monitor Trends**: Track performance over time -3. **Adjust Thresholds**: Tune limits based on application needs -4. **Document Results**: Keep performance baselines -5. **Investigate Failures**: Don't ignore test failures - -The system is designed to grow with your project, providing valuable insights throughout the development lifecycle. \ No newline at end of file diff --git a/draft- to be removed SW/components/perf_tests/Kconfig b/draft- to be removed SW/components/perf_tests/Kconfig deleted file mode 100644 index 7c3499b..0000000 --- a/draft- to be removed SW/components/perf_tests/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -menu "Performance Tests" - -config ENABLE_PERF_TESTS - bool "Enable performance tests (CPU, memory, stack)" - default y - help - Enable building and running performance-oriented Unity tests - (CPU load, memory consumption, and stack usage). - -if ENABLE_PERF_TESTS - -config ENABLE_CPU_LOAD_TEST - bool "Enable CPU load test" - default y - -config ENABLE_MEMORY_TEST - bool "Enable memory consumption test" - default y - -config ENABLE_STACK_USAGE_TEST - bool "Enable stack usage test" - default y - -endif # ENABLE_PERF_TESTS - -endmenu diff --git a/draft- to be removed SW/components/perf_tests/test/perf_tests.cpp b/draft- to be removed SW/components/perf_tests/test/perf_tests.cpp deleted file mode 100644 index 970216c..0000000 --- a/draft- to be removed SW/components/perf_tests/test/perf_tests.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/** - * @file perf_tests.cpp - * @brief Unity tests for CPU load, memory consumption, and stack usage. - * - * This file implements comprehensive performance monitoring for ESP32 systems. - * It tests three critical aspects of system health: - * 1. Memory Usage - Ensures sufficient free heap memory - * 2. Stack Usage - Monitors task stack consumption to prevent overflows - * 3. CPU Load - Analyzes processor utilization across both cores - * - * @author Mahmoud Elmohtady (improvements) - * @company Nabd solutions - ASF - * @copyright 2025 - */ - -// Standard C library includes for string operations and formatted output -#include // For strcasecmp(), strstr() - string comparison functions -#include // For printf-style functions (used by ESP_LOGI) -#include // For portable integer type definitions - -// FreeRTOS includes - the real-time operating system running on ESP32 -#include "freertos/FreeRTOS.h" // Core FreeRTOS definitions and types -#include "freertos/task.h" // Task management functions (create, delay, etc.) -#include "freertos/portmacro.h" // Platform-specific macros and definitions - -// ESP-IDF (Espressif IoT Development Framework) includes -#include "esp_timer.h" // High-resolution timer functions -#include "esp_system.h" // System-level functions and utilities -#include "esp_heap_caps.h" // Memory management with capability-based allocation -#include "esp_log.h" // Logging system for debug output - -// Conditional includes based on configuration -#if CONFIG_SPIRAM_SUPPORT -#include "esp_spiram.h" // External SPIRAM (Serial Peripheral RAM) support -#endif - -#if CONFIG_ENABLE_PERF_TESTS -#include "unity.h" // Unity test framework for professional testing -#endif - -// extern "C" tells the C++ compiler to use C-style function naming -// This is necessary because FreeRTOS and ESP-IDF are written in C -extern "C" { - -// TAG is used by ESP_LOGI() for log message identification -// All log messages from this file will be prefixed with "perf_tests" -static const char *TAG = "perf_tests"; - -/* ======================================================================== - * CONFIGURABLE THRESHOLDS - Adjust these values for your specific application - * ======================================================================== */ - -// Minimum free heap memory (in bytes) to consider the system "healthy" -// 1024 bytes = 1KB - very conservative threshold -// Increase this value for applications that need more memory headroom -#ifndef PERF_MIN_HEAP_BYTES -#define PERF_MIN_HEAP_BYTES (1024U) -#endif - -// Minimum unused stack space (in WORDS, not bytes) for the current task -// 100 words = 400 bytes on ESP32 (since each word is 4 bytes) -// This prevents stack overflow crashes in your application tasks -#ifndef PERF_MIN_STACK_WORDS_CURRENT -#define PERF_MIN_STACK_WORDS_CURRENT (100U) -#endif - -// Minimum unused stack space (in WORDS) for system idle tasks -// 50 words = 200 bytes - idle tasks do minimal work so need less stack -// Critical for system stability - idle task crashes = system crash -#ifndef PERF_MIN_STACK_WORDS_IDLE -#define PERF_MIN_STACK_WORDS_IDLE (50U) -#endif - -// Tolerance for CPU usage percentage calculations (as a float) -// 20.0% tolerance accounts for multi-core timing complexities -// In dual-core systems, percentages don't always sum to exactly 100% -#ifndef PERF_RUNTIME_PERCENT_TOLERANCE -#define PERF_RUNTIME_PERCENT_TOLERANCE (20.0f) -#endif - -/* ======================================================================== - * UTILITY FUNCTIONS - * ======================================================================== */ - -/** - * @brief Simple delay function that yields CPU to other tasks - * @param ms Delay time in milliseconds - * - * This is better than a busy-wait loop because it allows other tasks to run. - * vTaskDelay() puts the current task to sleep and wakes it up after the specified time. - * pdMS_TO_TICKS() converts milliseconds to FreeRTOS tick units. - */ -static void wait_ms(uint32_t ms) -{ - // Convert milliseconds to FreeRTOS ticks and delay the current task - // This allows other tasks to run during the delay period - vTaskDelay(pdMS_TO_TICKS(ms)); -} - -/* ======================================================================== - * PERFORMANCE TEST FUNCTIONS - * These functions only compile when CONFIG_ENABLE_PERF_TESTS is enabled - * ======================================================================== */ -#if CONFIG_ENABLE_PERF_TESTS - -/* ------------------------------------------------------------------------ - * MEMORY CONSUMPTION TEST - * ------------------------------------------------------------------------ */ -#if CONFIG_ENABLE_MEMORY_TEST -/** - * @brief Tests system memory consumption and availability - * - * This test checks different types of memory on the ESP32: - * 1. 8-bit accessible memory (most common, used by malloc()) - * 2. DMA-capable memory (required for hardware peripherals) - * 3. SPIRAM memory (external RAM, if configured) - * - * The test ensures the system has sufficient free memory for stable operation. - * Low memory can cause malloc() failures, task creation failures, or system crashes. - */ -void test_memory_consumption_basic(void) -{ - /* ---- CHECK 8-BIT ACCESSIBLE HEAP ---- */ - // This is the most commonly used memory type - where malloc() allocates from - - // Get current free memory in the 8-bit heap - size_t free_now_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); - - // Get the minimum free memory since boot (worst case scenario) - // This shows if the system has been under memory pressure - size_t free_min_8bit = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT); - - // Log the results for debugging and monitoring - ESP_LOGI(TAG, "8-bit heap: free_now=%u free_min=%u", (unsigned)free_now_8bit, (unsigned)free_min_8bit); - - // CRITICAL TEST: Ensure we have enough free memory - // If this fails, your application may crash due to out-of-memory conditions - TEST_ASSERT_MESSAGE(free_now_8bit >= PERF_MIN_HEAP_BYTES, - "Not enough free 8-bit heap; increase RAM or lower threshold"); - - /* ---- CHECK DMA-CAPABLE HEAP ---- */ - // DMA memory is required for hardware peripherals like SPI, I2C, WiFi, etc. - // Some ESP32 configurations share this with 8-bit heap, others separate it - - // Get current free DMA-capable memory - size_t free_now_dma = heap_caps_get_free_size(MALLOC_CAP_DMA); - - // Get minimum free DMA memory since boot - size_t free_min_dma = heap_caps_get_minimum_free_size(MALLOC_CAP_DMA); - - // Log DMA memory status - ESP_LOGI(TAG, "DMA heap: free_now=%u free_min=%u", (unsigned)free_now_dma, (unsigned)free_min_dma); - - // Basic sanity check - ensure the API call succeeded - // Note: On some configurations, DMA heap is the same as 8-bit heap - TEST_ASSERT_GREATER_OR_EQUAL_size_t(0, free_min_dma); - - /* ---- CHECK SPIRAM (EXTERNAL RAM) IF AVAILABLE ---- */ -#if CONFIG_SPIRAM_SUPPORT - // SPIRAM is external RAM that can expand memory from ~300KB to several MB - // It's slower than internal RAM but great for large buffers - - // Check if SPIRAM was successfully initialized at boot - if (esp_spiram_is_initialized()) { - // Get free SPIRAM memory (combined with 8-bit capability) - size_t free_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - - // Get minimum free SPIRAM since boot - size_t min_spiram = heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - - // Log SPIRAM status - ESP_LOGI(TAG, "SPIRAM: free_now=%u free_min=%u", (unsigned)free_spiram, (unsigned)min_spiram); - - // Ensure SPIRAM is functioning (basic sanity check) - TEST_ASSERT_GREATER_OR_EQUAL_size_t(0, min_spiram); - } -#endif -} -#endif // CONFIG_ENABLE_MEMORY_TEST - -/* ------------------------------------------------------------------------ - * STACK USAGE MONITORING TESTS - * ------------------------------------------------------------------------ */ -#if CONFIG_ENABLE_STACK_USAGE_TEST - -/** - * @brief Helper function to convert stack words to bytes for human readability - * @param words Stack size in words (FreeRTOS native unit) - * @return Stack size in bytes - * - * FreeRTOS measures stack in "words" which are platform-specific. - * On ESP32, 1 word = 4 bytes (32-bit architecture). - * This function converts to bytes for easier understanding. - */ -static inline size_t stack_words_to_bytes(UBaseType_t words) -{ - // sizeof(StackType_t) is 4 bytes on ESP32 (32-bit words) - return (size_t)words * sizeof(StackType_t); -} - -/** - * @brief Tests stack usage of the currently running task - * - * Stack overflow is one of the most common causes of embedded system crashes. - * This test monitors how much stack space remains unused in the current task. - * - * IMPORTANT: "High water mark" means UNUSED stack, not USED stack! - * - High value = lots of unused stack = good - * - Low value = little unused stack = danger of overflow - */ -void test_stack_usage_current_task(void) -{ - // Get the "high water mark" - minimum unused stack since task creation - // NULL parameter means "check the currently running task" - UBaseType_t high_water_words = uxTaskGetStackHighWaterMark(NULL); - - // Convert to bytes for easier understanding - size_t high_water_bytes = stack_words_to_bytes(high_water_words); - - // Log the results for monitoring and debugging - ESP_LOGI(TAG, "Current task high-water: %u words (%u bytes)", - (unsigned)high_water_words, (unsigned)high_water_bytes); - - // CRITICAL TEST: Ensure sufficient unused stack remains - // If this fails, the task is at risk of stack overflow crash - TEST_ASSERT_MESSAGE(high_water_words >= PERF_MIN_STACK_WORDS_CURRENT, - "Current task stack high-water too low; consider increasing stack size"); -} - -/* ---- MULTI-CORE vs SINGLE-CORE IDLE TASK MONITORING ---- */ -#if (configNUM_CORES > 1) -/** - * @brief Tests stack usage of idle tasks on multi-core ESP32 - * - * In multi-core systems, each CPU core has its own idle task: - * - IDLE0: Runs on CPU core 0 when no other tasks need it - * - IDLE1: Runs on CPU core 1 when no other tasks need it - * - * Idle task stack overflow crashes the entire system! - */ -void test_stack_usage_idle_tasks(void) -{ - // Loop through each CPU core (ESP32 has 2 cores: 0 and 1) - for (int cpu = 0; cpu < configNUM_CORES; ++cpu) { - - // Get the idle task handle for this specific CPU core - TaskHandle_t idle = xTaskGetIdleTaskHandleForCore(cpu); - - // Ensure we got a valid handle (system sanity check) - TEST_ASSERT_NOT_NULL_MESSAGE(idle, "Idle task handle is NULL for a CPU"); - - // Get the high water mark for this idle task - UBaseType_t hw = uxTaskGetStackHighWaterMark(idle); - - // Convert to bytes for logging - size_t hw_bytes = stack_words_to_bytes(hw); - - // Log idle task stack status for each core - ESP_LOGI(TAG, "Idle task (cpu %d) high-water: %u words (%u bytes)", - cpu, (unsigned)hw, (unsigned)hw_bytes); - - // CRITICAL TEST: Ensure idle task has sufficient stack - // Idle task crash = system crash, so this is very important - TEST_ASSERT_MESSAGE(hw >= PERF_MIN_STACK_WORDS_IDLE, - "Idle task stack high-water too low; increase idle task stack for CPU"); - } -} - -#else -/** - * @brief Tests stack usage of idle task on single-core ESP32 - * - * Single-core systems have only one idle task that runs when no other tasks are active. - * This is a simpler version of the multi-core test above. - */ -void test_stack_usage_idle_task(void) -{ - // Get the single idle task handle (no core specification needed) - TaskHandle_t idle = xTaskGetIdleTaskHandle(); - - // Ensure we got a valid handle - TEST_ASSERT_NOT_NULL_MESSAGE(idle, "Idle task handle is NULL"); - - // Get high water mark for the idle task - UBaseType_t hw = uxTaskGetStackHighWaterMark(idle); - - // Convert to bytes for logging - size_t hw_bytes = stack_words_to_bytes(hw); - - // Log idle task stack status - ESP_LOGI(TAG, "Idle task high-water: %u words (%u bytes)", (unsigned)hw, (unsigned)hw_bytes); - - // CRITICAL TEST: Ensure idle task has sufficient stack - TEST_ASSERT_MESSAGE(hw >= PERF_MIN_STACK_WORDS_IDLE, - "Idle task stack high-water too low; increase idle task stack"); -} -#endif - -#endif // CONFIG_ENABLE_STACK_USAGE_TEST - -/* ------------------------------------------------------------------------ - * CPU LOAD ANALYSIS TEST - * ------------------------------------------------------------------------ */ -#if CONFIG_ENABLE_CPU_LOAD_TEST - -/** - * @brief Analyzes CPU utilization across all cores and tasks - * - * This is the most complex test because it deals with multi-core timing statistics. - * It measures how much CPU time each task consumes and identifies performance bottlenecks. - * - * Key concepts: - * - Runtime statistics track CPU time per task using a high-resolution timer - * - Idle tasks run when no other tasks need CPU (high idle = low system load) - * - Multi-core systems have separate idle tasks per core - * - Percentages may not sum to exactly 100% due to timing complexities - * - * Requirements: - * - configGENERATE_RUN_TIME_STATS must be enabled in FreeRTOS config - * - High-resolution timer must be configured (ESP_TIMER recommended) - */ -void test_cpu_load_estimation(void) -{ - /* ---- CHECK IF RUNTIME STATISTICS ARE ENABLED ---- */ -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - /* ---- STEP 1: STABILIZATION PERIOD ---- */ - // Allow the system to reach steady state before measurement - // Longer period = more accurate measurements, but slower test - wait_ms(1000); // 1 second should be sufficient for most applications - - /* ---- STEP 2: GET TASK COUNT ---- */ - // Find out how many tasks are currently running in the system - UBaseType_t num_tasks = uxTaskGetNumberOfTasks(); - - // Sanity check - ensure FreeRTOS is reporting tasks correctly - TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(0, num_tasks, "No tasks reported by uxTaskGetNumberOfTasks()"); - - /* ---- STEP 3: ALLOCATE MEMORY FOR TASK DATA ---- */ - // We need an array to hold information about each task - // Add a small margin in case new tasks are created during measurement - const UBaseType_t margin = 4; - - // TaskStatus_t is a FreeRTOS structure containing task information - TaskStatus_t *task_array = (TaskStatus_t *)malloc(sizeof(TaskStatus_t) * (num_tasks + margin)); - - // Ensure memory allocation succeeded - TEST_ASSERT_NOT_NULL_MESSAGE(task_array, "Failed to allocate task array for system state"); - - /* ---- STEP 4: CAPTURE SYSTEM STATE SNAPSHOT ---- */ - // This is the critical measurement - atomic snapshot of all task states - unsigned long total_run_time = 0; // FreeRTOS will fill this with total CPU time - - // uxTaskGetSystemState() captures all task information atomically - UBaseType_t fetched = uxTaskGetSystemState(task_array, num_tasks + margin, &total_run_time); - - // Log the raw data for debugging - ESP_LOGI(TAG, "uxTaskGetSystemState fetched=%u total_run_time=%lu", (unsigned)fetched, total_run_time); - - /* ---- STEP 5: VALIDATE DATA QUALITY ---- */ - // Ensure the data capture was successful - TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(0, fetched, "uxTaskGetSystemState returned no tasks"); - TEST_ASSERT_GREATER_THAN_MESSAGE(0UL, total_run_time, "Total run time is zero; ensure runtime stats timer is configured"); - - /* ---- STEP 6: MULTI-CORE AWARENESS ---- */ - // Multi-core systems have complex timing behavior - // Each core contributes independently to the total runtime - (void)total_run_time; // Suppress unused variable warning for normalized_total_time - -#if (configNUM_CORES > 1) - // Log that we're handling multi-core complexity - ESP_LOGI(TAG, "Multi-core system detected, using adjusted calculation"); -#endif - - /* ---- STEP 7: INITIALIZE ANALYSIS VARIABLES ---- */ - double percent_sum = 0.0; // Sum of non-idle task percentages - double idle_percent_total = 0.0; // Sum of all idle task percentages - int idle_task_count = 0; // Number of idle tasks found - - /* ---- STEP 8: ANALYZE EACH TASK ---- */ - for (UBaseType_t i = 0; i < fetched; ++i) { - - // Get the runtime counter for this task (CPU time consumed) - unsigned long run = task_array[i].ulRunTimeCounter; - - // Calculate percentage: (task_time / total_time) * 100 - double pct = 0.0; - if (total_run_time > 0) { - pct = ((double)run * 100.0) / (double)total_run_time; - } - - // Log detailed information for each task (useful for debugging) - ESP_LOGI(TAG, "Task[%u] name='%s' handle=%p run=%lu pct=%.2f", - (unsigned)i, task_array[i].pcTaskName, task_array[i].xHandle, run, pct); - - /* ---- IDENTIFY IDLE TASKS ---- */ - // Idle tasks have special names and behavior - // In multi-core: "IDLE0" (core 0), "IDLE1" (core 1) - // In single-core: usually just "IDLE" - if (task_array[i].pcTaskName != NULL && - (strcasecmp(task_array[i].pcTaskName, "IDLE0") == 0 || - strcasecmp(task_array[i].pcTaskName, "IDLE1") == 0 || - strstr(task_array[i].pcTaskName, "IDLE") != NULL)) - { - // This is an idle task - track it separately - idle_percent_total += pct; - idle_task_count++; - ESP_LOGI(TAG, "Found idle task: %s with %.2f%% usage", task_array[i].pcTaskName, pct); - } - - /* ---- SEPARATE ACTIVE vs IDLE TASKS ---- */ - // Only count non-idle tasks for system load calculation - // Idle tasks run when nothing else needs CPU, so they don't represent "work" - if (task_array[i].pcTaskName == NULL || - (strstr(task_array[i].pcTaskName, "IDLE") == NULL)) { - percent_sum += pct; - } - } - - /* ---- STEP 9: CLEANUP MEMORY ---- */ - // Free the allocated task array - free(task_array); - - /* ---- STEP 10: ANALYZE RESULTS ---- */ - // Log the analysis results - ESP_LOGI(TAG, "Non-idle task runtime sum = %.2f%%", percent_sum); - ESP_LOGI(TAG, "Total idle task runtime = %.2f%% (across %d idle tasks)", idle_percent_total, idle_task_count); - ESP_LOGI(TAG, "System appears to be %.2f%% busy", percent_sum); - - /* ---- STEP 11: VALIDATE SYSTEM HEALTH ---- */ - // These are relaxed validations designed for multi-core systems - // The goal is to ensure the system is reporting reasonable values - - // Ensure we found idle tasks (basic system sanity check) - TEST_ASSERT_MESSAGE(idle_task_count > 0, "No idle tasks found; runtime stats may not be working"); - - // Ensure idle percentage makes sense (not negative) - TEST_ASSERT_MESSAGE(idle_percent_total >= 0.0, "Idle task percentage is negative"); - - // Ensure active task percentage is reasonable (not impossibly high) - TEST_ASSERT_MESSAGE(percent_sum >= 0.0 && percent_sum <= 200.0, "Non-idle task percentage sum is unreasonable"); - - // Check for system overload (too much CPU usage) - TEST_ASSERT_MESSAGE(percent_sum < 150.0, "System appears overloaded or runtime stats misconfigured"); - - // Log successful completion - ESP_LOGI(TAG, "CPU load test completed - system load appears reasonable"); - -#else - /* ---- RUNTIME STATISTICS DISABLED ---- */ - // If FreeRTOS runtime statistics are not enabled, skip this test - TEST_IGNORE_MESSAGE("configGENERATE_RUN_TIME_STATS is disabled; enable to run CPU load test"); -#endif // configGENERATE_RUN_TIME_STATS -} -#endif // CONFIG_ENABLE_CPU_LOAD_TEST - - #endif // CONFIG_ENABLE_PERF_TESTS - - } // extern "C" - -/* ======================================================================== - * UNITY TEST FRAMEWORK INTEGRATION - * - * This section integrates our performance tests with the Unity test framework. - * Unity provides professional test reporting, assertions, and test management. - * ======================================================================== */ -#if CONFIG_ENABLE_PERF_TESTS - -// Forward declaration of app_main (defined in main.cpp) -extern "C" void app_main(void); - -/** - * @brief Test registration function (currently unused but kept for future expansion) - * - * This function could be used for dynamic test registration if needed. - * Currently, we use the simpler RUN_TEST() approach in unity_task(). - */ -extern "C" void register_perf_tests(void) -{ - // This function demonstrates how to register tests by name - // Currently not used, but available for future dynamic test loading - -#if CONFIG_ENABLE_MEMORY_TEST - unity_run_test_by_name("test_memory_consumption_basic"); -#endif - -#if CONFIG_ENABLE_STACK_USAGE_TEST - unity_run_test_by_name("test_stack_usage_current_task"); -#if (configNUM_CORES > 1) - unity_run_test_by_name("test_stack_usage_idle_tasks"); -#else - unity_run_test_by_name("test_stack_usage_idle_task"); -#endif -#endif - -#if CONFIG_ENABLE_CPU_LOAD_TEST - unity_run_test_by_name("test_cpu_load_estimation"); -#endif -} - -/** - * @brief Main Unity test runner task - * @param pvParameters Task parameters (unused, required by FreeRTOS) - * - * This function runs as a FreeRTOS task and executes all performance tests. - * It's called from main.cpp when performance testing is enabled. - * - * Execution flow: - * 1. Allow system to stabilize after boot - * 2. Initialize Unity test framework - * 3. Run each enabled test function - * 4. Print final test results - * 5. Keep task alive for system stability - */ -extern "C" void unity_task(void *pvParameters) -{ - // Suppress unused parameter warning (FreeRTOS requires this parameter) - (void)pvParameters; - - /* ---- STEP 1: SYSTEM STABILIZATION ---- */ - // Give the system a moment to finish initialization - // This ensures all components are ready before testing begins - vTaskDelay(2); // 2 FreeRTOS ticks (usually 20ms) - - /* ---- STEP 2: INITIALIZE UNITY FRAMEWORK ---- */ - // UNITY_BEGIN() sets up the test framework and resets counters - UNITY_BEGIN(); - - /* ---- STEP 3: RUN PERFORMANCE TESTS ---- */ - // Each RUN_TEST() macro executes a test function and tracks results - // Tests are run conditionally based on configuration flags - -#if CONFIG_ENABLE_MEMORY_TEST - // Test memory consumption and availability - RUN_TEST(test_memory_consumption_basic); -#endif - -#if CONFIG_ENABLE_STACK_USAGE_TEST - // Test current task stack usage - RUN_TEST(test_stack_usage_current_task); - - // Test idle task stack usage (multi-core vs single-core) -#if (configNUM_CORES > 1) - RUN_TEST(test_stack_usage_idle_tasks); // Multi-core version -#else - RUN_TEST(test_stack_usage_idle_task); // Single-core version -#endif -#endif - -#if CONFIG_ENABLE_CPU_LOAD_TEST - // Test CPU utilization across all cores and tasks - RUN_TEST(test_cpu_load_estimation); -#endif - - /* ---- STEP 4: FINALIZE AND REPORT RESULTS ---- */ - // UNITY_END() prints the final test summary: - // - Total tests run - // - Number of failures - // - Number of ignored tests - // - Overall PASS/FAIL status - UNITY_END(); - - /* ---- STEP 5: KEEP TASK ALIVE ---- */ - // The task must remain alive for system stability - // Deleting this task could cause issues with FreeRTOS scheduler - while(1) { - // Sleep for 1 second, then repeat - // This keeps the task alive with minimal CPU usage - vTaskDelay(1000 / portTICK_PERIOD_MS); - } -} - -#endif // CONFIG_ENABLE_PERF_TESTS - \ No newline at end of file diff --git a/draft- to be removed SW/components/system_tests/__pycache__/scan_serial.cpython-313.pyc b/draft- to be removed SW/components/system_tests/__pycache__/scan_serial.cpython-313.pyc deleted file mode 100644 index dad1744a5d0d81e190b19c93e09ddf7056f3ad3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5757 zcmb7IOKcm*8J^`X$>l?&BvKM7$=1l0Ei*Bx#IHnh99OlhM7AWmTq#W|2keSmQEO9N zW_IZZ53SKdAptF9r!efe1uUZlteoOwQxt8D251jOK}L3|tc5mcbIDDy4J62^|Lk%} zN|qC3fSsMkKkx7VzklX&LxUSZ`2O6Fz*Q2De+-FhNI(K}5)t#y5XQ*c zh|T!3gf;#g;f%kX*x_$G={Vse&J#T0vDwZ=Tp_dr32ZwOxPvxx1maFJ5&P#fGaj+& z_8;V>yrkQY&*ijBNmIm(EAr^^FyybHGlLa*&N47Q^bMnP5IY1r#7@Bh zF)uhFb_rgAH{{%ci+IxRNQ3S@jLAK!%N8k%I{OkHgy zd9d=IM44*sn>b_57uF6n)n2DuRu6UU>{i*7*Gk2GR;u>jf$G}uR(TplnDK~9x94*? ziRj#%l9F^Trw~nd=7^G%RF%--b+3}wa(ONBjFwI7DMj8=o8>nE29Tk1rr+bAKm_N9;_%-b z1ZLn(gv2HUm<5UIxz*%+fZ6?QmN{h;xGXbe=?02BYBE+zup7O>i3*NM#)tOXdH^>) zDB>)GB+h8>#|vnf0+s!|FoSuBiQ%K>Rcci&|)ZFXnMNP`8B94w>NzLuwhof`&z!;9Eh|; z^2LH5a?|-4992efR2sz*u7(rcrl>lX73ZXgjliBF-I<(AC1Bku-C2xDGcEKc(vp^_ z?0_EH0EN05Dyxn{bQyi>@h|o-^xtr-c($)QPq#0msN@pSU6ANWiW0g-e8lXBSXX3IQ}a7C;~5tGGG!=KudEONt2aqtPqYy zqj;EN1&joq6-nxXNF)l>0*9fFgkT;8huPmmgwgHltdz+Rdd`KeVG&T5!kSVU&p6_0 zFR?;vwRe2X98{v6jz=5-Ga_d-!|Z@j%1>9Un9h=XR(BIg%ad%9S~=J8i%BU*XB%Nn zu(^!IB>-}|gGg#VqgjT_#GT&+f5KXg-mw9CW^1c*7c4}58=}kTGrpnN7+LQ5Ao6}> zx#R9o(bs>UA6RY0OTjzg+uHCvQ}?H4tOlz(dDb*>0w>t}Z5T~ep&K_`i@Gi#Syx-7xtav@;Sji~ zD(%H#Wt&4hu(q}|)!SJ1;*uBN_wE3a@(0Sku9B~7#n(O0QiZRXkfQJ4ef|)X zU2)ymd84K1>sr!2=J!5vptkPo%2j2p6_;CkORc@&`K-2uR$IbrftKq7R|l>iy?S&d z(DOxuv)MiGc+y=hJwkS1N-qTj5lm#h2g8kz1hDI&JZv zz+N?$q)y=$NQ7&`2B&bU%7O8%_>MKW=oCWRQJv%#c-&E6zXdBA+_A;%<5kXp{iy^C z`%_hRjJH~KwZEl@fbN&3sw@}ptVviYxXuIj19Lm4x~wwTo$olCKD)pJyMhPtjJA{? zHU&!~shgX2ccZB)V>^)uXuzlojqjO3N7ybj!+;~)C5SUp<`Sm2T+<=0_?0+Klzc8$ za0yV8qtsaN;7VOA7BeVK=QUA1cTUb^3bwvs_$CTm-|3Md%9OsOm;;woN|*{e9%(W) zjRiF`6_ZZiq&&Kr6$Yc7<iQn%#yq8Z6)uv2i~srHslR`1zm)m zdyJT-@F&60I>?2;R;dlW*FM;A>@fQ4VfPTve&l2zPS&#z#h_so{sf6@pk;t9NNo;V z*#)?cG5rj9lT{pViRh|DsP$=~GG2Y=dAcskf}hROM}Krw%_ zr}NtQxMP*hfUr6Z(PgyG*Mw=*S3-y9M^;-}uUxuvZmD@`Xz5Tf@LbXR+*fP2yunJ zR;lg#*`RmOkM8;1gPrWX4hCXaw(+7xsnNJ!n)*qNDtQ$m`UJ_sGmOq1J2loHVbV9> zqv6A&5ifnYqR$%ea^+4W;CUvWp=oad-qXZPrN*B~%*aI5=pJO1M1oMDnl3Ko62qG` zn3cRmvq^~bmIS9zFd=!wm4-}}hd zWN&-4o44tv-&?> - VERBOSE : 0 - DEBUG : 1 - INFO : 2 - WARNING : 3 - ERROR : 4 - NONE : 5 - } - - class LoggerConfig { - +LogLevel minLevel - +bool enableTimestamp - +bool enableColor - +bool enableId - +uint32_t maxMessageLength - } - - class Logger { - <> - -LoggerConfig s_config - -COLOR_RESET : char* - -COLOR_VERBOSE : char* - -COLOR_DEBUG : char* - -COLOR_INFO : char* - -COLOR_WARNING : char* - -COLOR_ERROR : char* - - +initialize(config: LoggerConfig) void - +setLogLevel(level: LogLevel) void - +getLogLevel() LogLevel - +enableTimestamp(enable: bool) void - +enableColor(enable: bool) void - +enableId(enable: bool) void - +getIsoTimestamp(buffer: char*, size: size_t) char* - +log(tag: char*, id: uint32_t, level: LogLevel, format: char*, ...) void - +logVerbose(tag: char*, id: uint32_t, format: char*, ...) void - +logDebug(tag: char*, id: uint32_t, format: char*, ...) void - +logInfo(tag: char*, id: uint32_t, format: char*, ...) void - +logWarning(tag: char*, id: uint32_t, format: char*, ...) void - +logError(tag: char*, id: uint32_t, format: char*, ...) void - +getDefaultConfig() LoggerConfig - +logLevelToString(level: LogLevel) char* - +logLevelToColor(level: LogLevel) char* - } - - Logger --> LoggerConfig : uses - Logger --> LogLevel : uses - } - - class ESP_IDF_Log { - <> - +ESP_LOGV(tag, format, ...) - +ESP_LOGD(tag, format, ...) - +ESP_LOGI(tag, format, ...) - +ESP_LOGW(tag, format, ...) - +ESP_LOGE(tag, format, ...) - } - - Logger --> ESP_IDF_Log : delegates to -``` - -### Sequence Diagram - Logging Flow - -```mermaid -sequenceDiagram - participant App as Application - participant Macro as ASF_LOGI Macro - participant Logger as asf::logger - participant Formatter as Message Formatter - participant ESP as ESP-IDF Log - participant Output as Console/UART - - App->>Macro: ASF_LOGI(TAG, ID, format, args) - Macro->>Logger: logInfo(TAG, ID, format, args) - - alt Log level check - Logger->>Logger: Check if INFO >= minLevel - alt Level allowed - Logger->>Formatter: Format message with timestamp, color, ID - Formatter->>Logger: Formatted message string - Logger->>ESP: ESP_LOGI("ASF", formatted_message) - ESP->>Output: Write to console/UART - else Level filtered - Logger-->>App: Return (no output) - end - end -``` - -### State Diagram - Logger Configuration - -```mermaid -stateDiagram-v2 - [*] --> Uninitialized - - Uninitialized --> Initialized : initialize(config) - - state Initialized { - [*] --> DefaultConfig - DefaultConfig --> CustomConfig : setLogLevel() / enableTimestamp() / etc. - CustomConfig --> DefaultConfig : initialize(defaultConfig) - - state "Runtime Configuration" as Runtime { - [*] --> LevelFiltering - LevelFiltering --> TimestampEnabled - TimestampEnabled --> ColorEnabled - ColorEnabled --> IdEnabled - IdEnabled --> LevelFiltering - } - - DefaultConfig --> Runtime - CustomConfig --> Runtime - } - - Initialized --> [*] : Application Exit -``` - -### Component Diagram - -```mermaid -graph TB - subgraph "ASF Logger Component" - subgraph "Public API" - A[Logger Functions] - B[Convenience Macros] - C[Configuration API] - end - - subgraph "Core Implementation" - D[Message Formatter] - E[Level Filter] - F[Timestamp Generator] - G[Color Manager] - end - - subgraph "Configuration" - H[Static Config] - I[Runtime Settings] - end - end - - subgraph "External Dependencies" - J[ESP-IDF Log System] - K[POSIX Time Functions] - L[Standard C Library] - end - - A --> D - A --> E - B --> A - C --> H - C --> I - D --> F - D --> G - D --> J - F --> K - D --> L - E --> H -``` - -## Design Patterns - -### 1. Namespace Pattern - -The logger uses a namespace-based design instead of a class-based approach: - -**Benefits:** -- Zero instantiation overhead -- No virtual function calls -- Simple include and use -- Thread-safe by design (minimal shared state) - -```cpp -namespace asf { -namespace logger { - void logInfo(const char* tag, uint32_t id, const char* format, ...); -} -} -``` - -### 2. Configuration Object Pattern - -Configuration is encapsulated in a structure for easy management: - -```cpp -struct LoggerConfig { - LogLevel minLevel; - bool enableTimestamp; - bool enableColor; - bool enableId; - uint32_t maxMessageLength; -}; -``` - -### 3. Template Specialization for Performance - -The logger uses compile-time optimizations where possible: - -```cpp -// Macros provide compile-time string concatenation -#define ASF_LOGI(tag, id, format, ...) \ - asf::logger::logInfo(tag, id, format, ##__VA_ARGS__) -``` - -### 4. Facade Pattern - -The logger acts as a facade over the ESP-IDF logging system, providing a simplified interface: - -```cpp -// Complex ESP-IDF logging -ESP_LOGI(TAG, "Message with %d parameters", value); - -// Simplified ASF logging -ASF_LOGI(TAG, 1001, "Message with %d parameters", value); -``` - -## Component Structure - -### File Organization - -``` -components/utils/logger/ -├── CMakeLists.txt # Build configuration -├── README.md # User documentation -├── ARCHITECTURE.md # This document -├── com/ # Core implementation -│ ├── logger.hpp # Public API header -│ └── logger.cpp # Implementation -├── test/ # Unit tests -│ ├── CMakeLists.txt -│ └── test_logger.cpp -└── example/ # Usage examples - └── gpio_wrapper_example.cpp -``` - -### Header Dependencies - -```mermaid -graph TD - A[logger.hpp] --> B[cstdint] - A --> C[cstdarg] - A --> D[esp_log.h] - A --> E[esp_timer.h] - - F[logger.cpp] --> A - F --> G[cstdio] - F --> H[cstring] - F --> I[ctime] - F --> J[sys/time.h] -``` - -## API Design - -### Function Hierarchy - -``` -asf::logger namespace -├── Configuration Functions -│ ├── initialize(config) -│ ├── setLogLevel(level) -│ ├── getLogLevel() -│ ├── enableTimestamp(enable) -│ ├── enableColor(enable) -│ └── enableId(enable) -├── Core Logging Functions -│ ├── log(tag, id, level, format, ...) -│ ├── logVerbose(tag, id, format, ...) -│ ├── logDebug(tag, id, format, ...) -│ ├── logInfo(tag, id, format, ...) -│ ├── logWarning(tag, id, format, ...) -│ └── logError(tag, id, format, ...) -├── Utility Functions -│ ├── getIsoTimestamp(buffer, size) -│ ├── logLevelToString(level) -│ ├── logLevelToColor(level) -│ └── getDefaultConfig() -└── Convenience Macros - ├── ASF_LOG_VERBOSE(tag, id, format, ...) - ├── ASF_LOG_DEBUG(tag, id, format, ...) - ├── ASF_LOG_INFO(tag, id, format, ...) - ├── ASF_LOG_WARNING(tag, id, format, ...) - ├── ASF_LOG_ERROR(tag, id, format, ...) - ├── ASF_LOGV(tag, id, format, ...) - ├── ASF_LOGD(tag, id, format, ...) - ├── ASF_LOGI(tag, id, format, ...) - ├── ASF_LOGW(tag, id, format, ...) - └── ASF_LOGE(tag, id, format, ...) -``` - -### Message Flow Architecture - -```mermaid -flowchart TD - A[Application Code] --> B{Macro Call} - B --> C[Level Check] - C --> D{Level >= MinLevel?} - D -->|No| E[Return - No Output] - D -->|Yes| F[Format Message] - F --> G[Add Timestamp] - G --> H[Add Color Codes] - H --> I[Add Message ID] - I --> J[Call ESP-IDF Log] - J --> K[Output to Console/UART] - - style A fill:#e1f5fe - style E fill:#ffebee - style K fill:#e8f5e8 -``` - -## Performance Analysis - -### Memory Usage - -| Component | Flash (bytes) | RAM (bytes) | Stack (bytes/call) | -|-----------|---------------|-------------|-------------------| -| Core Implementation | ~2048 | ~20 (static config) | ~400 | -| Macros | ~0 | ~0 | ~0 | -| Per Log Call | ~0 | ~0 | ~400 | -| **Total** | **~2KB** | **~20B** | **~400B** | - -### Performance Characteristics - -```mermaid -graph LR - subgraph "Performance Metrics" - A[Level Check: O(1)] - B[Message Format: O(n)] - C[Timestamp: O(1)] - D[ESP-IDF Call: O(1)] - end - - subgraph "Optimization Techniques" - E[Early Level Filtering] - F[Stack-based Buffers] - G[Compile-time Macros] - H[Minimal Function Calls] - end - - A --> E - B --> F - C --> G - D --> H -``` - -### Timing Analysis - -| Operation | Typical Time (μs) | Notes | -|-----------|------------------|-------| -| Level Check | < 0.1 | Simple integer comparison | -| Message Formatting | 10-50 | Depends on message complexity | -| Timestamp Generation | 5-10 | System call overhead | -| ESP-IDF Output | 100-1000 | UART/Console output speed | - -## Integration Guide - -### Step-by-Step Integration - -1. **Include Header** -```cpp -#include "logger.hpp" -``` - -2. **Initialize Logger** -```cpp -void app_main() { - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - config.minLevel = asf::logger::LogLevel::DEBUG; - asf::logger::initialize(config); -} -``` - -3. **Define Module Constants** -```cpp -// module_log_ids.hpp -static const char* TAG = "MY_MODULE"; -namespace MyModuleLogIds { - static const uint32_t INIT_SUCCESS = 1001; - static const uint32_t CONFIG_ERROR = 1601; -} -``` - -4. **Replace Existing Logging** -```cpp -// Before -ESP_LOGI(TAG, "Module initialized"); - -// After -ASF_LOGI(TAG, MyModuleLogIds::INIT_SUCCESS, "Module initialized"); -``` - -### Integration Patterns - -#### Pattern 1: Module-Specific Wrapper -```cpp -class ModuleLogger { -private: - static const char* TAG; - -public: - static void info(uint32_t id, const char* format, ...) { - va_list args; - va_start(args, format); - asf::logger::logInfo(TAG, id, format, args); - va_end(args); - } -}; -``` - -#### Pattern 2: Macro Wrapper -```cpp -#define MODULE_LOGI(id, format, ...) \ - ASF_LOGI("MODULE_NAME", id, format, ##__VA_ARGS__) -``` - -#### Pattern 3: Template Wrapper -```cpp -template -class TypedLogger { -public: - static void info(uint32_t id, const char* format, ...) { - // Implementation - } -}; -``` - -## Testing Strategy - -### Test Categories - -```mermaid -mindmap - root((ASF Logger Tests)) - Unit Tests - Configuration Tests - Level Filtering Tests - Message Formatting Tests - Utility Function Tests - Integration Tests - ESP-IDF Integration - Multi-threaded Usage - Performance Tests - System Tests - Memory Usage Tests - Real-world Scenarios - Error Handling Tests -``` - -### Test Coverage Matrix - -| Component | Unit Tests | Integration Tests | Performance Tests | -|-----------|------------|------------------|------------------| -| Configuration Manager | ✅ | ✅ | ✅ | -| Message Formatter | ✅ | ✅ | ✅ | -| Level Filtering | ✅ | ✅ | ✅ | -| Timestamp Generation | ✅ | ✅ | ✅ | -| Color Management | ✅ | ✅ | ❌ | -| Macro Interface | ✅ | ✅ | ✅ | -| Error Handling | ✅ | ✅ | ❌ | - -### Automated Testing Pipeline - -```mermaid -flowchart LR - A[Code Commit] --> B[Build Tests] - B --> C[Unit Tests] - C --> D[Integration Tests] - D --> E[Performance Tests] - E --> F[Memory Tests] - F --> G{All Pass?} - G -->|Yes| H[Deploy] - G -->|No| I[Report Failure] - I --> J[Fix Issues] - J --> A -``` - -## Future Enhancements - -### Planned Features - -1. **Log Rotation** - - File-based logging with rotation - - Configurable file sizes and retention - -2. **Remote Logging** - - Network-based log transmission - - Log aggregation support - -3. **Structured Logging** - - JSON format support - - Key-value pair logging - -4. **Performance Monitoring** - - Built-in performance metrics - - Log frequency analysis - -5. **Advanced Filtering** - - Tag-based filtering - - Runtime filter configuration - -### Architecture Evolution - -```mermaid -timeline - title ASF Logger Evolution - - section Phase 1 (Current) - Basic Logging : Core functionality - : ESP-IDF integration - : Message formatting - - section Phase 2 (Next) - Enhanced Features : File logging - : Network logging - : JSON support - - section Phase 3 (Future) - Advanced Analytics : Performance monitoring - : Log analysis - : Machine learning integration -``` - -### Extensibility Points - -The logger is designed with several extensibility points: - -1. **Custom Formatters**: Plugin architecture for message formatting -2. **Output Backends**: Support for multiple output destinations -3. **Filter Plugins**: Custom filtering logic -4. **Compression**: Log compression for storage efficiency - -## Conclusion - -The ASF Logger provides a robust, efficient, and extensible logging solution for ESP-IDF applications. Its namespace-based design ensures minimal overhead while providing rich functionality for structured logging with unique message identification. - -The architecture balances performance, usability, and maintainability, making it suitable for both development and production environments. The comprehensive testing strategy and clear integration patterns ensure reliable operation across various use cases. - -Future enhancements will focus on advanced features while maintaining the core design principles of simplicity, performance, and reliability. \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/CMakeLists.txt b/draft- to be removed SW/components/utils/logger/CMakeLists.txt deleted file mode 100644 index acaabf8..0000000 --- a/draft- to be removed SW/components/utils/logger/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/logger.cpp" - INCLUDE_DIRS "com" - REQUIRES log esp_timer -) \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/DIAGRAMS.md b/draft- to be removed SW/components/utils/logger/DIAGRAMS.md deleted file mode 100644 index e79b7fb..0000000 --- a/draft- to be removed SW/components/utils/logger/DIAGRAMS.md +++ /dev/null @@ -1,689 +0,0 @@ -# ASF Logger - UML Diagrams and Visual Documentation - -## Table of Contents -1. [System Overview](#system-overview) -2. [Class Diagrams](#class-diagrams) -3. [Sequence Diagrams](#sequence-diagrams) -4. [State Diagrams](#state-diagrams) -5. [Component Diagrams](#component-diagrams) -6. [Deployment Diagrams](#deployment-diagrams) -7. [Activity Diagrams](#activity-diagrams) - -## System Overview - -### High-Level System Architecture - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ Application Layer │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ GPIO │ │ UART │ │ I2C │ │ Other │ │ -│ │ Wrapper │ │ Wrapper │ │ Wrapper │ │ Modules │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ ASF Logger │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────────────┐ │ -│ │ Configuration │ │ Message │ │ API Layer │ │ -│ │ Manager │ │ Formatter │ │ ┌─────────────────────────────┐ │ │ -│ │ │ │ │ │ │ Convenience Macros │ │ │ -│ │ • Log Levels │ │ • Timestamps │ │ │ ASF_LOGI, ASF_LOGE, etc. │ │ │ -│ │ • Color Config │ │ • Color Codes │ │ └─────────────────────────────┘ │ │ -│ │ • Buffer Size │ │ • Message IDs │ │ ┌─────────────────────────────┐ │ │ -│ │ • Runtime Ctrl │ │ • Format String │ │ │ Core Functions │ │ │ -│ └─────────────────┘ └─────────────────┘ │ │ logInfo, logError, etc. │ │ │ -│ │ └─────────────────────────────┘ │ │ -│ └─────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ ESP-IDF Log System │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────────────┐ │ -│ │ Log Levels │ │ Tag Filtering │ │ Output Routing │ │ -│ │ │ │ │ │ │ │ -│ │ • ESP_LOG_NONE │ │ • Per-tag level │ │ • UART Console │ │ -│ │ • ESP_LOG_ERROR │ │ • Wildcard tags │ │ • JTAG Debug │ │ -│ │ • ESP_LOG_WARN │ │ • Runtime ctrl │ │ • Custom outputs │ │ -│ │ • ESP_LOG_INFO │ │ │ │ │ │ -│ │ • ESP_LOG_DEBUG │ │ │ │ │ │ -│ │ • ESP_LOG_VERBOSE│ │ │ │ │ │ -│ └─────────────────┘ └─────────────────┘ └─────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ Hardware Layer │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────────────┐ │ -│ │ UART │ │ JTAG │ │ Other I/O │ │ -│ │ Controller │ │ Interface │ │ │ │ -│ └─────────────────┘ └─────────────────┘ └─────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -## Class Diagrams - -### Core Logger Class Structure - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ asf::logger namespace │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ LogLevel (enum class) │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ + VERBOSE : uint8_t = 0 │ │ -│ │ + DEBUG : uint8_t = 1 │ │ -│ │ + INFO : uint8_t = 2 │ │ -│ │ + WARNING : uint8_t = 3 │ │ -│ │ + ERROR : uint8_t = 4 │ │ -│ │ + NONE : uint8_t = 5 │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ LoggerConfig (struct) │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ + minLevel : LogLevel │ │ -│ │ + enableTimestamp : bool │ │ -│ │ + enableColor : bool │ │ -│ │ + enableId : bool │ │ -│ │ + maxMessageLength : uint32_t │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ Logger Functions (namespace) │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ Static Data: │ │ -│ │ - s_config : LoggerConfig │ │ -│ │ - COLOR_RESET : const char* │ │ -│ │ - COLOR_VERBOSE : const char* │ │ -│ │ - COLOR_DEBUG : const char* │ │ -│ │ - COLOR_INFO : const char* │ │ -│ │ - COLOR_WARNING : const char* │ │ -│ │ - COLOR_ERROR : const char* │ │ -│ │ │ │ -│ │ Configuration Functions: │ │ -│ │ + initialize(config: LoggerConfig) : void │ │ -│ │ + setLogLevel(level: LogLevel) : void │ │ -│ │ + getLogLevel() : LogLevel │ │ -│ │ + enableTimestamp(enable: bool) : void │ │ -│ │ + enableColor(enable: bool) : void │ │ -│ │ + enableId(enable: bool) : void │ │ -│ │ + getDefaultConfig() : LoggerConfig │ │ -│ │ │ │ -│ │ Core Logging Functions: │ │ -│ │ + log(tag: char*, id: uint32_t, level: LogLevel, │ │ -│ │ format: char*, ...) : void │ │ -│ │ + logVerbose(tag: char*, id: uint32_t, │ │ -│ │ format: char*, ...) : void │ │ -│ │ + logDebug(tag: char*, id: uint32_t, │ │ -│ │ format: char*, ...) : void │ │ -│ │ + logInfo(tag: char*, id: uint32_t, │ │ -│ │ format: char*, ...) : void │ │ -│ │ + logWarning(tag: char*, id: uint32_t, │ │ -│ │ format: char*, ...) : void │ │ -│ │ + logError(tag: char*, id: uint32_t, │ │ -│ │ format: char*, ...) : void │ │ -│ │ │ │ -│ │ Utility Functions: │ │ -│ │ + getIsoTimestamp(buffer: char*, size: size_t) : char* │ │ -│ │ + logLevelToString(level: LogLevel) : char* │ │ -│ │ + logLevelToColor(level: LogLevel) : char* │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ Convenience Macros │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ Long Form: │ │ -│ │ • ASF_LOG_VERBOSE(tag, id, format, ...) │ │ -│ │ • ASF_LOG_DEBUG(tag, id, format, ...) │ │ -│ │ • ASF_LOG_INFO(tag, id, format, ...) │ │ -│ │ • ASF_LOG_WARNING(tag, id, format, ...) │ │ -│ │ • ASF_LOG_ERROR(tag, id, format, ...) │ │ -│ │ │ │ -│ │ Short Form: │ │ -│ │ • ASF_LOGV(tag, id, format, ...) │ │ -│ │ • ASF_LOGD(tag, id, format, ...) │ │ -│ │ • ASF_LOGI(tag, id, format, ...) │ │ -│ │ • ASF_LOGW(tag, id, format, ...) │ │ -│ │ • ASF_LOGE(tag, id, format, ...) │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -### Relationship with ESP-IDF - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ ASF Logger Dependencies │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ asf::logger │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ │ uses │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ ESP-IDF Log System │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ + ESP_LOGV(tag, format, ...) │ │ -│ │ + ESP_LOGD(tag, format, ...) │ │ -│ │ + ESP_LOGI(tag, format, ...) │ │ -│ │ + ESP_LOGW(tag, format, ...) │ │ -│ │ + ESP_LOGE(tag, format, ...) │ │ -│ │ + esp_log_level_set(tag, level) │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ │ uses │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ System Libraries │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ Standard C Library: │ │ -│ │ • cstdio (printf family) │ │ -│ │ • cstring (string operations) │ │ -│ │ • ctime (time formatting) │ │ -│ │ • cstdarg (variadic functions) │ │ -│ │ │ │ -│ │ POSIX Functions: │ │ -│ │ • sys/time.h (gettimeofday) │ │ -│ │ │ │ -│ │ ESP-IDF Specific: │ │ -│ │ • esp_timer.h (high resolution timing) │ │ -│ │ • esp_log.h (logging infrastructure) │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -## Sequence Diagrams - -### Basic Logging Sequence - -``` -Application ASF_LOGI asf::logger Message ESP-IDF Console - Code Macro ::logInfo Formatter Log Sys Output - │ │ │ │ │ │ - │ Log Call │ │ │ │ │ - ├────────────► │ │ │ │ - │ │ logInfo() │ │ │ │ - │ ├─────────────► │ │ │ - │ │ │ Level Check │ │ │ - │ │ ├─────────────┤ │ │ - │ │ │ │ │ │ - │ │ │ Level OK? │ │ │ - │ │ ├─────────────┤ │ │ - │ │ │ │ │ │ - │ │ │ Format Msg │ │ │ - │ │ ├─────────────► │ │ - │ │ │ │ Formatted │ │ - │ │ │ │ Message │ │ - │ │ │ ◄─────────────┤ │ - │ │ │ │ │ │ - │ │ │ ESP_LOGI() │ │ │ - │ │ ├─────────────────────────────► │ - │ │ │ │ │ Output │ - │ │ │ │ ├────────────► - │ │ │ │ │ │ - │ │ Return │ │ │ │ - │ ◄─────────────┤ │ │ │ - │ Return │ │ │ │ │ - ◄────────────┤ │ │ │ │ - │ │ │ │ │ │ -``` - -### Configuration Change Sequence - -``` -Application asf::logger Configuration ESP-IDF - Code Functions Manager Log System - │ │ │ │ - │ setLogLevel │ │ │ - ├─────────────► │ │ - │ │ Update Config │ │ - │ ├───────────────► │ - │ │ │ Set ESP Level│ - │ │ ├──────────────► - │ │ │ │ - │ │ Config Updated│ │ - │ ◄───────────────┤ │ - │ Return │ │ │ - ◄─────────────┤ │ │ - │ │ │ │ - │ │ │ │ - │ Next Log │ │ │ - ├─────────────► │ │ - │ │ Check Level │ │ - │ ├───────────────► │ - │ │ New Level │ │ - │ ◄───────────────┤ │ - │ │ │ │ - │ Log Output │ │ │ - ◄─────────────┤ │ │ - │ │ │ │ -``` - -### Error Handling Sequence - -``` -Application ASF_LOGE asf::logger Message ESP-IDF Console - Code Macro ::logError Formatter Log Sys Output - │ │ │ │ │ │ - │ Error Log │ │ │ │ │ - ├────────────► │ │ │ │ - │ │ logError() │ │ │ │ - │ ├─────────────► │ │ │ - │ │ │ Level Check │ │ │ - │ │ ├─────────────┤ │ │ - │ │ │ (Always OK │ │ │ - │ │ │ for ERROR) │ │ │ - │ │ │ │ │ │ - │ │ │ Format Msg │ │ │ - │ │ ├─────────────► │ │ - │ │ │ │ Add Error │ │ - │ │ │ │ Color Code │ │ - │ │ │ │ Add Timestamp│ │ - │ │ │ │ Add Message │ │ - │ │ │ │ ID │ │ - │ │ │ │ │ │ - │ │ │ │ Formatted │ │ - │ │ │ │ Error Msg │ │ - │ │ │ ◄─────────────┤ │ - │ │ │ │ │ │ - │ │ │ ESP_LOGE() │ │ │ - │ │ ├─────────────────────────────► │ - │ │ │ │ │ Red Error │ - │ │ │ │ │ Output │ - │ │ │ │ ├────────────► - │ │ │ │ │ │ - │ │ Return │ │ │ │ - │ ◄─────────────┤ │ │ │ - │ Return │ │ │ │ │ - ◄────────────┤ │ │ │ │ - │ │ │ │ │ │ -``` - -## State Diagrams - -### Logger State Machine - -``` - ┌─────────────────────────────────────────────────────────┐ - │ Logger State Machine │ - └─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ [Initial State] │ - │ Uninitialized │ - │ │ - │ • No configuration loaded │ - │ • Default ESP-IDF logging active │ - │ • ASF functions not available │ - └─────────────────────────────────────────────────────────┘ - │ - │ initialize(config) - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Initialized │ - │ │ - │ • Configuration loaded │ - │ • ESP-IDF log level set │ - │ • ASF functions active │ - │ • Ready for logging │ - └─────────────────────────────────────────────────────────┘ - │ - │ - ┌─────────────────────────┼─────────────────────────┐ - │ │ │ - ▼ ▼ ▼ - ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ - │ Level Filter │ │ Message Format │ │ Runtime Config │ - │ │ │ │ │ │ - │ • Check min level │ │ • Add timestamp │ │ • Change log level │ - │ • Allow/block msg │ │ • Add color codes │ │ • Toggle features │ - │ • Early return │ │ • Add message ID │ │ • Update settings │ - └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ - │ │ │ - │ │ │ - └─────────────────────────┼─────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Output Ready │ - │ │ - │ • Message formatted │ - │ • Ready for ESP-IDF output │ - │ • All processing complete │ - └─────────────────────────────────────────────────────────┘ - │ - │ ESP_LOG*() call - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Message Output │ - │ │ - │ • Sent to ESP-IDF log system │ - │ • Routed to console/UART │ - │ • Visible to user │ - └─────────────────────────────────────────────────────────┘ -``` - -### Configuration State Transitions - -``` - ┌─────────────────────────────────────────────────────────┐ - │ Configuration States │ - └─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Default Config │ - │ │ - │ minLevel = INFO │ - │ enableTimestamp = true │ - │ enableColor = true │ - │ enableId = true │ - │ maxMessageLength = 256 │ - └─────────────────────────────────────────────────────────┘ - │ - │ Runtime changes - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Custom Config │ - │ │ - │ User-modified settings: │ - │ • setLogLevel() │ - │ • enableTimestamp() │ - │ • enableColor() │ - │ • enableId() │ - └─────────────────────────────────────────────────────────┘ - │ - │ initialize(defaultConfig) - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Reset to Default │ - │ │ - │ All settings restored to default values │ - └─────────────────────────────────────────────────────────┘ -``` - -## Component Diagrams - -### Internal Component Structure - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ ASF Logger Component │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ Public Interface │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │ -│ │ │ Core API │ │ Convenience │ │ Configuration │ │ │ -│ │ │ Functions │ │ Macros │ │ API │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • logInfo() │ │ • ASF_LOGI() │ │ • initialize() │ │ │ -│ │ │ • logError() │ │ • ASF_LOGE() │ │ • setLogLevel() │ │ │ -│ │ │ • logDebug() │ │ • ASF_LOGD() │ │ • enableColor() │ │ │ -│ │ │ • logWarning() │ │ • ASF_LOGW() │ │ • getLogLevel() │ │ │ -│ │ │ • logVerbose() │ │ • ASF_LOGV() │ │ │ │ │ -│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ Internal Components │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │ -│ │ │ Configuration │ │ Message │ │ Utility │ │ │ -│ │ │ Manager │ │ Formatter │ │ Functions │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • Static config │ │ • Timestamp gen │ │ • Level to string │ │ │ -│ │ │ • Level filter │ │ • Color codes │ │ • Level to color │ │ │ -│ │ │ • Runtime ctrl │ │ • Message ID │ │ • Default config │ │ │ -│ │ │ • Validation │ │ • Format string │ │ • Validation │ │ │ -│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ External Dependencies │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │ -│ │ │ ESP-IDF Log │ │ Standard C │ │ POSIX Time │ │ │ -│ │ │ System │ │ Library │ │ Functions │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • ESP_LOGI() │ │ • printf() │ │ • gettimeofday() │ │ │ -│ │ │ • ESP_LOGE() │ │ • snprintf() │ │ • localtime() │ │ │ -│ │ │ • ESP_LOGD() │ │ • vsnprintf() │ │ • struct timeval │ │ │ -│ │ │ • ESP_LOGW() │ │ • memset() │ │ │ │ │ -│ │ │ • ESP_LOGV() │ │ • strlen() │ │ │ │ │ -│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -### Data Flow Component Diagram - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ Data Flow Architecture │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │ -│ │ Application │ │ ASF Logger │ │ ESP-IDF Log │ │ -│ │ Code │ │ Macros │ │ System │ │ -│ │ │ │ │ │ │ │ -│ │ • Log calls │───►│ • ASF_LOGI() │───►│ • ESP_LOGI() │ │ -│ │ • Error msgs │ │ • ASF_LOGE() │ │ • ESP_LOGE() │ │ -│ │ • Debug info │ │ • ASF_LOGD() │ │ • Level filtering │ │ -│ └─────────────────┘ └─────────────────┘ └─────────────────────────┘ │ -│ │ │ │ -│ ▼ ▼ │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │ -│ │ Message ID │ │ Message │ │ Console/UART │ │ -│ │ Management │ │ Formatter │ │ Output │ │ -│ │ │ │ │ │ │ │ -│ │ • ID validation │───►│ • Timestamp │───►│ • Serial output │ │ -│ │ • Range check │ │ • Color codes │ │ • JTAG debug │ │ -│ │ • Uniqueness │ │ • Format string │ │ • Custom handlers │ │ -│ └─────────────────┘ └─────────────────┘ └─────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ Configuration │ │ Level │ │ -│ │ Manager │ │ Filter │ │ -│ │ │ │ │ │ -│ │ • Runtime cfg │───►│ • Min level │ │ -│ │ • Feature flags │ │ • Early return │ │ -│ │ • Buffer size │ │ • Performance │ │ -│ └─────────────────┘ └─────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -## Deployment Diagrams - -### ESP32 System Deployment - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ ESP32 Device │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ Flash Memory │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │ -│ │ │ Application │ │ ASF Logger │ │ ESP-IDF │ │ │ -│ │ │ Code │ │ Component │ │ Framework │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • Main app │ │ • logger.cpp │ │ • Log system │ │ │ -│ │ │ • GPIO wrapper │ │ • logger.hpp │ │ • UART drivers │ │ │ -│ │ │ • UART wrapper │ │ • Macros │ │ • System libs │ │ │ -│ │ │ • Other modules │ │ • Config │ │ • FreeRTOS │ │ │ -│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ RAM Memory │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │ -│ │ │ Stack │ │ Static Data │ │ Heap │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • Log buffers │ │ • Logger config │ │ • Dynamic alloc │ │ │ -│ │ │ • Function vars │ │ • Color strings │ │ • Task stacks │ │ │ -│ │ │ • Call stack │ │ • Constants │ │ • Buffers │ │ │ -│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ Hardware Interfaces │ │ -│ ├─────────────────────────────────────────────────────────────────────┤ │ -│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │ -│ │ │ UART │ │ JTAG │ │ GPIO │ │ │ -│ │ │ Controller │ │ Interface │ │ Pins │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • Serial output │ │ • Debug output │ │ • Status LEDs │ │ │ -│ │ │ • Console I/O │ │ • Trace data │ │ • Debug signals │ │ │ -│ │ │ • Log routing │ │ • Real-time │ │ • External conn │ │ │ -│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ External Connections │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐ │ -│ │ Serial │ │ Debug Probe │ │ Network/WiFi │ │ -│ │ Console │ │ │ │ │ │ -│ │ │ │ • JTAG adapter │ │ • Remote logging │ │ -│ │ • Terminal app │ │ • OpenOCD │ │ • Log aggregation │ │ -│ │ • Log viewer │ │ • GDB debug │ │ • Cloud logging │ │ -│ │ • Real-time │ │ • Trace viewer │ │ • Monitoring systems │ │ -│ └─────────────────┘ └─────────────────┘ └─────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -## Activity Diagrams - -### Logging Process Activity - -``` - ┌─────────────────────────────────────────────────────────┐ - │ Logging Activity │ - └─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ [Start] │ - │ Application Log Call │ - └─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Macro Expansion │ - │ │ - │ ASF_LOGI(TAG, ID, format, args) │ - │ ↓ │ - │ asf::logger::logInfo(TAG, ID, format, args) │ - └─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Level Check │ - │ │ - │ Is INFO >= minLevel? │ - └─────────────────────────────────────────────────────────┘ - │ - ┌─────────┴─────────┐ - │ │ - No Yes - │ │ - ▼ ▼ - ┌─────────────────────┐ ┌─────────────────────────────────┐ - │ [End] │ │ Format Message │ - │ Early Return │ │ │ - │ (No Output) │ │ • Get timestamp │ - └─────────────────────┘ │ • Add color codes │ - │ • Add message ID │ - │ • Format with args │ - └─────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────┐ - │ Call ESP-IDF │ - │ │ - │ ESP_LOGI("ASF", formatted_msg) │ - └─────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────┐ - │ Output Routing │ - │ │ - │ • Check ESP-IDF log level │ - │ • Route to console/UART │ - │ • Apply ESP-IDF formatting │ - └─────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────┐ - │ [End] │ - │ Message Output │ - └─────────────────────────────────┘ -``` - -### Configuration Change Activity - -``` - ┌─────────────────────────────────────────────────────────┐ - │ Configuration Change Activity │ - └─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ [Start] │ - │ Configuration Change Request │ - └─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────────┐ - │ Validate Parameters │ - │ │ - │ • Check log level range │ - │ • Validate boolean flags │ - │ • Check buffer size limits │ - └─────────────────────────────────────────────────────────┘ - │ - ┌─────────┴─────────┐ - │ │ - Valid Invalid - │ │ - ▼ ▼ - ┌─────────────────────────────────┐ ┌─────────────────────┐ - │ Update Configuration │ │ [End] │ - │ │ │ Return Error │ - │ • Modify static config │ │ │ - │ • Store new values │ └─────────────────────┘ - └─────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────┐ - │ Update ESP-IDF Settings │ - │ │ - │ esp_log_level_set("*", level) │ - └─────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────┐ - │ Apply Changes │ - │ │ - │ • New settings active │ - │ • Subsequent logs affected │ - └─────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────┐ - │ [End] │ - │ Configuration Updated │ - └─────────────────────────────────┘ -``` - -This comprehensive visual documentation provides detailed UML diagrams and architectural views of the ASF Logger system, showing how all components interact and the flow of data through the system. These diagrams can be used for understanding the system architecture, debugging issues, and planning future enhancements. \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/README.md b/draft- to be removed SW/components/utils/logger/README.md deleted file mode 100644 index c7a378a..0000000 --- a/draft- to be removed SW/components/utils/logger/README.md +++ /dev/null @@ -1,431 +0,0 @@ -# ASF Logger Module - -## Overview - -The ASF Logger module provides a comprehensive C++ wrapper for ESP-IDF logging functionality. It offers a clean, efficient, and feature-rich logging interface that abstracts the underlying ESP-IDF logging mechanism while providing enhanced formatting, filtering, and configuration options. - -## Features - -- **Multiple Log Levels**: Verbose, Debug, Info, Warning, Error -- **ISO 8601 Timestamps**: Precise timestamping with millisecond accuracy -- **Unique Message IDs**: Track and identify specific log messages -- **Color-Coded Output**: Visual distinction between log levels -- **Configurable Filtering**: Runtime log level adjustment -- **Low Overhead**: Minimal performance impact with compile-time optimizations -- **Thread-Safe**: Built on ESP-IDF's thread-safe logging system -- **Easy Integration**: Simple namespace-based API with convenient macros - -## Architecture - -### Design Philosophy - -The logger is implemented as a namespace with free functions rather than a class-based approach for several reasons: - -1. **Zero Overhead**: No object instantiation or virtual function calls -2. **Compile-Time Efficiency**: Header-only interface with minimal includes -3. **Easy Integration**: Simple include without complex initialization -4. **Memory Efficient**: No per-instance memory overhead -5. **Thread-Safe**: Stateless design with minimal shared state - -### Output Format - -The logger produces output in the following format: -``` -ISO_TIMESTAMP : TAG[LEVEL] : ID : Message -``` - -Example: -``` -2025-01-21T10:30:45.123Z : GPIO_WRAPPER[INFO] : 1001 : GPIO wrapper initialized -2025-01-21T10:30:45.124Z : UART_WRAPPER[ERROR] : 2001 : Failed to configure UART port 0 -``` - -### Class Diagram - -``` -┌─────────────────────────────────────┐ -│ asf::logger │ -│ (namespace) │ -├─────────────────────────────────────┤ -│ + initialize(config): void │ -│ + setLogLevel(level): void │ -│ + getLogLevel(): LogLevel │ -│ + enableTimestamp(enable): void │ -│ + enableColor(enable): void │ -│ + enableId(enable): void │ -│ + getIsoTimestamp(buf, size): char* │ -│ + log(tag, id, level, fmt, ...): void│ -│ + logVerbose(tag, id, fmt, ...): void│ -│ + logDebug(tag, id, fmt, ...): void │ -│ + logInfo(tag, id, fmt, ...): void │ -│ + logWarning(tag, id, fmt, ...): void│ -│ + logError(tag, id, fmt, ...): void │ -│ + getDefaultConfig(): LoggerConfig │ -│ + logLevelToString(level): char* │ -│ + logLevelToColor(level): char* │ -└─────────────────────────────────────┘ -``` - -### Enumerations - -#### LogLevel -- `VERBOSE`: Most detailed logging (level 0) -- `DEBUG`: Debug information (level 1) -- `INFO`: General information (level 2) -- `WARNING`: Warning messages (level 3) -- `ERROR`: Error messages (level 4) -- `NONE`: No logging (level 5) - -### Configuration Structure - -```cpp -struct LoggerConfig { - LogLevel minLevel; // Minimum log level to display - bool enableTimestamp; // Enable ISO timestamp in output - bool enableColor; // Enable color output - bool enableId; // Enable unique ID in output - uint32_t maxMessageLength; // Maximum message length -}; -``` - -## Usage Examples - -### Basic Usage - -```cpp -#include "logger.hpp" - -static const char* TAG = "MY_MODULE"; - -void myFunction() { - // Initialize logger with default configuration - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - asf::logger::initialize(config); - - // Log messages with different levels - asf::logger::logInfo(TAG, 1001, "Module initialized successfully"); - asf::logger::logWarning(TAG, 1002, "Configuration parameter missing, using default: %d", 42); - asf::logger::logError(TAG, 1003, "Failed to connect to server: %s", "timeout"); -} -``` - -### Using Convenience Macros - -```cpp -#include "logger.hpp" - -static const char* TAG = "SENSOR_MODULE"; - -void sensorTask() { - // Short form macros for easier usage - ASF_LOGI(TAG, 2001, "Sensor task started"); - ASF_LOGD(TAG, 2002, "Reading sensor value: %d", sensorValue); - ASF_LOGW(TAG, 2003, "Sensor value out of range: %d", sensorValue); - ASF_LOGE(TAG, 2004, "Sensor communication failed"); - - // Long form macros - ASF_LOG_INFO(TAG, 2005, "Sensor calibration complete"); - ASF_LOG_ERROR(TAG, 2006, "Critical sensor failure detected"); -} -``` - -### Custom Configuration - -```cpp -#include "logger.hpp" - -void setupCustomLogger() { - asf::logger::LoggerConfig config = {}; - config.minLevel = asf::logger::LogLevel::DEBUG; - config.enableTimestamp = true; - config.enableColor = false; // Disable colors for file output - config.enableId = true; - config.maxMessageLength = 512; // Longer messages - - asf::logger::initialize(config); - - // Runtime configuration changes - asf::logger::setLogLevel(asf::logger::LogLevel::WARNING); - asf::logger::enableColor(true); -} -``` - -### Performance-Critical Code - -```cpp -#include "logger.hpp" - -static const char* TAG = "PERFORMANCE"; - -void performanceCriticalFunction() { - // Check log level before expensive operations - if (asf::logger::getLogLevel() <= asf::logger::LogLevel::DEBUG) { - // Only format expensive debug info if debug logging is enabled - char debugInfo[256]; - formatExpensiveDebugInfo(debugInfo, sizeof(debugInfo)); - ASF_LOGD(TAG, 3001, "Debug info: %s", debugInfo); - } - - // Error logging is always fast - ASF_LOGE(TAG, 3002, "Critical error occurred"); -} -``` - -### Module-Specific Logging - -```cpp -// gpio_wrapper.cpp -#include "logger.hpp" - -static const char* TAG = "GPIO_WRAPPER"; - -class Gpio { -public: - bool configure(uint32_t pin, GpioMode mode) { - ASF_LOGI(TAG, 4001, "Configuring GPIO pin %lu", pin); - - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 4002, "Invalid GPIO pin: %lu", pin); - return false; - } - - ASF_LOGD(TAG, 4003, "GPIO pin %lu configured successfully", pin); - return true; - } -}; -``` - -## API Reference - -### Initialization Functions - -- **initialize(config)**: Initialize logger with configuration -- **getDefaultConfig()**: Get default logger configuration - -### Configuration Functions - -- **setLogLevel(level)**: Set minimum log level -- **getLogLevel()**: Get current minimum log level -- **enableTimestamp(enable)**: Enable/disable timestamp -- **enableColor(enable)**: Enable/disable color output -- **enableId(enable)**: Enable/disable message ID - -### Logging Functions - -- **log(tag, id, level, format, ...)**: Main logging function -- **logVerbose(tag, id, format, ...)**: Log verbose message -- **logDebug(tag, id, format, ...)**: Log debug message -- **logInfo(tag, id, format, ...)**: Log info message -- **logWarning(tag, id, format, ...)**: Log warning message -- **logError(tag, id, format, ...)**: Log error message - -### Utility Functions - -- **getIsoTimestamp(buffer, size)**: Get ISO 8601 timestamp -- **logLevelToString(level)**: Convert log level to string -- **logLevelToColor(level)**: Convert log level to color code - -### Convenience Macros - -#### Long Form Macros -- `ASF_LOG_VERBOSE(tag, id, format, ...)` -- `ASF_LOG_DEBUG(tag, id, format, ...)` -- `ASF_LOG_INFO(tag, id, format, ...)` -- `ASF_LOG_WARNING(tag, id, format, ...)` -- `ASF_LOG_ERROR(tag, id, format, ...)` - -#### Short Form Macros -- `ASF_LOGV(tag, id, format, ...)` -- `ASF_LOGD(tag, id, format, ...)` -- `ASF_LOGI(tag, id, format, ...)` -- `ASF_LOGW(tag, id, format, ...)` -- `ASF_LOGE(tag, id, format, ...)` - -## Message ID Guidelines - -To maintain consistency and avoid conflicts, follow these guidelines for message IDs: - -### ID Ranges by Module -- **1000-1999**: Core system modules -- **2000-2999**: Hardware abstraction layer (HAL) -- **3000-3999**: Application layer -- **4000-4999**: Communication modules -- **5000-5999**: User interface modules -- **6000-6999**: Test and debug modules - -### ID Ranges by Severity -Within each module range: -- **x001-x199**: Info messages -- **x200-x399**: Debug messages -- **x400-x599**: Warning messages -- **x600-x799**: Error messages -- **x800-x999**: Verbose messages - -### Example ID Assignment -```cpp -// GPIO Wrapper (HAL module, range 2000-2999) -static const uint32_t GPIO_INIT_SUCCESS = 2001; // Info -static const uint32_t GPIO_PIN_CONFIGURED = 2002; // Info -static const uint32_t GPIO_DEBUG_STATE = 2201; // Debug -static const uint32_t GPIO_INVALID_PIN = 2601; // Error -static const uint32_t GPIO_CONFIG_FAILED = 2602; // Error -``` - -## Performance Considerations - -### Compile-Time Optimizations - -The logger is designed for minimal overhead: - -1. **Level Filtering**: Messages below the minimum level are filtered at runtime -2. **Macro Efficiency**: Macros provide zero-overhead abstraction -3. **String Formatting**: Only performed when message will be output -4. **Memory Usage**: Fixed buffer sizes prevent dynamic allocation - -### Runtime Performance - -- **Fast Level Check**: O(1) log level comparison -- **Efficient Formatting**: Uses stack-based buffers -- **Minimal Function Calls**: Direct ESP-IDF integration -- **Thread-Safe**: No locking overhead (ESP-IDF handles synchronization) - -### Memory Usage - -- **Static Configuration**: ~20 bytes of static memory -- **Stack Usage**: ~400 bytes per log call (configurable) -- **No Heap Allocation**: All operations use stack memory -- **Flash Usage**: ~2KB for complete implementation - -## Integration with ESP-IDF Wrappers - -### Replacing ESP-IDF Logging - -Replace ESP-IDF logging calls in your wrappers: - -```cpp -// Before (ESP-IDF logging) -ESP_LOGI(TAG, "GPIO wrapper initialized"); -ESP_LOGE(TAG, "Failed to configure GPIO pin %lu: %s", pin, esp_err_to_name(ret)); - -// After (ASF logging) -ASF_LOGI(TAG, 1001, "GPIO wrapper initialized"); -ASF_LOGE(TAG, 1002, "Failed to configure GPIO pin %lu: %s", pin, esp_err_to_name(ret)); -``` - -### Consistent Error Reporting - -```cpp -bool Gpio::configure(uint32_t pin, GpioMode mode) { - ASF_LOGI(TAG, 2001, "Configuring GPIO pin %lu", pin); - - if (!isValidPin(pin)) { - ASF_LOGE(TAG, 2002, "Invalid GPIO pin: %lu", pin); - return false; - } - - esp_err_t ret = gpio_config(&config); - if (ret != ESP_OK) { - ASF_LOGE(TAG, 2003, "Failed to configure GPIO pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, 2004, "GPIO pin %lu configured successfully", pin); - return true; -} -``` - -## Testing - -The logger includes comprehensive unit tests covering: - -- **Initialization and Configuration**: Default and custom configurations -- **Log Level Management**: Setting and getting log levels -- **Message Formatting**: Timestamp, color, and ID formatting -- **Null Parameter Handling**: Graceful handling of invalid inputs -- **Performance Testing**: High-frequency logging scenarios -- **Macro Functionality**: All convenience macros -- **Edge Cases**: Long messages, buffer limits, etc. - -### Running Tests - -```bash -# Build and run logger tests -idf.py build -idf.py flash monitor -``` - -## Dependencies - -- ESP-IDF logging system (`esp_log.h`) -- ESP-IDF timer (`esp_timer.h`) -- Standard C library (`cstdio`, `cstring`, `ctime`) -- POSIX time functions (`sys/time.h`) - -## Thread Safety - -The ASF Logger is thread-safe because: - -1. **ESP-IDF Integration**: Uses ESP-IDF's thread-safe logging system -2. **Minimal Shared State**: Only configuration is shared between threads -3. **Atomic Operations**: Configuration changes are atomic -4. **Stack-Based Buffers**: Each thread uses its own stack space - -## Limitations - -- **Message Length**: Limited by configured maximum message length (default: 256 characters) -- **ID Range**: 32-bit unsigned integer range (0 to 4,294,967,295) -- **Color Support**: Depends on terminal/console color support -- **Timestamp Accuracy**: Limited by system clock resolution - -## Migration Guide - -### From ESP-IDF Logging - -1. Include the ASF logger header: -```cpp -#include "logger.hpp" -``` - -2. Replace ESP-IDF logging calls: -```cpp -// Old -ESP_LOGI(TAG, "Message"); -ESP_LOGE(TAG, "Error: %d", error); - -// New -ASF_LOGI(TAG, 1001, "Message"); -ASF_LOGE(TAG, 1002, "Error: %d", error); -``` - -3. Initialize the logger in your main function: -```cpp -void app_main() { - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - asf::logger::initialize(config); - - // Your application code -} -``` - -### Message ID Assignment - -Create a header file for your module's message IDs: - -```cpp -// module_log_ids.hpp -#pragma once - -namespace MyModule { - namespace LogIds { - // Info messages (1001-1199) - static const uint32_t INIT_SUCCESS = 1001; - static const uint32_t CONFIG_LOADED = 1002; - - // Error messages (1600-1799) - static const uint32_t INIT_FAILED = 1601; - static const uint32_t CONFIG_ERROR = 1602; - } -} -``` - -This ASF Logger provides a robust, efficient, and feature-rich logging solution that enhances the ESP-IDF logging system while maintaining compatibility and performance. \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/USAGE_GUIDE.md b/draft- to be removed SW/components/utils/logger/USAGE_GUIDE.md deleted file mode 100644 index 2096c11..0000000 --- a/draft- to be removed SW/components/utils/logger/USAGE_GUIDE.md +++ /dev/null @@ -1,630 +0,0 @@ -# ASF Logger - Usage Guide - -## Table of Contents -1. [Quick Start](#quick-start) -2. [Basic Usage](#basic-usage) -3. [Advanced Configuration](#advanced-configuration) -4. [Message ID Management](#message-id-management) -5. [Integration Examples](#integration-examples) -6. [Best Practices](#best-practices) -7. [Troubleshooting](#troubleshooting) -8. [Migration Guide](#migration-guide) - -## Quick Start - -### 1. Include the Logger -```cpp -#include "logger.hpp" -``` - -### 2. Initialize in main() -```cpp -void app_main() { - // Initialize with default settings - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - asf::logger::initialize(config); - - // Your application code here -} -``` - -### 3. Start Logging -```cpp -static const char* TAG = "MAIN"; - -ASF_LOGI(TAG, 1001, "Application started"); -ASF_LOGW(TAG, 1002, "Warning: Low memory detected"); -ASF_LOGE(TAG, 1003, "Error: Failed to initialize sensor"); -``` - -### 4. Expected Output -``` -2025-01-21T10:30:45.123Z : MAIN[INFO] : 1001 : Application started -2025-01-21T10:30:45.124Z : MAIN[WARNING] : 1002 : Warning: Low memory detected -2025-01-21T10:30:45.125Z : MAIN[ERROR] : 1003 : Error: Failed to initialize sensor -``` - -## Basic Usage - -### Available Log Levels - -```cpp -// Verbose - Most detailed information -ASF_LOGV(TAG, 1001, "Detailed debug information: %d", value); - -// Debug - Debug information -ASF_LOGD(TAG, 1002, "Debug: Processing item %d", itemId); - -// Info - General information -ASF_LOGI(TAG, 1003, "System initialized successfully"); - -// Warning - Warning conditions -ASF_LOGW(TAG, 1004, "Warning: Configuration missing, using default"); - -// Error - Error conditions -ASF_LOGE(TAG, 1005, "Error: Failed to connect to server"); -``` - -### Long Form Macros - -```cpp -// Alternative syntax (same functionality) -ASF_LOG_VERBOSE(TAG, 1001, "Verbose message"); -ASF_LOG_DEBUG(TAG, 1002, "Debug message"); -ASF_LOG_INFO(TAG, 1003, "Info message"); -ASF_LOG_WARNING(TAG, 1004, "Warning message"); -ASF_LOG_ERROR(TAG, 1005, "Error message"); -``` - -### Direct Function Calls - -```cpp -// Direct function calls (less common usage) -asf::logger::logInfo(TAG, 1001, "Direct function call"); -asf::logger::logError(TAG, 1002, "Error via function call"); -``` - -## Advanced Configuration - -### Custom Configuration - -```cpp -void setupCustomLogger() { - asf::logger::LoggerConfig config = {}; - - // Set minimum log level - config.minLevel = asf::logger::LogLevel::DEBUG; - - // Configure output format - config.enableTimestamp = true; // Show timestamps - config.enableColor = false; // Disable colors (for file output) - config.enableId = true; // Show message IDs - - // Set buffer size - config.maxMessageLength = 512; // Longer messages - - // Apply configuration - asf::logger::initialize(config); -} -``` - -### Runtime Configuration Changes - -```cpp -void configureLoggerAtRuntime() { - // Change log level during runtime - asf::logger::setLogLevel(asf::logger::LogLevel::WARNING); - - // Toggle features - asf::logger::enableTimestamp(false); // Disable timestamps - asf::logger::enableColor(true); // Enable colors - asf::logger::enableId(false); // Disable message IDs - - // Check current settings - asf::logger::LogLevel currentLevel = asf::logger::getLogLevel(); - ASF_LOGI("CONFIG", 2001, "Current log level: %s", - asf::logger::logLevelToString(currentLevel)); -} -``` - -### Production vs Development Settings - -```cpp -void setupProductionLogger() { - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - - // Production settings - config.minLevel = asf::logger::LogLevel::WARNING; // Only warnings and errors - config.enableColor = false; // No colors for log files - config.maxMessageLength = 128; // Smaller buffer - - asf::logger::initialize(config); -} - -void setupDevelopmentLogger() { - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - - // Development settings - config.minLevel = asf::logger::LogLevel::VERBOSE; // All messages - config.enableColor = true; // Colorful output - config.maxMessageLength = 512; // Larger buffer - - asf::logger::initialize(config); -} -``` - -## Message ID Management - -### ID Allocation Strategy - -```cpp -// Create a header file for your module's log IDs -// my_module_log_ids.hpp - -#pragma once - -namespace MyModuleLogIds { - // Info messages (1001-1199) - static const uint32_t MODULE_INIT = 1001; - static const uint32_t CONFIG_LOADED = 1002; - static const uint32_t TASK_STARTED = 1003; - static const uint32_t CONNECTION_ESTABLISHED = 1004; - - // Debug messages (1201-1399) - static const uint32_t DEBUG_STATE_CHANGE = 1201; - static const uint32_t DEBUG_DATA_RECEIVED = 1202; - static const uint32_t DEBUG_PROCESSING = 1203; - - // Warning messages (1401-1599) - static const uint32_t CONFIG_MISSING = 1401; - static const uint32_t MEMORY_LOW = 1402; - static const uint32_t TIMEOUT_WARNING = 1403; - - // Error messages (1601-1799) - static const uint32_t INIT_FAILED = 1601; - static const uint32_t CONNECTION_FAILED = 1602; - static const uint32_t CRITICAL_ERROR = 1603; -} -``` - -### Using Message IDs - -```cpp -#include "my_module_log_ids.hpp" - -static const char* TAG = "MY_MODULE"; - -void myModuleInit() { - ASF_LOGI(TAG, MyModuleLogIds::MODULE_INIT, "Initializing module"); - - if (!loadConfiguration()) { - ASF_LOGW(TAG, MyModuleLogIds::CONFIG_MISSING, - "Configuration file missing, using defaults"); - } else { - ASF_LOGI(TAG, MyModuleLogIds::CONFIG_LOADED, "Configuration loaded successfully"); - } - - if (!initializeHardware()) { - ASF_LOGE(TAG, MyModuleLogIds::INIT_FAILED, "Hardware initialization failed"); - return; - } - - ASF_LOGI(TAG, MyModuleLogIds::TASK_STARTED, "Module initialization complete"); -} -``` - -### Global ID Registry - -```cpp -// global_log_ids.hpp -#pragma once - -namespace GlobalLogIds { - // System-wide ID ranges - namespace System { - static const uint32_t BOOT_START = 1; - static const uint32_t BOOT_COMPLETE = 2; - static const uint32_t SHUTDOWN_START = 3; - } - - namespace GPIO { - static const uint32_t BASE = 2000; - static const uint32_t INIT_SUCCESS = BASE + 1; - static const uint32_t CONFIG_ERROR = BASE + 601; - } - - namespace UART { - static const uint32_t BASE = 3000; - static const uint32_t PORT_OPENED = BASE + 1; - static const uint32_t TRANSMISSION_ERROR = BASE + 601; - } - - namespace WiFi { - static const uint32_t BASE = 4000; - static const uint32_t CONNECTED = BASE + 1; - static const uint32_t CONNECTION_FAILED = BASE + 601; - } -} -``` - -## Integration Examples - -### GPIO Wrapper Integration - -```cpp -// gpio_wrapper.cpp -#include "logger.hpp" -#include "global_log_ids.hpp" - -static const char* TAG = "GPIO_WRAPPER"; - -class Gpio { -public: - bool configure(uint32_t pin, GpioMode mode) { - ASF_LOGI(TAG, GlobalLogIds::GPIO::INIT_SUCCESS, - "Configuring GPIO pin %lu as %s", pin, getModeString(mode)); - - if (!isValidPin(pin)) { - ASF_LOGE(TAG, GlobalLogIds::GPIO::CONFIG_ERROR, - "Invalid GPIO pin number: %lu", pin); - return false; - } - - // ESP-IDF configuration code... - esp_err_t ret = gpio_config(&config); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GlobalLogIds::GPIO::CONFIG_ERROR, - "GPIO configuration failed: %s", esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, GlobalLogIds::GPIO::INIT_SUCCESS, - "GPIO pin %lu configured successfully", pin); - return true; - } - - bool setLevel(uint32_t pin, uint32_t level) { - ASF_LOGD(TAG, GlobalLogIds::GPIO::BASE + 201, - "Setting GPIO pin %lu to level %lu", pin, level); - - // Implementation... - - return true; - } -}; -``` - -### UART Wrapper Integration - -```cpp -// uart_wrapper.cpp -#include "logger.hpp" -#include "global_log_ids.hpp" - -static const char* TAG = "UART_WRAPPER"; - -class Uart { -public: - bool initialize(UartPort port, const UartConfig& config) { - ASF_LOGI(TAG, GlobalLogIds::UART::PORT_OPENED, - "Initializing UART port %d with baudrate %d", - static_cast(port), static_cast(config.baudrate)); - - // Configuration and error handling with logging... - - return true; - } - - int32_t transmit(UartPort port, const uint8_t* data, size_t length) { - ASF_LOGD(TAG, GlobalLogIds::UART::BASE + 201, - "Transmitting %zu bytes on UART port %d", - length, static_cast(port)); - - // Transmission logic with error logging... - - return length; - } -}; -``` - -### Application-Level Integration - -```cpp -// main.cpp -#include "logger.hpp" -#include "global_log_ids.hpp" - -static const char* TAG = "MAIN"; - -void app_main() { - // Initialize logger first - setupLogger(); - - ASF_LOGI(TAG, GlobalLogIds::System::BOOT_START, "System boot started"); - - // Initialize components - if (!initializeGPIO()) { - ASF_LOGE(TAG, 1001, "GPIO initialization failed"); - return; - } - - if (!initializeUART()) { - ASF_LOGE(TAG, 1002, "UART initialization failed"); - return; - } - - if (!initializeWiFi()) { - ASF_LOGE(TAG, 1003, "WiFi initialization failed"); - return; - } - - ASF_LOGI(TAG, GlobalLogIds::System::BOOT_COMPLETE, "System boot completed successfully"); - - // Main application loop - while (true) { - runApplicationTasks(); - vTaskDelay(pdMS_TO_TICKS(100)); - } -} - -void setupLogger() { - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - - #ifdef DEBUG_BUILD - config.minLevel = asf::logger::LogLevel::DEBUG; - config.enableColor = true; - #else - config.minLevel = asf::logger::LogLevel::INFO; - config.enableColor = false; - #endif - - asf::logger::initialize(config); -} -``` - -## Best Practices - -### 1. Consistent Tagging - -```cpp -// Good: Use consistent, descriptive tags -static const char* TAG = "SENSOR_MGR"; -static const char* TAG = "WIFI_CTRL"; -static const char* TAG = "DATA_PROC"; - -// Avoid: Inconsistent or unclear tags -static const char* TAG = "S1"; -static const char* TAG = "Module"; -static const char* TAG = "temp"; -``` - -### 2. Meaningful Message IDs - -```cpp -// Good: Structured ID allocation -namespace SensorLogIds { - static const uint32_t SENSOR_INIT_SUCCESS = 5001; - static const uint32_t SENSOR_READ_COMPLETE = 5002; - static const uint32_t SENSOR_CALIBRATION_ERROR = 5601; -} - -// Avoid: Random or unclear IDs -ASF_LOGI(TAG, 42, "Something happened"); -ASF_LOGE(TAG, 999999, "Error occurred"); -``` - -### 3. Appropriate Log Levels - -```cpp -// Good: Use appropriate levels -ASF_LOGV(TAG, 1001, "Entering function processData()"); // Verbose -ASF_LOGD(TAG, 1002, "Processing %d items", itemCount); // Debug -ASF_LOGI(TAG, 1003, "Data processing completed successfully"); // Info -ASF_LOGW(TAG, 1004, "Queue is 80%% full, consider optimization"); // Warning -ASF_LOGE(TAG, 1005, "Critical: Database connection lost"); // Error - -// Avoid: Wrong levels -ASF_LOGE(TAG, 1001, "Function started"); // Error level for normal operation -ASF_LOGI(TAG, 1002, "CRITICAL FAILURE"); // Info level for critical error -``` - -### 4. Performance-Conscious Logging - -```cpp -// Good: Check level before expensive operations -if (asf::logger::getLogLevel() <= asf::logger::LogLevel::DEBUG) { - char debugBuffer[256]; - formatComplexDebugInfo(debugBuffer, sizeof(debugBuffer)); - ASF_LOGD(TAG, 1001, "Debug info: %s", debugBuffer); -} - -// Good: Use appropriate data types -ASF_LOGI(TAG, 1002, "Processing item %lu of %lu", currentItem, totalItems); - -// Avoid: Expensive operations in log calls -ASF_LOGD(TAG, 1003, "Debug: %s", expensiveStringOperation().c_str()); -``` - -### 5. Error Context - -```cpp -// Good: Provide context with errors -esp_err_t ret = gpio_config(&config); -if (ret != ESP_OK) { - ASF_LOGE(TAG, 2001, "GPIO configuration failed for pin %lu: %s", - pin, esp_err_to_name(ret)); - return false; -} - -// Good: Include relevant state information -ASF_LOGW(TAG, 2002, "Retry attempt %d/%d failed, retrying in %d ms", - currentAttempt, maxAttempts, retryDelay); -``` - -## Troubleshooting - -### Common Issues - -#### 1. No Log Output - -**Problem**: Logger initialized but no messages appear. - -**Solutions**: -```cpp -// Check log level -asf::logger::LogLevel currentLevel = asf::logger::getLogLevel(); -ASF_LOGI("DEBUG", 9001, "Current log level: %s", - asf::logger::logLevelToString(currentLevel)); - -// Ensure level is appropriate -asf::logger::setLogLevel(asf::logger::LogLevel::VERBOSE); - -// Test with error level (always visible) -ASF_LOGE("TEST", 9002, "Test error message"); -``` - -#### 2. Truncated Messages - -**Problem**: Long messages are cut off. - -**Solutions**: -```cpp -// Increase buffer size -asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); -config.maxMessageLength = 512; // Increase from default 256 -asf::logger::initialize(config); - -// Or split long messages -ASF_LOGI(TAG, 1001, "Long message part 1: %s", part1); -ASF_LOGI(TAG, 1002, "Long message part 2: %s", part2); -``` - -#### 3. Performance Issues - -**Problem**: Logging is slowing down the application. - -**Solutions**: -```cpp -// Increase minimum log level for production -asf::logger::setLogLevel(asf::logger::LogLevel::WARNING); - -// Use conditional logging for debug -#ifdef DEBUG_BUILD - ASF_LOGD(TAG, 1001, "Debug information: %d", value); -#endif - -// Check level before expensive formatting -if (asf::logger::getLogLevel() <= asf::logger::LogLevel::DEBUG) { - ASF_LOGD(TAG, 1002, "Expensive debug: %s", formatExpensiveData()); -} -``` - -#### 4. Memory Issues - -**Problem**: Stack overflow or memory corruption. - -**Solutions**: -```cpp -// Reduce buffer size -asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); -config.maxMessageLength = 128; // Reduce buffer size -asf::logger::initialize(config); - -// Avoid very long format strings -// Bad: -ASF_LOGI(TAG, 1001, "Very long format string with many parameters %d %d %d %d %d %d %d %d", - a, b, c, d, e, f, g, h); - -// Good: -ASF_LOGI(TAG, 1001, "Parameters: a=%d, b=%d", a, b); -ASF_LOGI(TAG, 1002, "More parameters: c=%d, d=%d", c, d); -``` - -### Debug Mode - -```cpp -void enableDebugMode() { - // Enable all logging - asf::logger::setLogLevel(asf::logger::LogLevel::VERBOSE); - - // Enable all features - asf::logger::enableTimestamp(true); - asf::logger::enableColor(true); - asf::logger::enableId(true); - - ASF_LOGI("DEBUG", 9999, "Debug mode enabled - all logging active"); -} -``` - -## Migration Guide - -### From ESP-IDF Logging - -#### Step 1: Replace Headers -```cpp -// Remove ESP-IDF log includes (if standalone) -// #include "esp_log.h" - -// Add ASF logger -#include "logger.hpp" -``` - -#### Step 2: Initialize Logger -```cpp -void app_main() { - // Add logger initialization - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - asf::logger::initialize(config); - - // Existing code... -} -``` - -#### Step 3: Replace Log Calls -```cpp -// Before (ESP-IDF) -static const char* TAG = "MY_MODULE"; -ESP_LOGI(TAG, "Module initialized"); -ESP_LOGW(TAG, "Warning: %s", warningMsg); -ESP_LOGE(TAG, "Error code: %d", errorCode); - -// After (ASF Logger) -static const char* TAG = "MY_MODULE"; -ASF_LOGI(TAG, 1001, "Module initialized"); -ASF_LOGW(TAG, 1002, "Warning: %s", warningMsg); -ASF_LOGE(TAG, 1003, "Error code: %d", errorCode); -``` - -#### Step 4: Add Message IDs -```cpp -// Create ID definitions -namespace MyModuleIds { - static const uint32_t INIT_SUCCESS = 1001; - static const uint32_t WARNING_OCCURRED = 1002; - static const uint32_t ERROR_CODE = 1003; -} - -// Use in logging -ASF_LOGI(TAG, MyModuleIds::INIT_SUCCESS, "Module initialized"); -ASF_LOGW(TAG, MyModuleIds::WARNING_OCCURRED, "Warning: %s", warningMsg); -ASF_LOGE(TAG, MyModuleIds::ERROR_CODE, "Error code: %d", errorCode); -``` - -### Gradual Migration Strategy - -```cpp -// Phase 1: Dual logging (for testing) -#define DUAL_LOG_INFO(tag, id, format, ...) do { \ - ESP_LOGI(tag, format, ##__VA_ARGS__); \ - ASF_LOGI(tag, id, format, ##__VA_ARGS__); \ -} while(0) - -// Phase 2: Switch to ASF only -#define DUAL_LOG_INFO(tag, id, format, ...) \ - ASF_LOGI(tag, id, format, ##__VA_ARGS__) - -// Phase 3: Remove dual logging, use ASF directly -// ASF_LOGI(tag, id, format, ...) -``` - -This comprehensive usage guide provides practical examples and best practices for integrating and using the ASF Logger in your ESP-IDF projects. The structured approach to message IDs and consistent logging patterns will help maintain clean, traceable logs throughout your application. \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/com/logger.cpp b/draft- to be removed SW/components/utils/logger/com/logger.cpp deleted file mode 100644 index fb6ba39..0000000 --- a/draft- to be removed SW/components/utils/logger/com/logger.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/** - * @file logger.cpp - * @brief ASF Logger - Implementation of ESP-IDF logging wrapper - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "logger.hpp" -#include -#include -#include -#include - -namespace asf { -namespace logger { - -// Static configuration -static LoggerConfig s_config = { - .minLevel = LogLevel::INFO, - .enableTimestamp = true, - .enableColor = true, - .enableId = true, - .maxMessageLength = 256, - .filePath = nullptr -}; - -// Color codes for different log levels -static const char* COLOR_RESET = "\033[0m"; -static const char* COLOR_VERBOSE = "\033[37m"; // White -static const char* COLOR_DEBUG = "\033[36m"; // Cyan -static const char* COLOR_INFO = "\033[32m"; // Green -static const char* COLOR_WARNING = "\033[33m"; // Yellow -static const char* COLOR_ERROR = "\033[31m"; // Red - -void initialize(const LoggerConfig& config) -{ - s_config = config; - - // Set ESP-IDF log level based on our minimum level - esp_log_level_t espLevel = ESP_LOG_NONE; - switch (config.minLevel) { - case LogLevel::VERBOSE: - espLevel = ESP_LOG_VERBOSE; - break; - case LogLevel::DEBUG: - espLevel = ESP_LOG_DEBUG; - break; - case LogLevel::INFO: - espLevel = ESP_LOG_INFO; - break; - case LogLevel::WARNING: - espLevel = ESP_LOG_WARN; - break; - case LogLevel::ERROR: - espLevel = ESP_LOG_ERROR; - break; - case LogLevel::NONE: - espLevel = ESP_LOG_NONE; - break; - } - - esp_log_level_set("*", espLevel); -} - -void setLogLevel(LogLevel level) -{ - s_config.minLevel = level; - - // Update ESP-IDF log level - LoggerConfig tempConfig = s_config; - tempConfig.minLevel = level; - initialize(tempConfig); -} - -LogLevel getLogLevel() -{ - return s_config.minLevel; -} - -void enableTimestamp(bool enable) -{ - s_config.enableTimestamp = enable; -} - -void enableColor(bool enable) -{ - s_config.enableColor = enable; -} - -void enableId(bool enable) -{ - s_config.enableId = enable; -} - -void enableFileLogging(const char* filePath) -{ - s_config.filePath = filePath; -} - -const char* getIsoTimestamp(char* buffer, size_t bufferSize) -{ - if (buffer == nullptr || bufferSize < 24) { - return ""; - } - - // Get current time with microseconds - struct timeval tv; - gettimeofday(&tv, nullptr); - - struct tm* timeinfo = localtime(&tv.tv_sec); - - // Format: YYYY-MM-DDTHH:MM:SS.sssZ - snprintf(buffer, bufferSize, "%04d-%02d-%02dT%02d:%02d:%02d.%03ldZ", - timeinfo->tm_year + 1900, - timeinfo->tm_mon + 1, - timeinfo->tm_mday, - timeinfo->tm_hour, - timeinfo->tm_min, - timeinfo->tm_sec, - tv.tv_usec / 1000); - - return buffer; -} - -void log(const char* tag, uint32_t id, LogLevel level, Criticality criticality, const char* format, ...) -{ - // Check if we should log this level - if (level < s_config.minLevel) { - return; - } - - if (tag == nullptr || format == nullptr) { - return; - } - - // Prepare message buffer - char messageBuffer[s_config.maxMessageLength]; - - // Format the user message - va_list args; - va_start(args, format); - vsnprintf(messageBuffer, sizeof(messageBuffer), format, args); - va_end(args); - - // Prepare final output buffer - char outputBuffer[s_config.maxMessageLength + 128]; // Extra space for timestamp, tag, etc. - char timestampBuffer[32]; - - // Build the formatted log message - const char* colorStart = s_config.enableColor ? logLevelToColor(level) : ""; - const char* colorEnd = s_config.enableColor ? COLOR_RESET : ""; - const char* timestamp = s_config.enableTimestamp ? getIsoTimestamp(timestampBuffer, sizeof(timestampBuffer)) : ""; - const char* levelStr = logLevelToString(level); - const char* critStr = criticalityToString(criticality); - - if (s_config.enableTimestamp && s_config.enableId) { - snprintf(outputBuffer, sizeof(outputBuffer), "%s%s : %s[%s][%s] : %lu : %s%s", - colorStart, timestamp, tag, levelStr, critStr, id, messageBuffer, colorEnd); - } else if (s_config.enableTimestamp && !s_config.enableId) { - snprintf(outputBuffer, sizeof(outputBuffer), "%s%s : %s[%s][%s] : %s%s", - colorStart, timestamp, tag, levelStr, critStr, messageBuffer, colorEnd); - } else if (!s_config.enableTimestamp && s_config.enableId) { - snprintf(outputBuffer, sizeof(outputBuffer), "%s%s[%s][%s] : %lu : %s%s", - colorStart, tag, levelStr, critStr, id, messageBuffer, colorEnd); - } else { - snprintf(outputBuffer, sizeof(outputBuffer), "%s%s[%s][%s] : %s%s", - colorStart, tag, levelStr, critStr, messageBuffer, colorEnd); - } - - // Output using ESP-IDF logging system - switch (level) { - case LogLevel::VERBOSE: - ESP_LOGV("ASF", "%s", outputBuffer); - break; - case LogLevel::DEBUG: - ESP_LOGD("ASF", "%s", outputBuffer); - break; - case LogLevel::INFO: - ESP_LOGI("ASF", "%s", outputBuffer); - break; - case LogLevel::WARNING: - ESP_LOGW("ASF", "%s", outputBuffer); - break; - case LogLevel::ERROR: - ESP_LOGE("ASF", "%s", outputBuffer); - break; - case LogLevel::NONE: - break; - } - - // Write to file if enabled - if (s_config.filePath != nullptr) { - FILE* f = fopen(s_config.filePath, "a"); - if (f != nullptr) { - // Re-format without color codes for file output - char fileBuffer[s_config.maxMessageLength + 128]; - if (s_config.enableTimestamp && s_config.enableId) { - snprintf(fileBuffer, sizeof(fileBuffer), "%s : %s[%s][%s] : %lu : %s\n", - timestamp, tag, levelStr, critStr, id, messageBuffer); - } else if (s_config.enableTimestamp && !s_config.enableId) { - snprintf(fileBuffer, sizeof(fileBuffer), "%s : %s[%s][%s] : %s\n", - timestamp, tag, levelStr, critStr, messageBuffer); - } else if (!s_config.enableTimestamp && s_config.enableId) { - snprintf(fileBuffer, sizeof(fileBuffer), "%s[%s][%s] : %lu : %s\n", - tag, levelStr, critStr, id, messageBuffer); - } else { - snprintf(fileBuffer, sizeof(fileBuffer), "%s[%s][%s] : %s\n", - tag, levelStr, critStr, messageBuffer); - } - fprintf(f, "%s", fileBuffer); - fclose(f); - } - } -} - -void logVerbose(const char* tag, uint32_t id, Criticality criticality, const char* format, ...) -{ - if (LogLevel::VERBOSE < s_config.minLevel) { - return; - } - - va_list args; - va_start(args, format); - - char messageBuffer[s_config.maxMessageLength]; - vsnprintf(messageBuffer, sizeof(messageBuffer), format, args); - va_end(args); - - log(tag, id, LogLevel::VERBOSE, criticality, "%s", messageBuffer); -} - -void logDebug(const char* tag, uint32_t id, Criticality criticality, const char* format, ...) -{ - if (LogLevel::DEBUG < s_config.minLevel) { - return; - } - - va_list args; - va_start(args, format); - - char messageBuffer[s_config.maxMessageLength]; - vsnprintf(messageBuffer, sizeof(messageBuffer), format, args); - va_end(args); - - log(tag, id, LogLevel::DEBUG, criticality, "%s", messageBuffer); -} - -void logInfo(const char* tag, uint32_t id, Criticality criticality, const char* format, ...) -{ - if (LogLevel::INFO < s_config.minLevel) { - return; - } - - va_list args; - va_start(args, format); - - char messageBuffer[s_config.maxMessageLength]; - vsnprintf(messageBuffer, sizeof(messageBuffer), format, args); - va_end(args); - - log(tag, id, LogLevel::INFO, criticality, "%s", messageBuffer); -} - -void logWarning(const char* tag, uint32_t id, Criticality criticality, const char* format, ...) -{ - if (LogLevel::WARNING < s_config.minLevel) { - return; - } - - va_list args; - va_start(args, format); - - char messageBuffer[s_config.maxMessageLength]; - vsnprintf(messageBuffer, sizeof(messageBuffer), format, args); - va_end(args); - - log(tag, id, LogLevel::WARNING, criticality, "%s", messageBuffer); -} - -void logError(const char* tag, uint32_t id, Criticality criticality, const char* format, ...) -{ - if (LogLevel::ERROR < s_config.minLevel) { - return; - } - - va_list args; - va_start(args, format); - - char messageBuffer[s_config.maxMessageLength]; - vsnprintf(messageBuffer, sizeof(messageBuffer), format, args); - va_end(args); - - log(tag, id, LogLevel::ERROR, criticality, "%s", messageBuffer); -} - -LoggerConfig getDefaultConfig() -{ - LoggerConfig config = {}; - config.minLevel = LogLevel::INFO; - config.enableTimestamp = true; - config.enableColor = true; - config.enableId = true; - config.maxMessageLength = 256; - config.filePath = nullptr; - return config; -} - -const char* logLevelToString(LogLevel level) -{ - switch (level) { - case LogLevel::VERBOSE: - return "VERBOSE"; - case LogLevel::DEBUG: - return "DEBUG"; - case LogLevel::INFO: - return "INFO"; - case LogLevel::WARNING: - return "WARNING"; - case LogLevel::ERROR: - return "ERROR"; - case LogLevel::NONE: - return "NONE"; - default: - return "UNKNOWN"; - } -} - -const char* logLevelToColor(LogLevel level) -{ - switch (level) { - case LogLevel::VERBOSE: - return COLOR_VERBOSE; - case LogLevel::DEBUG: - return COLOR_DEBUG; - case LogLevel::INFO: - return COLOR_INFO; - case LogLevel::WARNING: - return COLOR_WARNING; - case LogLevel::ERROR: - return COLOR_ERROR; - case LogLevel::NONE: - return COLOR_RESET; - default: - return COLOR_RESET; - } -} - -const char* criticalityToString(Criticality criticality) -{ - switch (criticality) { - case Criticality::LOW: - return "LOW"; - case Criticality::MEDIUM: - return "MEDIUM"; - case Criticality::HIGH: - return "HIGH"; - case Criticality::VERY_HIGH: - return "VERY_HIGH"; - default: - return "UNKNOWN"; - } -} - -} // namespace logger -} // namespace asf \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/com/logger.hpp b/draft- to be removed SW/components/utils/logger/com/logger.hpp deleted file mode 100644 index dd2836f..0000000 --- a/draft- to be removed SW/components/utils/logger/com/logger.hpp +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @file logger.hpp - * @brief ASF Logger - Wrapper for ESP-IDF logging functionality - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - * - * @details - * Abstract logger class for the application and device driver layers - * - Does not depend directly on the low-level logging mechanism provided by platform - * - Supports logging levels (info, warn, debug, error, verbose) - * - Formats messages with ISO timestamp, TAG, level, and unique ID - * - Low overhead design for minimal performance impact - * - Easily included in all modules without compile/linking errors - * - Efficient in compilation time and flash space - * - * Design: Namespace with free functions for simplicity and zero overhead - */ - -#ifndef LOGGER_HPP -#define LOGGER_HPP - -#include -#include -#include "esp_log.h" -#include "esp_timer.h" - -/** - * @brief Logger namespace containing all logging functionality - */ -namespace asf { -namespace logger { - -/** - * @brief Log level enumeration - */ -enum class LogLevel : uint8_t -{ - VERBOSE = 0, ///< Verbose level (most detailed) - DEBUG = 1, ///< Debug level - INFO = 2, ///< Information level - WARNING = 3, ///< Warning level - ERROR = 4, ///< Error level - NONE = 5 ///< No logging -}; - -/** - * @brief Log criticality enumeration - */ -enum class Criticality : uint8_t -{ - LOW, ///< Low criticality - MEDIUM, ///< Medium criticality - HIGH, ///< High criticality - VERY_HIGH ///< Very high criticality -}; - -/** - * @brief Logger configuration structure - */ -struct LoggerConfig -{ - LogLevel minLevel; ///< Minimum log level to display - bool enableTimestamp; ///< Enable ISO timestamp in output - bool enableColor; ///< Enable color output - bool enableId; ///< Enable unique ID in output - uint32_t maxMessageLength; ///< Maximum message length - const char* filePath; ///< Path to log file (nullptr to disable file logging) -}; - -/** - * @brief Initialize the logger with configuration - * @param config Logger configuration - */ -void initialize(const LoggerConfig& config); - -/** - * @brief Set minimum log level - * @param level Minimum log level to display - */ -void setLogLevel(LogLevel level); - -/** - * @brief Get current minimum log level - * @return Current minimum log level - */ -LogLevel getLogLevel(); - -/** - * @brief Enable or disable timestamp in log output - * @param enable True to enable, false to disable - */ -void enableTimestamp(bool enable); - -/** - * @brief Enable or disable color in log output - * @param enable True to enable, false to disable - */ -void enableColor(bool enable); - -/** - * @brief Enable or disable ID in log output - * @param enable True to enable, false to disable - */ -void enableId(bool enable); - -/** - * @brief Enable file logging - * @param filePath Path to the log file (e.g., "/ESP/log.txt") - */ -void enableFileLogging(const char* filePath); - -/** - * @brief Get ISO 8601 formatted timestamp - * @param buffer Buffer to store timestamp - * @param bufferSize Size of buffer - * @return Pointer to buffer - */ -const char* getIsoTimestamp(char* buffer, size_t bufferSize); - -/** - * @brief Main logging function - * @param tag Log tag (module name) - * @param id Unique message ID - * @param level Log level - * @param criticality Message criticality - * @param format Printf-style format string - * @param ... Variable arguments - */ -void log(const char* tag, uint32_t id, LogLevel level, Criticality criticality, const char* format, ...); - -/** - * @brief Log verbose message - * @param tag Log tag (module name) - * @param id Unique message ID - * @param criticality Message criticality - * @param format Printf-style format string - * @param ... Variable arguments - */ -void logVerbose(const char* tag, uint32_t id, Criticality criticality, const char* format, ...); - -/** - * @brief Log debug message - * @param tag Log tag (module name) - * @param id Unique message ID - * @param criticality Message criticality - * @param format Printf-style format string - * @param ... Variable arguments - */ -void logDebug(const char* tag, uint32_t id, Criticality criticality, const char* format, ...); - -/** - * @brief Log info message - * @param tag Log tag (module name) - * @param id Unique message ID - * @param criticality Message criticality - * @param format Printf-style format string - * @param ... Variable arguments - */ -void logInfo(const char* tag, uint32_t id, Criticality criticality, const char* format, ...); - -/** - * @brief Log warning message - * @param tag Log tag (module name) - * @param id Unique message ID - * @param criticality Message criticality - * @param format Printf-style format string - * @param ... Variable arguments - */ -void logWarning(const char* tag, uint32_t id, Criticality criticality, const char* format, ...); - -/** - * @brief Log error message - * @param tag Log tag (module name) - * @param id Unique message ID - * @param criticality Message criticality - * @param format Printf-style format string - * @param ... Variable arguments - */ -void logError(const char* tag, uint32_t id, Criticality criticality, const char* format, ...); - -/** - * @brief Get default logger configuration - * @return Default logger configuration - */ -LoggerConfig getDefaultConfig(); - -/** - * @brief Convert log level to string - * @param level Log level - * @return String representation of log level - */ -const char* logLevelToString(LogLevel level); - -/** - * @brief Convert log level to color code - * @param level Log level - * @return ANSI color code string - */ -const char* logLevelToColor(LogLevel level); - -/** - * @brief Convert criticality to string - * @param criticality Message criticality - * @return String representation of criticality - */ -const char* criticalityToString(Criticality criticality); - -} // namespace logger -} // namespace asf - -// Convenience macros for easier usage -#define ASF_LOG_VERBOSE(tag, id, crit, format, ...) asf::logger::logVerbose(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOG_DEBUG(tag, id, crit, format, ...) asf::logger::logDebug(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOG_INFO(tag, id, crit, format, ...) asf::logger::logInfo(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOG_WARNING(tag, id, crit, format, ...) asf::logger::logWarning(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOG_ERROR(tag, id, crit, format, ...) asf::logger::logError(tag, id, crit, format, ##__VA_ARGS__) - -// Short form macros -#define ASF_LOGV(tag, id, crit, format, ...) ASF_LOG_VERBOSE(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOGD(tag, id, crit, format, ...) ASF_LOG_DEBUG(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOGI(tag, id, crit, format, ...) ASF_LOG_INFO(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOGW(tag, id, crit, format, ...) ASF_LOG_WARNING(tag, id, crit, format, ##__VA_ARGS__) -#define ASF_LOGE(tag, id, crit, format, ...) ASF_LOG_ERROR(tag, id, crit, format, ##__VA_ARGS__) - -#endif // LOGGER_HPP \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/example/gpio_wrapper_example.cpp b/draft- to be removed SW/components/utils/logger/example/gpio_wrapper_example.cpp deleted file mode 100644 index 296819c..0000000 --- a/draft- to be removed SW/components/utils/logger/example/gpio_wrapper_example.cpp +++ /dev/null @@ -1,355 +0,0 @@ -/** - * @file gpio_wrapper_example.cpp - * @brief Example of integrating ASF Logger with GPIO wrapper - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "logger.hpp" -#include "gpio.hpp" - -// Module-specific log tag and IDs -static const char* TAG = "GPIO_WRAPPER"; - -namespace GpioLogIds { - // Info messages (2001-2199) - static const uint32_t WRAPPER_INIT = 2001; - static const uint32_t WRAPPER_DESTROY = 2002; - static const uint32_t PIN_CONFIGURED = 2003; - static const uint32_t ISR_INSTALLED = 2004; - static const uint32_t INTERRUPT_ATTACHED = 2005; - static const uint32_t INTERRUPT_DETACHED = 2006; - - // Debug messages (2201-2399) - static const uint32_t PIN_LEVEL_SET = 2201; - static const uint32_t PIN_LEVEL_READ = 2202; - static const uint32_t PIN_TOGGLED = 2203; - - // Warning messages (2401-2599) - static const uint32_t ISR_ALREADY_INSTALLED = 2401; - static const uint32_t PORT_NOT_INITIALIZED = 2402; - - // Error messages (2601-2799) - static const uint32_t INVALID_PIN = 2601; - static const uint32_t CONFIG_FAILED = 2602; - static const uint32_t SET_LEVEL_FAILED = 2603; - static const uint32_t ISR_INSTALL_FAILED = 2604; - static const uint32_t INTERRUPT_ATTACH_FAILED = 2605; - static const uint32_t INTERRUPT_DETACH_FAILED = 2606; -} - -/** - * @brief Example GPIO wrapper with ASF Logger integration - */ -class GpioWithLogger -{ -public: - GpioWithLogger() : m_isrInstalled_(false) - { - ASF_LOGI(TAG, GpioLogIds::WRAPPER_INIT, "GPIO wrapper initialized"); - } - - ~GpioWithLogger() - { - if (m_isrInstalled_) { - uninstallIsr(); - } - ASF_LOGI(TAG, GpioLogIds::WRAPPER_DESTROY, "GPIO wrapper destroyed"); - } - - bool configure(uint32_t pin, GpioMode mode) - { - ASF_LOGI(TAG, GpioLogIds::PIN_CONFIGURED, "Configuring GPIO pin %lu", pin); - - if (!isValidPin(pin)) { - ASF_LOGE(TAG, GpioLogIds::INVALID_PIN, "Invalid GPIO pin: %lu", pin); - return false; - } - - gpio_config_t config = {}; - config.pin_bit_mask = (1ULL << pin); - config.mode = convertMode(mode); - config.intr_type = GPIO_INTR_DISABLE; - - // Configure pull-up/down based on mode - switch (mode) { - case GpioMode::INPUT_PULLUP: - config.pull_up_en = GPIO_PULLUP_ENABLE; - config.pull_down_en = GPIO_PULLDOWN_DISABLE; - ASF_LOGD(TAG, GpioLogIds::PIN_CONFIGURED, "Pin %lu configured with pull-up", pin); - break; - case GpioMode::INPUT_PULLDOWN: - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_ENABLE; - ASF_LOGD(TAG, GpioLogIds::PIN_CONFIGURED, "Pin %lu configured with pull-down", pin); - break; - default: - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_DISABLE; - ASF_LOGD(TAG, GpioLogIds::PIN_CONFIGURED, "Pin %lu configured without pull resistors", pin); - break; - } - - esp_err_t ret = gpio_config(&config); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GpioLogIds::CONFIG_FAILED, "Failed to configure GPIO pin %lu: %s", - pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, GpioLogIds::PIN_CONFIGURED, "GPIO pin %lu configured successfully", pin); - return true; - } - - bool setLevel(uint32_t pin, uint32_t level) - { - if (!isValidPin(pin)) { - ASF_LOGE(TAG, GpioLogIds::INVALID_PIN, "Invalid GPIO pin: %lu", pin); - return false; - } - - esp_err_t ret = gpio_set_level(static_cast(pin), level); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GpioLogIds::SET_LEVEL_FAILED, "Failed to set GPIO pin %lu level: %s", - pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGD(TAG, GpioLogIds::PIN_LEVEL_SET, "GPIO pin %lu set to level %lu", pin, level); - return true; - } - - int32_t getLevel(uint32_t pin) - { - if (!isValidPin(pin)) { - ASF_LOGE(TAG, GpioLogIds::INVALID_PIN, "Invalid GPIO pin: %lu", pin); - return -1; - } - - int level = gpio_get_level(static_cast(pin)); - ASF_LOGD(TAG, GpioLogIds::PIN_LEVEL_READ, "GPIO pin %lu level read: %d", pin, level); - return level; - } - - bool toggleLevel(uint32_t pin) - { - int32_t currentLevel = getLevel(pin); - if (currentLevel < 0) { - return false; - } - - bool result = setLevel(pin, currentLevel == 0 ? 1 : 0); - if (result) { - ASF_LOGD(TAG, GpioLogIds::PIN_TOGGLED, "GPIO pin %lu toggled from %ld to %d", - pin, currentLevel, currentLevel == 0 ? 1 : 0); - } - return result; - } - - bool installIsr(int flags = 0) - { - if (m_isrInstalled_) { - ASF_LOGW(TAG, GpioLogIds::ISR_ALREADY_INSTALLED, "GPIO ISR already installed"); - return true; - } - - esp_err_t ret = gpio_install_isr_service(flags); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GpioLogIds::ISR_INSTALL_FAILED, "Failed to install GPIO ISR service: %s", - esp_err_to_name(ret)); - return false; - } - - m_isrInstalled_ = true; - ASF_LOGI(TAG, GpioLogIds::ISR_INSTALLED, "GPIO ISR service installed successfully"); - return true; - } - - bool uninstallIsr() - { - if (!m_isrInstalled_) { - ASF_LOGW(TAG, GpioLogIds::PORT_NOT_INITIALIZED, "GPIO ISR not installed"); - return true; - } - - gpio_uninstall_isr_service(); - m_isrInstalled_ = false; - ASF_LOGI(TAG, GpioLogIds::ISR_INSTALLED, "GPIO ISR service uninstalled"); - return true; - } - - bool attachInterrupt(uint32_t pin, GpioIntType intType, GpioCallback callback, void* arg) - { - if (!isValidPin(pin)) { - ASF_LOGE(TAG, GpioLogIds::INVALID_PIN, "Invalid GPIO pin: %lu", pin); - return false; - } - - if (!m_isrInstalled_) { - ASF_LOGW(TAG, GpioLogIds::PORT_NOT_INITIALIZED, "GPIO ISR not installed, installing now"); - if (!installIsr()) { - return false; - } - } - - // Set interrupt type - esp_err_t ret = gpio_set_intr_type(static_cast(pin), convertIntType(intType)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GpioLogIds::INTERRUPT_ATTACH_FAILED, - "Failed to set interrupt type for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - // Add ISR handler - ret = gpio_isr_handler_add(static_cast(pin), - reinterpret_cast(callback), arg); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GpioLogIds::INTERRUPT_ATTACH_FAILED, - "Failed to add ISR handler for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, GpioLogIds::INTERRUPT_ATTACHED, "Interrupt attached to GPIO pin %lu", pin); - return true; - } - - bool detachInterrupt(uint32_t pin) - { - if (!isValidPin(pin)) { - ASF_LOGE(TAG, GpioLogIds::INVALID_PIN, "Invalid GPIO pin: %lu", pin); - return false; - } - - // Disable interrupt - esp_err_t ret = gpio_set_intr_type(static_cast(pin), GPIO_INTR_DISABLE); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GpioLogIds::INTERRUPT_DETACH_FAILED, - "Failed to disable interrupt for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - // Remove ISR handler - ret = gpio_isr_handler_remove(static_cast(pin)); - if (ret != ESP_OK) { - ASF_LOGE(TAG, GpioLogIds::INTERRUPT_DETACH_FAILED, - "Failed to remove ISR handler for pin %lu: %s", pin, esp_err_to_name(ret)); - return false; - } - - ASF_LOGI(TAG, GpioLogIds::INTERRUPT_DETACHED, "Interrupt detached from GPIO pin %lu", pin); - return true; - } - - static bool isValidPin(uint32_t pin) - { - return GPIO_IS_VALID_GPIO(pin); - } - -private: - bool m_isrInstalled_; - - gpio_mode_t convertMode(GpioMode mode) - { - switch (mode) { - case GpioMode::INPUT: - case GpioMode::INPUT_PULLUP: - case GpioMode::INPUT_PULLDOWN: - return GPIO_MODE_INPUT; - case GpioMode::OUTPUT: - return GPIO_MODE_OUTPUT; - case GpioMode::OUTPUT_OD: - return GPIO_MODE_OUTPUT_OD; - default: - return GPIO_MODE_INPUT; - } - } - - gpio_int_type_t convertIntType(GpioIntType intType) - { - switch (intType) { - case GpioIntType::DISABLE: - return GPIO_INTR_DISABLE; - case GpioIntType::RISING_EDGE: - return GPIO_INTR_POSEDGE; - case GpioIntType::FALLING_EDGE: - return GPIO_INTR_NEGEDGE; - case GpioIntType::ANY_EDGE: - return GPIO_INTR_ANYEDGE; - case GpioIntType::LOW_LEVEL: - return GPIO_INTR_LOW_LEVEL; - case GpioIntType::HIGH_LEVEL: - return GPIO_INTR_HIGH_LEVEL; - default: - return GPIO_INTR_DISABLE; - } - } -}; - -/** - * @brief Example usage of GPIO wrapper with ASF Logger - */ -void exampleUsage() -{ - // Initialize ASF Logger - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - config.minLevel = asf::logger::LogLevel::DEBUG; // Enable debug messages - asf::logger::initialize(config); - - ASF_LOGI("MAIN", 1001, "Starting GPIO wrapper example"); - - // Create GPIO instance - GpioWithLogger gpio; - - // Configure GPIO pin as output - if (gpio.configure(2, GpioMode::OUTPUT)) { - ASF_LOGI("MAIN", 1002, "GPIO pin 2 configured as output"); - - // Set pin high - gpio.setLevel(2, 1); - - // Toggle pin - gpio.toggleLevel(2); - } else { - ASF_LOGE("MAIN", 1003, "Failed to configure GPIO pin 2"); - } - - // Configure GPIO pin as input with pull-up - if (gpio.configure(4, GpioMode::INPUT_PULLUP)) { - ASF_LOGI("MAIN", 1004, "GPIO pin 4 configured as input with pull-up"); - - // Read pin level - int32_t level = gpio.getLevel(4); - ASF_LOGI("MAIN", 1005, "GPIO pin 4 level: %ld", level); - } - - ASF_LOGI("MAIN", 1006, "GPIO wrapper example completed"); -} - -/** - * @brief Interrupt handler example - */ -void IRAM_ATTR gpioInterruptHandler(uint32_t pin, void* arg) -{ - // Note: In interrupt context, logging should be minimal - // Consider using a queue to defer logging to a task - ASF_LOGI("ISR", 9001, "Interrupt on pin %lu", pin); -} - -/** - * @brief Example with interrupt handling - */ -void interruptExample() -{ - ASF_LOGI("MAIN", 1007, "Starting interrupt example"); - - GpioWithLogger gpio; - - // Configure pin as input - gpio.configure(5, GpioMode::INPUT); - - // Attach interrupt - gpio.attachInterrupt(5, GpioIntType::FALLING_EDGE, gpioInterruptHandler, nullptr); - - ASF_LOGI("MAIN", 1008, "Interrupt example setup complete"); -} \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/test/CMakeLists.txt b/draft- to be removed SW/components/utils/logger/test/CMakeLists.txt deleted file mode 100644 index e2f7d2a..0000000 --- a/draft- to be removed SW/components/utils/logger/test/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "test_logger.cpp" - INCLUDE_DIRS "." - REQUIRES unity logger -) \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/logger/test/test_logger.cpp b/draft- to be removed SW/components/utils/logger/test/test_logger.cpp deleted file mode 100644 index 9cdf971..0000000 --- a/draft- to be removed SW/components/utils/logger/test/test_logger.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/** - * @file test_logger.cpp - * @brief Unit tests for ASF Logger - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "unity.h" -#include "logger.hpp" -#include -#include - -// Test constants -static const char* TEST_TAG = "TEST_LOGGER"; -static const uint32_t TEST_ID = 12345; - -/** - * @brief Test logger initialization - */ -void test_logger_initialization() -{ - // Test default configuration - asf::logger::LoggerConfig defaultConfig = asf::logger::getDefaultConfig(); - - TEST_ASSERT_EQUAL(asf::logger::LogLevel::INFO, defaultConfig.minLevel); - TEST_ASSERT_TRUE(defaultConfig.enableTimestamp); - TEST_ASSERT_TRUE(defaultConfig.enableColor); - TEST_ASSERT_TRUE(defaultConfig.enableId); - TEST_ASSERT_EQUAL(256, defaultConfig.maxMessageLength); - - // Test custom configuration - asf::logger::LoggerConfig customConfig = {}; - customConfig.minLevel = asf::logger::LogLevel::DEBUG; - customConfig.enableTimestamp = false; - customConfig.enableColor = false; - customConfig.enableId = false; - customConfig.maxMessageLength = 128; - - asf::logger::initialize(customConfig); - - TEST_ASSERT_EQUAL(asf::logger::LogLevel::DEBUG, asf::logger::getLogLevel()); -} - -/** - * @brief Test log level functionality - */ -void test_log_levels() -{ - // Test setting different log levels - asf::logger::setLogLevel(asf::logger::LogLevel::VERBOSE); - TEST_ASSERT_EQUAL(asf::logger::LogLevel::VERBOSE, asf::logger::getLogLevel()); - - asf::logger::setLogLevel(asf::logger::LogLevel::DEBUG); - TEST_ASSERT_EQUAL(asf::logger::LogLevel::DEBUG, asf::logger::getLogLevel()); - - asf::logger::setLogLevel(asf::logger::LogLevel::INFO); - TEST_ASSERT_EQUAL(asf::logger::LogLevel::INFO, asf::logger::getLogLevel()); - - asf::logger::setLogLevel(asf::logger::LogLevel::WARNING); - TEST_ASSERT_EQUAL(asf::logger::LogLevel::WARNING, asf::logger::getLogLevel()); - - asf::logger::setLogLevel(asf::logger::LogLevel::ERROR); - TEST_ASSERT_EQUAL(asf::logger::LogLevel::ERROR, asf::logger::getLogLevel()); - - asf::logger::setLogLevel(asf::logger::LogLevel::NONE); - TEST_ASSERT_EQUAL(asf::logger::LogLevel::NONE, asf::logger::getLogLevel()); -} - -/** - * @brief Test log level to string conversion - */ -void test_log_level_to_string() -{ - TEST_ASSERT_EQUAL_STRING("VERBOSE", asf::logger::logLevelToString(asf::logger::LogLevel::VERBOSE)); - TEST_ASSERT_EQUAL_STRING("DEBUG", asf::logger::logLevelToString(asf::logger::LogLevel::DEBUG)); - TEST_ASSERT_EQUAL_STRING("INFO", asf::logger::logLevelToString(asf::logger::LogLevel::INFO)); - TEST_ASSERT_EQUAL_STRING("WARNING", asf::logger::logLevelToString(asf::logger::LogLevel::WARNING)); - TEST_ASSERT_EQUAL_STRING("ERROR", asf::logger::logLevelToString(asf::logger::LogLevel::ERROR)); - TEST_ASSERT_EQUAL_STRING("NONE", asf::logger::logLevelToString(asf::logger::LogLevel::NONE)); -} - -/** - * @brief Test log level to color conversion - */ -void test_log_level_to_color() -{ - // Test that color codes are returned (non-empty strings) - const char* verboseColor = asf::logger::logLevelToColor(asf::logger::LogLevel::VERBOSE); - const char* debugColor = asf::logger::logLevelToColor(asf::logger::LogLevel::DEBUG); - const char* infoColor = asf::logger::logLevelToColor(asf::logger::LogLevel::INFO); - const char* warningColor = asf::logger::logLevelToColor(asf::logger::LogLevel::WARNING); - const char* errorColor = asf::logger::logLevelToColor(asf::logger::LogLevel::ERROR); - - TEST_ASSERT_NOT_NULL(verboseColor); - TEST_ASSERT_NOT_NULL(debugColor); - TEST_ASSERT_NOT_NULL(infoColor); - TEST_ASSERT_NOT_NULL(warningColor); - TEST_ASSERT_NOT_NULL(errorColor); - - // Test that different levels have different colors - TEST_ASSERT_NOT_EQUAL_STRING(verboseColor, debugColor); - TEST_ASSERT_NOT_EQUAL_STRING(debugColor, infoColor); - TEST_ASSERT_NOT_EQUAL_STRING(infoColor, warningColor); - TEST_ASSERT_NOT_EQUAL_STRING(warningColor, errorColor); -} - -/** - * @brief Test ISO timestamp generation - */ -void test_iso_timestamp() -{ - char timestampBuffer[32]; - const char* timestamp = asf::logger::getIsoTimestamp(timestampBuffer, sizeof(timestampBuffer)); - - TEST_ASSERT_NOT_NULL(timestamp); - TEST_ASSERT_GREATER_THAN(0, strlen(timestamp)); - - // Check basic format (should contain 'T' and 'Z') - TEST_ASSERT_NOT_NULL(strchr(timestamp, 'T')); - TEST_ASSERT_NOT_NULL(strchr(timestamp, 'Z')); - - // Test with insufficient buffer - char smallBuffer[10]; - const char* smallTimestamp = asf::logger::getIsoTimestamp(smallBuffer, sizeof(smallBuffer)); - TEST_ASSERT_EQUAL_STRING("", smallTimestamp); - - // Test with null buffer - const char* nullTimestamp = asf::logger::getIsoTimestamp(nullptr, 32); - TEST_ASSERT_EQUAL_STRING("", nullTimestamp); -} - -/** - * @brief Test configuration toggles - */ -void test_configuration_toggles() -{ - // Test timestamp toggle - asf::logger::enableTimestamp(true); - // No direct way to test this without capturing output, but ensure no crash - - asf::logger::enableTimestamp(false); - // No direct way to test this without capturing output, but ensure no crash - - // Test color toggle - asf::logger::enableColor(true); - // No direct way to test this without capturing output, but ensure no crash - - asf::logger::enableColor(false); - // No direct way to test this without capturing output, but ensure no crash - - // Test ID toggle - asf::logger::enableId(true); - // No direct way to test this without capturing output, but ensure no crash - - asf::logger::enableId(false); - // No direct way to test this without capturing output, but ensure no crash -} - -/** - * @brief Test basic logging functions - */ -void test_basic_logging() -{ - // Initialize logger with verbose level to test all functions - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - config.minLevel = asf::logger::LogLevel::VERBOSE; - asf::logger::initialize(config); - - // Test all logging functions (should not crash) - asf::logger::logVerbose(TEST_TAG, TEST_ID, "Verbose message: %d", 1); - asf::logger::logDebug(TEST_TAG, TEST_ID, "Debug message: %d", 2); - asf::logger::logInfo(TEST_TAG, TEST_ID, "Info message: %d", 3); - asf::logger::logWarning(TEST_TAG, TEST_ID, "Warning message: %d", 4); - asf::logger::logError(TEST_TAG, TEST_ID, "Error message: %d", 5); - - // Test main log function - asf::logger::log(TEST_TAG, TEST_ID, asf::logger::LogLevel::INFO, "Main log function: %s", "test"); -} - -/** - * @brief Test logging macros - */ -void test_logging_macros() -{ - // Initialize logger with verbose level - asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); - config.minLevel = asf::logger::LogLevel::VERBOSE; - asf::logger::initialize(config); - - // Test all macros (should not crash) - ASF_LOG_VERBOSE(TEST_TAG, TEST_ID, "Verbose macro: %d", 1); - ASF_LOG_DEBUG(TEST_TAG, TEST_ID, "Debug macro: %d", 2); - ASF_LOG_INFO(TEST_TAG, TEST_ID, "Info macro: %d", 3); - ASF_LOG_WARNING(TEST_TAG, TEST_ID, "Warning macro: %d", 4); - ASF_LOG_ERROR(TEST_TAG, TEST_ID, "Error macro: %d", 5); - - // Test short form macros - ASF_LOGV(TEST_TAG, TEST_ID, "Verbose short macro: %d", 1); - ASF_LOGD(TEST_TAG, TEST_ID, "Debug short macro: %d", 2); - ASF_LOGI(TEST_TAG, TEST_ID, "Info short macro: %d", 3); - ASF_LOGW(TEST_TAG, TEST_ID, "Warning short macro: %d", 4); - ASF_LOGE(TEST_TAG, TEST_ID, "Error short macro: %d", 5); -} - -/** - * @brief Test log level filtering - */ -void test_log_level_filtering() -{ - // Set log level to WARNING - asf::logger::setLogLevel(asf::logger::LogLevel::WARNING); - - // These should be filtered out (no crash expected) - asf::logger::logVerbose(TEST_TAG, TEST_ID, "This should be filtered"); - asf::logger::logDebug(TEST_TAG, TEST_ID, "This should be filtered"); - asf::logger::logInfo(TEST_TAG, TEST_ID, "This should be filtered"); - - // These should pass through (no crash expected) - asf::logger::logWarning(TEST_TAG, TEST_ID, "This should pass"); - asf::logger::logError(TEST_TAG, TEST_ID, "This should pass"); -} - -/** - * @brief Test null parameter handling - */ -void test_null_parameters() -{ - // Test with null tag (should not crash) - asf::logger::logInfo(nullptr, TEST_ID, "Test message"); - - // Test with null format (should not crash) - asf::logger::logInfo(TEST_TAG, TEST_ID, nullptr); - - // Test main log function with null parameters - asf::logger::log(nullptr, TEST_ID, asf::logger::LogLevel::INFO, "Test message"); - asf::logger::log(TEST_TAG, TEST_ID, asf::logger::LogLevel::INFO, nullptr); -} - -/** - * @brief Test long messages - */ -void test_long_messages() -{ - // Create a long message - char longMessage[512]; - memset(longMessage, 'A', sizeof(longMessage) - 1); - longMessage[sizeof(longMessage) - 1] = '\0'; - - // Should handle long messages gracefully (truncate if necessary) - asf::logger::logInfo(TEST_TAG, TEST_ID, "Long message: %s", longMessage); -} - -/** - * @brief Test performance (basic timing) - */ -void test_performance() -{ - // Set to ERROR level to minimize output - asf::logger::setLogLevel(asf::logger::LogLevel::ERROR); - - // Perform many log calls that should be filtered out - for (int i = 0; i < 1000; i++) { - asf::logger::logInfo(TEST_TAG, i, "Performance test message %d", i); - } - - // This test mainly ensures no crashes during high-frequency logging - TEST_ASSERT_TRUE(true); // If we reach here, performance test passed -} - -/** - * @brief Run all logger tests - */ -extern "C" void app_main() -{ - UNITY_BEGIN(); - - RUN_TEST(test_logger_initialization); - RUN_TEST(test_log_levels); - RUN_TEST(test_log_level_to_string); - RUN_TEST(test_log_level_to_color); - RUN_TEST(test_iso_timestamp); - RUN_TEST(test_configuration_toggles); - RUN_TEST(test_basic_logging); - RUN_TEST(test_logging_macros); - RUN_TEST(test_log_level_filtering); - RUN_TEST(test_null_parameters); - RUN_TEST(test_long_messages); - RUN_TEST(test_performance); - - UNITY_END(); -} \ No newline at end of file diff --git a/draft- to be removed SW/components/utils/time_utils/CMakeLists.txt b/draft- to be removed SW/components/utils/time_utils/CMakeLists.txt deleted file mode 100644 index 65e40b7..0000000 --- a/draft- to be removed SW/components/utils/time_utils/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "com/time_utils.cpp" - INCLUDE_DIRS "com" - REQUIRES -) diff --git a/draft- to be removed SW/components/utils/time_utils/com/time_utils.cpp b/draft- to be removed SW/components/utils/time_utils/com/time_utils.cpp deleted file mode 100644 index f544679..0000000 --- a/draft- to be removed SW/components/utils/time_utils/com/time_utils.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file time_utils.cpp - * @brief Time utility functions implementation - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#include "time_utils.hpp" -#include -#include -#include - -namespace asf { -namespace utils { - -bool setSystemTime(const std::string& isoTimeStr) { - struct tm tm_time = {0}; - int ms = 0; - - // Parse ISO 8601: 2025-01-01T00:00:00.423Z - if (sscanf(isoTimeStr.c_str(), "%d-%d-%dT%d:%d:%d.%dZ", - &tm_time.tm_year, &tm_time.tm_mon, &tm_time.tm_mday, - &tm_time.tm_hour, &tm_time.tm_min, &tm_time.tm_sec, &ms) < 6) { - return false; - } - - tm_time.tm_year -= 1900; - tm_time.tm_mon -= 1; - - time_t t = mktime(&tm_time); - if (t == -1) { - return false; - } - - struct timeval tv; - tv.tv_sec = t; - tv.tv_usec = ms * 1000; - - return settimeofday(&tv, nullptr) == 0; -} - -} // namespace utils -} // namespace asf diff --git a/draft- to be removed SW/components/utils/time_utils/com/time_utils.hpp b/draft- to be removed SW/components/utils/time_utils/com/time_utils.hpp deleted file mode 100644 index 96c694c..0000000 --- a/draft- to be removed SW/components/utils/time_utils/com/time_utils.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file time_utils.hpp - * @brief Time utility functions for system time setup - * @author Mahmoud Elmohtady - * @company Nabd solutions - ASF - * @copyright Copyright (c) 2025 - */ - -#pragma once - -#include - -namespace asf { -namespace utils { - -/** - * @brief Set the system time from an ISO 8601 string - * - * @param isoTimeStr ISO 8601 formatted time string (e.g., "2025-01-01T00:00:00.423Z") - * @return true if time was set successfully, false otherwise - */ -bool setSystemTime(const std::string& isoTimeStr); - -} // namespace utils -} // namespace asf diff --git a/draft- to be removed SW/features/F-COM_Communication.md b/draft- to be removed SW/features/F-COM_Communication.md deleted file mode 100644 index 7621985..0000000 --- a/draft- to be removed SW/features/F-COM_Communication.md +++ /dev/null @@ -1,561 +0,0 @@ -# Feature Specification: Communication -# Feature ID: F-COM (F-COM-001 to F-COM-005) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Communication - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Communication feature provides comprehensive data exchange capabilities between the ASF Sensor Hub and external entities including the Main Hub and peer Sensor Hubs. This feature ensures reliable, secure, and deterministic transfer of sensor data, diagnostics, configuration updates, and control commands. - -### 1.2 Feature Scope - -**In Scope:** -- Bidirectional communication with Main Hub via MQTT over TLS 1.2 -- On-demand data broadcasting and request/response handling -- Peer-to-peer communication between Sensor Hubs via ESP-NOW -- Long-range fallback communication options (LoRa/Cellular) -- Communication protocol management and error handling - -**Out of Scope:** -- Main Hub broker implementation and configuration -- Cloud communication protocols and interfaces -- Internet connectivity and routing management -- Physical network infrastructure design - -## 2. Sub-Features - -### 2.1 F-COM-001: Main Hub Communication - -**Description:** Primary bidirectional communication channel with the Main Hub using MQTT over TLS 1.2 for secure and reliable data exchange. - -**Protocol Stack:** -```mermaid -graph TB - subgraph "Communication Protocol Stack" - APP[Application Layer - CBOR Messages] - MQTT[MQTT Layer - QoS 1, Topics, Keepalive] - TLS[TLS 1.2 Layer - mTLS, X.509 Certificates] - TCP[TCP Layer - Reliable Transport] - IP[IP Layer - Network Routing] - WIFI[Wi-Fi 802.11n - 2.4 GHz Physical Layer] - end - - APP --> MQTT - MQTT --> TLS - TLS --> TCP - TCP --> IP - IP --> WIFI -``` - -**MQTT Configuration:** -- **Broker:** Main Hub / Edge Gateway -- **QoS Level:** QoS 1 (At least once delivery) -- **Keepalive:** 60 seconds with 30-second timeout -- **Max Message Size:** 8KB per message -- **Payload Format:** CBOR (Compact Binary Object Representation) - -**Topic Structure:** -``` -/farm/{site_id}/{house_id}/{node_id}/data/{sensor_type} -/farm/{site_id}/{house_id}/{node_id}/status/heartbeat -/farm/{site_id}/{house_id}/{node_id}/status/system -/farm/{site_id}/{house_id}/{node_id}/cmd/{command_type} -/farm/{site_id}/{house_id}/{node_id}/diag/{severity_level} -/farm/{site_id}/{house_id}/{node_id}/ota/{action} -``` - -### 2.2 F-COM-002: On-Demand Data Broadcasting - -**Description:** Real-time data request/response mechanism allowing the Main Hub to query current sensor data without waiting for periodic updates. - -**Request/Response Flow:** -```mermaid -sequenceDiagram - participant MH as Main Hub - participant API as Main Hub APIs - participant DP as Data Pool - participant SM as Sensor Manager - - Note over MH,SM: On-Demand Data Request - - MH->>API: REQUEST_SENSOR_DATA(sensor_ids) - API->>DP: getLatestSensorData(sensor_ids) - DP-->>API: sensor_data_records - - alt Data available and fresh - API->>API: formatCBORResponse(data) - API->>MH: SENSOR_DATA_RESPONSE(data) - else Data stale or unavailable - API->>SM: requestImmediateSample(sensor_ids) - SM->>SM: performSampling() - SM->>DP: updateSensorData(fresh_data) - DP-->>API: fresh_sensor_data - API->>MH: SENSOR_DATA_RESPONSE(fresh_data) - end - - Note over MH,SM: Response time < 100ms -``` - -**Response Characteristics:** -- **Maximum Response Time:** 100ms from request to response -- **Data Freshness:** Timestamp included with all data -- **Validity Status:** Data quality indicators included -- **Batch Support:** Multiple sensors in single response - -### 2.3 F-COM-003: Peer Sensor Hub Communication - -**Description:** Limited peer-to-peer communication between Sensor Hubs using ESP-NOW for coordination and status exchange. - -**ESP-NOW Configuration:** -- **Protocol:** ESP-NOW (IEEE 802.11 vendor-specific) -- **Range:** ~200m line-of-sight, ~50m through walls -- **Security:** Application-layer AES-128 encryption -- **Max Peers:** 20 concurrent peer connections -- **Acknowledgment:** Application-layer retry mechanism - -**Peer Message Types:** -```c -typedef enum { - PEER_MSG_PING = 0x01, // Connectivity check - PEER_MSG_PONG = 0x02, // Connectivity response - PEER_MSG_TIME_SYNC_REQ = 0x03, // Time synchronization request - PEER_MSG_TIME_SYNC_RESP = 0x04, // Time synchronization response - PEER_MSG_STATUS_UPDATE = 0x05, // Status information exchange - PEER_MSG_EMERGENCY = 0x06 // Emergency notification -} peer_message_type_t; - -typedef struct { - uint8_t message_type; - uint8_t source_id[6]; // MAC address - uint8_t sequence_number; - uint16_t payload_length; - uint8_t payload[ESP_NOW_MAX_DATA_LEN - 10]; - uint8_t checksum; -} peer_message_t; -``` - -### 2.4 F-COM-004: Heartbeat and Status Reporting - -**Description:** Continuous system health and status reporting to maintain connection awareness and system monitoring. - -**Heartbeat Message Structure:** -```c -typedef struct { - uint32_t uptime_seconds; - char firmware_version[16]; - uint32_t free_heap_bytes; - int8_t wifi_rssi_dbm; - uint32_t error_bitmap; - system_state_t current_state; - uint8_t sensor_count_active; - uint8_t sensor_count_total; - uint32_t last_data_timestamp; - uint16_t communication_errors; -} heartbeat_payload_t; -``` - -**Status Reporting Schedule:** -- **Heartbeat Interval:** 10 seconds (configurable) -- **Status Update:** On state changes (immediate) -- **Error Reporting:** On fault detection (immediate) -- **Performance Metrics:** Every 5 minutes - -### 2.5 F-COM-005: Long-Range Fallback Communication - -**Description:** Optional long-range communication capability for farm-scale distances where Wi-Fi coverage is insufficient. - -**Fallback Options:** -1. **LoRa Module (Optional):** - - External LoRa transceiver (SX1276/SX1262) - - LoRaWAN or proprietary protocol - - Use cases: Emergency alerts, basic status - - Data rate: Low (not suitable for OTA updates) - -2. **Cellular Module (Alternative):** - - LTE-M or NB-IoT modem - - Higher data rate than LoRa - - Suitable for OTA updates - - Higher power consumption and cost - -**Fallback Activation Logic:** -```mermaid -graph TD - START[Communication Start] --> WIFI{Wi-Fi Available?} - WIFI -->|Yes| CONNECT[Connect to Wi-Fi] - WIFI -->|No| FALLBACK{Fallback Enabled?} - - CONNECT --> MQTT{MQTT Connected?} - MQTT -->|Yes| NORMAL[Normal Operation] - MQTT -->|No| RETRY[Retry Connection] - - RETRY --> TIMEOUT{Timeout Exceeded?} - TIMEOUT -->|No| MQTT - TIMEOUT -->|Yes| FALLBACK - - FALLBACK -->|Yes| LORA[Activate LoRa/Cellular] - FALLBACK -->|No| OFFLINE[Offline Mode] - - LORA --> LIMITED[Limited Communication] - OFFLINE --> STORE[Store Data Locally] - - NORMAL --> MONITOR[Monitor Connection] - LIMITED --> MONITOR - MONITOR --> WIFI -``` - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-COM-001** | SR-COM-001, SR-COM-002, SR-COM-003 | MQTT over TLS communication with Main Hub | -| **F-COM-002** | SR-COM-004, SR-COM-005 | On-demand data requests and responses | -| **F-COM-003** | SR-COM-006, SR-COM-007 | ESP-NOW peer communication | -| **F-COM-004** | SR-COM-008, SR-COM-009 | Heartbeat and status reporting | -| **F-COM-005** | SR-COM-010, SR-COM-011 | Long-range fallback communication | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-COM-001** | SWR-COM-001, SWR-COM-002, SWR-COM-003 | MQTT client, TLS implementation, topic management | -| **F-COM-002** | SWR-COM-004, SWR-COM-005, SWR-COM-006 | Request handling, data formatting, response timing | -| **F-COM-003** | SWR-COM-007, SWR-COM-008, SWR-COM-009 | ESP-NOW driver, peer management, encryption | -| **F-COM-004** | SWR-COM-010, SWR-COM-011, SWR-COM-012 | Status collection, heartbeat scheduling, error reporting | -| **F-COM-005** | SWR-COM-013, SWR-COM-014, SWR-COM-015 | Fallback protocols, activation logic, data prioritization | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **Main Hub APIs** | MQTT communication, message handling, protocol management | `application_layer/business_stack/main_hub_apis/` | -| **Network Stack** | Wi-Fi management, TCP/IP, TLS implementation | `drivers/network_stack/` | -| **Peer Communication Manager** | ESP-NOW management, peer coordination | `application_layer/peer_comm/` | -| **Communication Controller** | Protocol coordination, fallback management | `application_layer/comm_controller/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Event System** | Message routing, status notifications | `application_layer/business_stack/event_system/` | -| **Data Pool** | Latest sensor data access | `application_layer/DP_stack/data_pool/` | -| **Security Manager** | Certificate management, encryption | `application_layer/security/` | -| **Diagnostics Task** | Communication error logging | `application_layer/diag_task/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "Communication Feature" - API[Main Hub APIs] - NS[Network Stack] - PCM[Peer Comm Manager] - CC[Communication Controller] - end - - subgraph "Core System" - ES[Event System] - DP[Data Pool] - SEC[Security Manager] - DIAG[Diagnostics Task] - end - - subgraph "Hardware Interfaces" - WIFI[Wi-Fi Radio] - ESPNOW[ESP-NOW Interface] - LORA[LoRa Module] - CELL[Cellular Module] - end - - subgraph "External" - MAINHUB[Main Hub] - PEERS[Peer Hubs] - end - - API <--> NS - API <--> ES - API <--> DP - API <--> SEC - - PCM <--> ESPNOW - PCM <--> ES - PCM <--> SEC - - CC --> API - CC --> PCM - CC --> NS - - NS --> WIFI - NS --> SEC - NS --> DIAG - - WIFI <--> MAINHUB - ESPNOW <--> PEERS - LORA -.-> MAINHUB - CELL -.-> MAINHUB - - ES -.->|Status Events| API - DP -.->|Sensor Data| API - DIAG -.->|Error Events| API -``` - -### 4.4 Communication Flow Sequence - -```mermaid -sequenceDiagram - participant SM as Sensor Manager - participant ES as Event System - participant API as Main Hub APIs - participant NS as Network Stack - participant MH as Main Hub - - Note over SM,MH: Sensor Data Communication Flow - - SM->>ES: publish(SENSOR_DATA_UPDATE, data) - ES->>API: sensorDataEvent(data) - - API->>API: formatMQTTMessage(data) - API->>NS: publishMQTT(topic, payload) - NS->>NS: encryptTLS(payload) - NS->>MH: MQTT_PUBLISH(encrypted_data) - - MH-->>NS: MQTT_PUBACK - NS-->>API: publishComplete() - - alt Communication Error - NS->>DIAG: logCommError(error_details) - NS->>ES: publish(COMM_ERROR, error) - ES->>API: commErrorEvent(error) - API->>API: handleCommError() - end - - Note over SM,MH: Heartbeat Flow - - loop Every 10 seconds - API->>API: collectSystemStatus() - API->>NS: publishHeartbeat(status) - NS->>MH: MQTT_PUBLISH(heartbeat) - end -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **Connection Establishment:** - - Initialize Wi-Fi connection with configured credentials - - Establish TLS session with Main Hub broker - - Authenticate using device certificate (mTLS) - - Subscribe to command and configuration topics - -2. **Data Communication:** - - Publish sensor data on acquisition completion - - Send heartbeat messages at regular intervals - - Handle on-demand data requests from Main Hub - - Process configuration and command messages - -3. **Peer Communication:** - - Maintain ESP-NOW peer list and connections - - Exchange status information with nearby hubs - - Coordinate time synchronization when needed - - Handle emergency notifications from peers - -4. **Error Recovery:** - - Detect communication failures and timeouts - - Implement exponential backoff for reconnection - - Switch to fallback communication if available - - Store data locally during communication outages - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **Wi-Fi Disconnection** | Link status monitoring | Attempt reconnection, activate fallback | -| **MQTT Broker Unreachable** | Connection timeout | Retry with backoff, store data locally | -| **TLS Certificate Error** | Certificate validation failure | Log security event, request new certificate | -| **Message Timeout** | Acknowledgment timeout | Retry message, escalate if persistent | -| **Peer Communication Failure** | ESP-NOW transmission failure | Remove peer, attempt rediscovery | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Establish connections, authenticate, subscribe to topics | -| **RUNNING** | Full communication functionality, all protocols active | -| **WARNING** | Continue communication, increase error reporting | -| **FAULT** | Emergency communication only, diagnostic data priority | -| **OTA_UPDATE** | OTA-specific communication, suspend normal data flow | -| **TEARDOWN** | Send final status, gracefully close connections | -| **SERVICE** | Engineering communication enabled, diagnostic access | -| **SD_DEGRADED** | Continue communication, no local data buffering | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Connection Establishment:** Maximum 30 seconds for initial connection -- **Message Transmission:** Maximum 5 seconds for MQTT publish -- **On-Demand Response:** Maximum 100ms from request to response -- **Heartbeat Interval:** 10 seconds ±1 second tolerance - -### 6.2 Resource Constraints - -- **Memory Usage:** Maximum 64KB for communication buffers -- **Bandwidth Usage:** Maximum 1 Mbps average, 5 Mbps peak -- **Connection Limit:** 1 Main Hub + 20 peer connections maximum -- **Message Queue:** Maximum 100 pending messages - -### 6.3 Security Constraints - -- **Encryption:** All communication must use TLS 1.2 or higher -- **Authentication:** Mutual TLS required for Main Hub communication -- **Certificate Validation:** Full certificate chain validation required -- **Key Management:** Automatic key rotation support required - -## 7. Interface Specifications - -### 7.1 Main Hub APIs Public Interface - -```c -// Connection management -bool mainHubAPI_initialize(const comm_config_t* config); -bool mainHubAPI_connect(void); -bool mainHubAPI_disconnect(void); -bool mainHubAPI_isConnected(void); - -// Message publishing -bool mainHubAPI_publishSensorData(const sensor_data_record_t* data); -bool mainHubAPI_publishHeartbeat(const heartbeat_payload_t* heartbeat); -bool mainHubAPI_publishDiagnostic(const diagnostic_event_t* event); -bool mainHubAPI_publishStatus(const system_status_t* status); - -// Message handling -bool mainHubAPI_subscribeToCommands(command_handler_t handler); -bool mainHubAPI_subscribeToConfig(config_handler_t handler); -bool mainHubAPI_handleOnDemandRequest(const data_request_t* request); - -// Status and statistics -comm_status_t mainHubAPI_getConnectionStatus(void); -comm_stats_t mainHubAPI_getStatistics(void); -bool mainHubAPI_resetStatistics(void); -``` - -### 7.2 Peer Communication Manager API - -```c -// Peer management -bool peerComm_initialize(void); -bool peerComm_addPeer(const uint8_t* mac_address); -bool peerComm_removePeer(const uint8_t* mac_address); -bool peerComm_getPeerList(peer_info_t* peers, size_t* count); - -// Message transmission -bool peerComm_sendPing(const uint8_t* peer_mac); -bool peerComm_sendTimeSync(const uint8_t* peer_mac, uint64_t timestamp); -bool peerComm_sendStatus(const uint8_t* peer_mac, const peer_status_t* status); -bool peerComm_broadcastEmergency(const emergency_msg_t* emergency); - -// Message reception -bool peerComm_registerMessageHandler(peer_message_handler_t handler); -bool peerComm_setEncryptionKey(const uint8_t* key, size_t key_length); -``` - -### 7.3 Network Stack Interface - -```c -// Network management -bool networkStack_initialize(void); -bool networkStack_connectWiFi(const wifi_config_t* config); -bool networkStack_disconnectWiFi(void); -wifi_status_t networkStack_getWiFiStatus(void); - -// MQTT operations -bool networkStack_connectMQTT(const mqtt_config_t* config); -bool networkStack_publishMQTT(const char* topic, const uint8_t* payload, size_t length); -bool networkStack_subscribeMQTT(const char* topic, mqtt_message_handler_t handler); -bool networkStack_disconnectMQTT(void); - -// TLS management -bool networkStack_loadCertificate(const uint8_t* cert, size_t cert_length); -bool networkStack_loadPrivateKey(const uint8_t* key, size_t key_length); -bool networkStack_validateCertificate(const uint8_t* cert); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Protocol Implementation:** MQTT, TLS, ESP-NOW protocol compliance -- **Message Formatting:** CBOR encoding/decoding validation -- **Error Handling:** Network failure and recovery scenarios -- **Security:** Certificate validation and encryption testing - -### 8.2 Integration Testing - -- **Main Hub Communication:** End-to-end MQTT communication testing -- **Peer Communication:** ESP-NOW multi-device testing -- **Fallback Systems:** LoRa/Cellular fallback activation -- **Event Integration:** Communication event publication and handling - -### 8.3 System Testing - -- **Load Testing:** High-frequency data transmission under load -- **Reliability Testing:** 48-hour continuous communication -- **Security Testing:** Penetration testing and certificate validation -- **Interoperability:** Communication with actual Main Hub systems - -### 8.4 Acceptance Criteria - -- Successful connection establishment within timing constraints -- 99.9% message delivery success rate under normal conditions -- On-demand responses within 100ms requirement -- Secure communication with proper certificate validation -- Graceful handling of all communication error conditions -- Peer communication functional with multiple concurrent peers - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **Event System:** Message routing and status notifications -- **Data Pool:** Access to latest sensor data for transmission -- **Security Manager:** Certificate management and encryption -- **State Manager:** System state awareness for communication control - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** Wi-Fi, TCP/IP, TLS, ESP-NOW drivers -- **Main Hub Broker:** MQTT broker availability and configuration -- **Network Infrastructure:** Wi-Fi access points and internet connectivity -- **Certificate Authority:** X.509 certificates for device authentication - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Adaptive QoS:** Dynamic quality of service based on network conditions -- **Mesh Networking:** Sensor Hub mesh for extended coverage -- **Edge Computing:** Local data processing and filtering -- **5G Integration:** 5G connectivity for high-bandwidth applications - -### 10.2 Scalability Considerations - -- **Protocol Optimization:** Compressed protocols for bandwidth efficiency -- **Load Balancing:** Multiple Main Hub connections for redundancy -- **Cloud Integration:** Direct cloud connectivity bypass Main Hub -- **IoT Platform Integration:** Standard IoT platform protocol support - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-COM, SWR-COM) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-DAQ_Sensor_Data_Acquisition.md b/draft- to be removed SW/features/F-DAQ_Sensor_Data_Acquisition.md deleted file mode 100644 index 157f4cf..0000000 --- a/draft- to be removed SW/features/F-DAQ_Sensor_Data_Acquisition.md +++ /dev/null @@ -1,445 +0,0 @@ -# Feature Specification: Sensor Data Acquisition -# Feature ID: F-DAQ (F-DAQ-001 to F-DAQ-005) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Sensor Data Acquisition - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Sensor Data Acquisition feature provides comprehensive environmental sensor data collection, processing, and preparation capabilities for the ASF Sensor Hub. This feature ensures reliable, high-quality sensor data is available for persistence, communication, and system monitoring. - -### 1.2 Feature Scope - -**In Scope:** -- Multi-sensor data acquisition from 7 sensor types -- High-frequency sampling with configurable parameters -- Local data filtering and noise reduction -- Timestamped data record generation -- Sensor state management and lifecycle control - -**Out of Scope:** -- Sensor hardware design and manufacturing -- Main Hub data processing and analytics -- Control algorithm implementation -- Actuator management - -## 2. Sub-Features - -### 2.1 F-DAQ-001: Multi-Sensor Data Acquisition - -**Description:** Simultaneous data acquisition from multiple heterogeneous environmental sensors. - -**Supported Sensor Types:** -- Temperature sensors (I2C/Analog) -- Humidity sensors (I2C) -- Carbon Dioxide (CO₂) sensors (UART/I2C) -- Ammonia (NH₃) sensors (Analog/I2C) -- Volatile Organic Compounds (VOC) sensors (I2C) -- Particulate Matter (PM) sensors (UART/I2C) -- Light Intensity sensors (Analog/I2C) - -**Key Capabilities:** -- Concurrent sensor handling without blocking -- Modular sensor driver architecture -- Runtime sensor presence awareness -- Per-sensor enable/disable control - -### 2.2 F-DAQ-002: High-Frequency Sampling - -**Description:** Multiple raw readings per acquisition cycle with configurable sampling parameters. - -**Sampling Characteristics:** -- Default: 10 samples per sensor per cycle -- Configurable sampling count (5-20 samples) -- Bounded sampling time window (max 800ms) -- Deterministic sampling intervals - -**Benefits:** -- Noise reduction through oversampling -- Statistical confidence in measurements -- Outlier detection capability - -### 2.3 F-DAQ-003: Local Data Filtering - -**Description:** Configurable filtering algorithms applied to raw sensor samples. - -**Available Filters:** -- **Median Filter:** Removes outliers and impulse noise -- **Moving Average:** Smooths data and reduces random noise -- **Rate-of-Change Limiter:** Prevents unrealistic value jumps - -**Filter Configuration:** -- Filter type selectable per sensor -- Filter parameters configurable via Machine Constants -- Real-time filter switching capability - -### 2.4 F-DAQ-004: Timestamped Data Generation - -**Description:** Association of processed sensor values with accurate timestamps. - -**Timestamp Characteristics:** -- Generated after filtering completion -- System time based (RTC or synchronized) -- Accuracy: ±1 second -- ISO 8601 format for persistence - -**Data Record Structure:** -```c -typedef struct { - uint8_t sensor_id; - sensor_type_t sensor_type; - float filtered_value; - char unit[8]; - uint64_t timestamp_ms; - data_validity_t validity; - uint16_t sample_count; - float raw_min, raw_max; -} sensor_data_record_t; -``` - -### 2.5 F-DAQ-005: Sensor State Management - -**Description:** Comprehensive sensor lifecycle and state management. - -**Sensor States:** -- **UNKNOWN:** Initial state, not yet detected -- **DETECTED:** Sensor presence confirmed -- **INITIALIZED:** Driver loaded and configured -- **ENABLED:** Active data acquisition -- **DISABLED:** Present but not acquiring data -- **FAULTY:** Detected failure condition -- **REMOVED:** Previously present, now absent - -**State Transitions:** -```mermaid -stateDiagram-v2 - [*] --> UNKNOWN - UNKNOWN --> DETECTED : Presence detected - DETECTED --> INITIALIZED : Driver loaded - INITIALIZED --> ENABLED : Acquisition started - ENABLED --> DISABLED : Manual disable - DISABLED --> ENABLED : Manual enable - ENABLED --> FAULTY : Failure detected - FAULTY --> ENABLED : Recovery successful - DETECTED --> REMOVED : Presence lost - INITIALIZED --> REMOVED : Presence lost - ENABLED --> REMOVED : Presence lost - DISABLED --> REMOVED : Presence lost - FAULTY --> REMOVED : Presence lost - REMOVED --> DETECTED : Presence restored -``` - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-DAQ-001** | SR-DAQ-001 | Multi-sensor support for 7 sensor types | -| **F-DAQ-002** | SR-DAQ-002 | High-frequency sampling (min 10 samples/cycle) | -| **F-DAQ-003** | SR-DAQ-003 | Local data filtering with configurable algorithms | -| **F-DAQ-004** | SR-DAQ-004 | Timestamped data generation (±1 second accuracy) | -| **F-DAQ-005** | SR-DAQ-005 | Sensor state management and lifecycle control | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-DAQ-001** | SWR-DAQ-001, SWR-DAQ-002, SWR-DAQ-003 | Sensor driver abstraction, type enumeration, concurrent handling | -| **F-DAQ-002** | SWR-DAQ-004, SWR-DAQ-005, SWR-DAQ-006 | Configurable sampling, time windows, buffer management | -| **F-DAQ-003** | SWR-DAQ-007, SWR-DAQ-008, SWR-DAQ-009 | Median filter, moving average, filter selection | -| **F-DAQ-004** | SWR-DAQ-010, SWR-DAQ-011, SWR-DAQ-012 | Time interface, timestamp API, data record structure | -| **F-DAQ-005** | SWR-DAQ-013, SWR-DAQ-014, SWR-DAQ-015 | State enumeration, transition logic, persistence interface | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **Sensor Manager** | Acquisition coordination, filtering, state management | `application_layer/business_stack/sensor_manager/` | -| **Sensor Drivers** | Hardware interface, raw data acquisition | `drivers/sensor_drivers/` | -| **Event System** | Data publication, component coordination | `application_layer/business_stack/event_system/` | -| **Data Pool** | Latest sensor data storage | `application_layer/DP_stack/data_pool/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Time Utils** | Timestamp generation | `utils/time_utils/` | -| **Logger** | Debug and diagnostic logging | `utils/logger/` | -| **Machine Constant Manager** | Filter configuration, sensor parameters | `application_layer/business_stack/mc_manager/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "Sensor Data Acquisition Feature" - SM[Sensor Manager] - SD[Sensor Drivers] - ES[Event System] - DP[Data Pool] - TU[Time Utils] - MCM[MC Manager] - end - - subgraph "External Interfaces" - SENSORS[Physical Sensors] - PERSIST[Persistence] - COMM[Communication] - end - - SENSORS -->|I2C/SPI/UART/ADC| SD - SD -->|Raw Samples| SM - MCM -->|Filter Config| SM - TU -->|Timestamp| SM - SM -->|Filtered Data| ES - ES -->|Data Update Event| DP - ES -->|Data Update Event| PERSIST - ES -->|Data Update Event| COMM - - SM -.->|State Changes| ES - SM -.->|Diagnostics| ES -``` - -### 4.4 Data Flow Sequence - -```mermaid -sequenceDiagram - participant Sensor as Physical Sensor - participant Driver as Sensor Driver - participant Manager as Sensor Manager - participant MCMgr as MC Manager - participant TimeUtil as Time Utils - participant EventSys as Event System - participant DataPool as Data Pool - - Note over Sensor,DataPool: Acquisition Cycle (1 second) - - Manager->>MCMgr: getSamplingConfig(sensor_id) - MCMgr-->>Manager: sampling_config - - loop 10 samples - Manager->>Driver: readSensor(sensor_id) - Driver->>Sensor: I2C/SPI/UART read - Sensor-->>Driver: raw_value - Driver-->>Manager: raw_sample - end - - Manager->>Manager: applyFilter(raw_samples) - Manager->>TimeUtil: getCurrentTimestamp() - TimeUtil-->>Manager: timestamp - - Manager->>Manager: createDataRecord() - Manager->>EventSys: publish(SENSOR_DATA_UPDATE, record) - EventSys->>DataPool: updateSensorData(record) - - Note over Manager,DataPool: Data available for persistence and communication -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **Initialization Phase:** - - Load sensor configuration from Machine Constants - - Initialize sensor drivers for detected sensors - - Configure sampling and filtering parameters - - Transition sensors to ENABLED state - -2. **Acquisition Cycle (1 second):** - - For each enabled sensor: - - Perform high-frequency sampling (10 samples) - - Apply configured filter to raw samples - - Generate timestamp for filtered value - - Create sensor data record - - Publish data update event - -3. **State Management:** - - Monitor sensor health during acquisition - - Detect and handle sensor failures - - Update sensor states based on conditions - - Report state changes via events - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **Sensor Communication Failure** | Timeout or invalid response | Mark sensor as FAULTY, continue with other sensors | -| **Out-of-Range Values** | Range validation | Mark data as invalid, log diagnostic event | -| **Sampling Timeout** | Bounded time window exceeded | Use partial samples, mark data quality degraded | -| **Filter Failure** | Exception in filter algorithm | Use raw average, log diagnostic event | -| **Memory Allocation Failure** | Buffer allocation failure | Skip cycle, trigger system diagnostic | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Initialize sensors, load configuration | -| **RUNNING** | Normal acquisition cycles | -| **WARNING** | Continue acquisition, increase diagnostic reporting | -| **FAULT** | Stop acquisition, preserve sensor states | -| **OTA_UPDATE** | Stop acquisition, save sensor states | -| **MC_UPDATE** | Stop acquisition, reload configuration after update | -| **TEARDOWN** | Stop acquisition, flush pending data | -| **SERVICE** | Limited acquisition for diagnostics | -| **SD_DEGRADED** | Continue acquisition, no persistence | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Acquisition Cycle:** Must complete within 1 second -- **Sampling Window:** Maximum 800ms per sensor -- **Filter Processing:** Maximum 50ms per sensor -- **Event Publication:** Maximum 10ms delay - -### 6.2 Resource Constraints - -- **Memory Usage:** Maximum 32KB for sensor data buffers -- **CPU Usage:** Maximum 20% of available CPU time -- **I/O Bandwidth:** Shared among all sensors, priority-based - -### 6.3 Quality Constraints - -- **Data Accuracy:** Within sensor specification limits -- **Timestamp Accuracy:** ±1 second of system time -- **Filter Effectiveness:** >90% noise reduction for median filter -- **State Consistency:** 100% accurate state representation - -## 7. Interface Specifications - -### 7.1 Sensor Manager Public API - -```c -// Initialization and configuration -bool sensorMgr_initialize(void); -bool sensorMgr_loadConfiguration(const machine_constants_t* mc); -bool sensorMgr_detectSensors(void); - -// Acquisition control -bool sensorMgr_startAcquisition(void); -bool sensorMgr_stopAcquisition(void); -bool sensorMgr_pauseAcquisition(void); -bool sensorMgr_resumeAcquisition(void); - -// Sensor control -bool sensorMgr_enableSensor(uint8_t sensor_id); -bool sensorMgr_disableSensor(uint8_t sensor_id); -bool sensorMgr_configureSensor(uint8_t sensor_id, const sensor_config_t* config); - -// Data access -bool sensorMgr_getLatestData(uint8_t sensor_id, sensor_data_record_t* record); -bool sensorMgr_getAllSensorData(sensor_data_record_t* records, size_t* count); - -// State management -sensor_state_t sensorMgr_getSensorState(uint8_t sensor_id); -bool sensorMgr_isSensorPresent(uint8_t sensor_id); -bool sensorMgr_isSensorEnabled(uint8_t sensor_id); -bool sensorMgr_isSensorHealthy(uint8_t sensor_id); - -// Statistics and diagnostics -bool sensorMgr_getSensorStatistics(uint8_t sensor_id, sensor_stats_t* stats); -bool sensorMgr_resetSensorStatistics(uint8_t sensor_id); -``` - -### 7.2 Event System Integration - -**Published Events:** -- `EVENT_SENSOR_DATA_UPDATE`: New sensor data available -- `EVENT_SENSOR_STATE_CHANGED`: Sensor state transition -- `EVENT_SENSOR_FAULT_DETECTED`: Sensor failure detected -- `EVENT_SENSOR_RECOVERY`: Sensor recovered from fault - -**Subscribed Events:** -- `EVENT_STATE_CHANGED`: System state transitions -- `EVENT_MC_UPDATED`: Machine constants updated -- `EVENT_TEARDOWN_INITIATED`: System teardown requested - -### 7.3 Data Pool Integration - -**Data Storage:** -- Latest sensor data records for all sensors -- Sensor state information -- Acquisition statistics and health metrics - -**Access Patterns:** -- Write: Sensor Manager updates after each acquisition cycle -- Read: Communication and Persistence components access latest data -- Query: HMI and Diagnostics access for display and analysis - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Sensor Driver Interface:** Mock sensors for driver testing -- **Filtering Algorithms:** Known input/output validation -- **State Machine:** All state transitions and edge cases -- **Data Record Generation:** Structure and content validation - -### 8.2 Integration Testing - -- **Sensor Manager + Drivers:** Real sensor hardware testing -- **Event System Integration:** Event publication and subscription -- **Data Pool Integration:** Data storage and retrieval -- **State Management:** Cross-component state coordination - -### 8.3 System Testing - -- **Multi-Sensor Acquisition:** All 7 sensor types simultaneously -- **Performance Testing:** Timing constraints under load -- **Fault Injection:** Sensor failure scenarios -- **Long-Duration Testing:** 24-hour continuous operation - -### 8.4 Acceptance Criteria - -- All sensor types successfully detected and initialized -- Acquisition cycles complete within 1-second constraint -- Filter algorithms reduce noise by >90% -- State transitions occur correctly under all conditions -- No memory leaks during continuous operation -- Graceful handling of all error conditions - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **Machine Constant Manager:** Sensor configuration and parameters -- **Event System:** Inter-component communication -- **Data Pool:** Data storage and access -- **Time Utils:** Timestamp generation -- **Logger:** Debug and diagnostic output - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** Hardware abstraction and drivers -- **FreeRTOS:** Task scheduling and timing -- **Hardware Sensors:** Physical sensor devices -- **System State Manager:** State-aware operation control - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Adaptive Filtering:** Machine learning-based filter optimization -- **Predictive Maintenance:** Sensor degradation prediction -- **Advanced Calibration:** Multi-point calibration support -- **Sensor Fusion:** Cross-sensor validation and fusion - -### 10.2 Scalability Considerations - -- **Additional Sensor Types:** Framework supports easy extension -- **Higher Sampling Rates:** Configurable for future requirements -- **Distributed Processing:** Support for sensor processing offload -- **Cloud Integration:** Direct sensor data streaming capability - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (45 SR, 122 SWR) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-DATA_Persistence_Management.md b/draft- to be removed SW/features/F-DATA_Persistence_Management.md deleted file mode 100644 index e69de29..0000000 diff --git a/draft- to be removed SW/features/F-DIAG_Diagnostics_Health.md b/draft- to be removed SW/features/F-DIAG_Diagnostics_Health.md deleted file mode 100644 index 80f602a..0000000 --- a/draft- to be removed SW/features/F-DIAG_Diagnostics_Health.md +++ /dev/null @@ -1,581 +0,0 @@ -# Feature Specification: Diagnostics & Health Monitoring -# Feature ID: F-DIAG (F-DIAG-001 to F-DIAG-004) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Diagnostics & Health Monitoring - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Diagnostics & Health Monitoring feature provides comprehensive system health assessment, fault detection, diagnostic event management, and engineering access capabilities for the ASF Sensor Hub. This feature ensures system reliability through proactive monitoring, structured fault reporting, and maintenance support. - -### 1.2 Feature Scope - -**In Scope:** -- Structured diagnostic code framework with severity classification -- Persistent diagnostic event storage and management -- Engineering diagnostic sessions with secure access -- System health monitoring and performance metrics -- Cross-component fault correlation and root cause analysis - -**Out of Scope:** -- Main Hub diagnostic aggregation and analysis -- Predictive maintenance algorithms (future enhancement) -- Hardware fault injection testing equipment -- Remote diagnostic access without Main Hub coordination - -## 2. Sub-Features - -### 2.1 F-DIAG-001: Diagnostic Code Management - -**Description:** Comprehensive diagnostic code framework for standardized fault identification, classification, and reporting across all system components. - -**Diagnostic Code Structure:** -```c -typedef struct { - uint16_t code; // Unique diagnostic code (0x0001-0xFFFF) - diagnostic_severity_t severity; // INFO, WARNING, ERROR, FATAL - diagnostic_category_t category; // SENSOR, COMM, STORAGE, SYSTEM, SECURITY - uint64_t timestamp_ms; // Event occurrence time - uint8_t source_component_id; // Component that generated the event - char description[64]; // Human-readable description - uint8_t data[32]; // Context-specific diagnostic data - uint16_t occurrence_count; // Number of times this event occurred -} diagnostic_event_t; - -typedef enum { - DIAG_SEVERITY_INFO = 0, // Informational, no action required - DIAG_SEVERITY_WARNING = 1, // Warning, monitoring required - DIAG_SEVERITY_ERROR = 2, // Error, corrective action needed - DIAG_SEVERITY_FATAL = 3 // Fatal, system functionality compromised -} diagnostic_severity_t; - -typedef enum { - DIAG_CATEGORY_SENSOR = 0, // Sensor-related diagnostics - DIAG_CATEGORY_COMM = 1, // Communication diagnostics - DIAG_CATEGORY_STORAGE = 2, // Storage and persistence diagnostics - DIAG_CATEGORY_SYSTEM = 3, // System management diagnostics - DIAG_CATEGORY_SECURITY = 4, // Security-related diagnostics - DIAG_CATEGORY_POWER = 5, // Power and fault handling diagnostics - DIAG_CATEGORY_OTA = 6 // OTA update diagnostics -} diagnostic_category_t; -``` - -**Diagnostic Code Registry (Examples):** -| Code | Severity | Category | Description | -|------|----------|----------|-------------| -| 0x1001 | WARNING | SENSOR | Sensor communication timeout | -| 0x1002 | ERROR | SENSOR | Sensor out-of-range value detected | -| 0x1003 | FATAL | SENSOR | Critical sensor hardware failure | -| 0x2001 | WARNING | COMM | Wi-Fi signal strength low | -| 0x2002 | ERROR | COMM | MQTT broker connection failed | -| 0x2003 | FATAL | COMM | TLS certificate validation failed | -| 0x3001 | WARNING | STORAGE | SD card space low (< 10%) | -| 0x3002 | ERROR | STORAGE | SD card write failure | -| 0x3003 | FATAL | STORAGE | SD card not detected | -| 0x4001 | INFO | SYSTEM | System state transition | -| 0x4002 | WARNING | SYSTEM | Memory usage high (> 80%) | -| 0x4003 | FATAL | SYSTEM | Watchdog timer reset | - -### 2.2 F-DIAG-002: Diagnostic Data Storage - -**Description:** Persistent storage of diagnostic events in non-volatile memory with efficient storage management and retrieval capabilities. - -**Storage Architecture:** -```mermaid -graph TB - subgraph "Diagnostic Storage System" - GEN[Diagnostic Generator] --> BUF[Ring Buffer] - BUF --> FILTER[Severity Filter] - FILTER --> PERSIST[Persistence Layer] - PERSIST --> SD[SD Card Storage] - PERSIST --> NVS[NVS Flash Storage] - end - - subgraph "Storage Policy" - CRITICAL[FATAL/ERROR Events] --> NVS - NORMAL[WARNING/INFO Events] --> SD - OVERFLOW[Buffer Overflow] --> DISCARD[Discard Oldest] - end - - subgraph "Retrieval Interface" - QUERY[Query Interface] --> PERSIST - EXPORT[Export Interface] --> PERSIST - CLEAR[Clear Interface] --> PERSIST - end -``` - -**Storage Management:** -- **Ring Buffer:** 100 events in RAM for immediate access -- **NVS Storage:** Critical events (ERROR/FATAL) persisted to flash -- **SD Card Storage:** All events stored to SD card when available -- **Retention Policy:** 30 days or 10,000 events maximum -- **Compression:** Event data compressed for efficient storage - -### 2.3 F-DIAG-003: Diagnostic Session - -**Description:** Secure engineering access interface for diagnostic data retrieval, system inspection, and maintenance operations. - -**Session Types:** -| Session Type | Access Level | Authentication | Capabilities | -|-------------|-------------|----------------|--------------| -| **Read-Only** | Basic | PIN code | View diagnostics, system status | -| **Engineering** | Advanced | Certificate | Diagnostic management, configuration | -| **Service** | Full | Multi-factor | System control, debug access | - -**Session Interface:** -```c -typedef struct { - session_id_t session_id; - session_type_t type; - uint64_t start_time; - uint64_t last_activity; - uint32_t timeout_seconds; - bool authenticated; - char user_id[32]; -} diagnostic_session_t; - -// Session management API -session_id_t diag_createSession(session_type_t type); -bool diag_authenticateSession(session_id_t session, const auth_credentials_t* creds); -bool diag_closeSession(session_id_t session); -bool diag_isSessionValid(session_id_t session); - -// Diagnostic access API -bool diag_getEvents(session_id_t session, diagnostic_filter_t* filter, - diagnostic_event_t* events, size_t* count); -bool diag_clearEvents(session_id_t session, diagnostic_filter_t* filter); -bool diag_exportEvents(session_id_t session, export_format_t format, - uint8_t* buffer, size_t* size); -bool diag_getSystemHealth(session_id_t session, system_health_t* health); -``` - -### 2.4 F-DIAG-004: System Health Monitoring - -**Description:** Continuous monitoring of system performance metrics, resource utilization, and component health status. - -**Health Metrics:** -```c -typedef struct { - // CPU and Memory - uint8_t cpu_usage_percent; - uint32_t free_heap_bytes; - uint32_t min_free_heap_bytes; - uint16_t task_count; - - // Storage - uint64_t sd_free_bytes; - uint64_t sd_total_bytes; - uint32_t nvs_free_entries; - uint32_t nvs_used_entries; - - // Communication - int8_t wifi_rssi_dbm; - uint32_t mqtt_messages_sent; - uint32_t mqtt_messages_failed; - uint32_t comm_error_count; - - // Sensors - uint8_t sensors_active; - uint8_t sensors_total; - uint8_t sensors_failed; - uint32_t sensor_error_count; - - // System - uint32_t uptime_seconds; - uint32_t reset_count; - system_state_t current_state; - uint32_t state_change_count; - - // Power - float supply_voltage; - bool brownout_detected; - uint32_t power_cycle_count; -} system_health_t; -``` - -**Health Monitoring Flow:** -```mermaid -sequenceDiagram - participant HM as Health Monitor - participant COMP as System Components - participant DIAG as Diagnostic Storage - participant ES as Event System - participant HMI as Local HMI - - Note over HM,HMI: Health Monitoring Cycle (10 seconds) - - loop Every 10 seconds - HM->>COMP: collectHealthMetrics() - COMP-->>HM: health_data - - HM->>HM: analyzeHealthTrends() - HM->>HM: detectAnomalies() - - alt Anomaly detected - HM->>DIAG: logDiagnosticEvent(anomaly) - HM->>ES: publish(HEALTH_ANOMALY, details) - end - - HM->>ES: publish(HEALTH_UPDATE, metrics) - ES->>HMI: updateHealthDisplay(metrics) - end -``` - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-DIAG-001** | SR-DIAG-001, SR-DIAG-002, SR-DIAG-003, SR-DIAG-004 | Diagnostic code framework and event management | -| **F-DIAG-002** | SR-DIAG-005, SR-DIAG-006, SR-DIAG-007 | Persistent diagnostic storage and retention | -| **F-DIAG-003** | SR-DIAG-008, SR-DIAG-009, SR-DIAG-010, SR-DIAG-011 | Engineering diagnostic sessions and access control | -| **F-DIAG-004** | SR-DIAG-012, SR-DIAG-013, SR-DIAG-014 | System health monitoring and performance metrics | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-DIAG-001** | SWR-DIAG-001, SWR-DIAG-002, SWR-DIAG-003 | Event structure, code registry, severity classification | -| **F-DIAG-002** | SWR-DIAG-004, SWR-DIAG-005, SWR-DIAG-006 | Storage management, persistence, retrieval interface | -| **F-DIAG-003** | SWR-DIAG-007, SWR-DIAG-008, SWR-DIAG-009 | Session management, authentication, access control | -| **F-DIAG-004** | SWR-DIAG-010, SWR-DIAG-011, SWR-DIAG-012 | Health metrics collection, anomaly detection, reporting | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **Diagnostics Task** | Health monitoring, event coordination, session management | `application_layer/diag_task/` | -| **Error Handler** | Diagnostic event generation, fault classification | `application_layer/error_handler/` | -| **Diagnostic Storage Manager** | Event persistence, retrieval, storage management | `application_layer/diag_storage/` | -| **Health Monitor** | System metrics collection, anomaly detection | `application_layer/health_monitor/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Event System** | Diagnostic event distribution, component coordination | `application_layer/business_stack/event_system/` | -| **Data Persistence** | Storage abstraction, NVS and SD card access | `application_layer/DP_stack/persistence/` | -| **Security Manager** | Session authentication, access control | `application_layer/security/` | -| **State Manager** | System state awareness, state-dependent diagnostics | `application_layer/business_stack/STM/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "Diagnostics & Health Monitoring Feature" - DT[Diagnostics Task] - EH[Error Handler] - DSM[Diagnostic Storage Manager] - HM[Health Monitor] - end - - subgraph "Core System Components" - ES[Event System] - DP[Data Persistence] - SEC[Security Manager] - STM[State Manager] - end - - subgraph "System Components" - SM[Sensor Manager] - COM[Communication] - OTA[OTA Manager] - PWR[Power Manager] - end - - subgraph "Storage" - NVS[NVS Flash] - SD[SD Card] - end - - subgraph "Interfaces" - HMI[Local HMI] - UART[UART Debug] - NET[Network Session] - end - - DT <--> ES - DT <--> DSM - DT <--> HM - DT <--> SEC - - EH --> ES - EH --> DSM - - DSM <--> DP - DSM --> NVS - DSM --> SD - - HM --> SM - HM --> COM - HM --> OTA - HM --> PWR - HM --> STM - - ES -.->|Health Events| HMI - ES -.->|Diagnostic Events| COM - DT -.->|Session Access| UART - DT -.->|Session Access| NET -``` - -### 4.4 Diagnostic Event Flow - -```mermaid -sequenceDiagram - participant COMP as System Component - participant EH as Error Handler - participant ES as Event System - participant DSM as Diagnostic Storage - participant DT as Diagnostics Task - participant COM as Communication - - Note over COMP,COM: Diagnostic Event Generation and Processing - - COMP->>EH: reportError(error_info) - EH->>EH: classifyError(error_info) - EH->>EH: generateDiagnosticEvent() - - EH->>ES: publish(DIAGNOSTIC_EVENT, event) - ES->>DSM: storeDiagnosticEvent(event) - ES->>DT: processDiagnosticEvent(event) - ES->>COM: reportDiagnosticEvent(event) - - DSM->>DSM: checkStoragePolicy(event.severity) - - alt Critical Event (ERROR/FATAL) - DSM->>NVS: persistToFlash(event) - end - - DSM->>SD: persistToSDCard(event) - - DT->>DT: updateHealthMetrics(event) - DT->>DT: checkSystemHealth() - - alt Health degradation detected - DT->>ES: publish(HEALTH_DEGRADATION, metrics) - end -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **System Initialization:** - - Initialize diagnostic storage and load existing events - - Start health monitoring tasks and metric collection - - Register diagnostic event handlers with all components - - Establish baseline health metrics and thresholds - -2. **Continuous Monitoring:** - - Collect system health metrics every 10 seconds - - Process diagnostic events from all system components - - Store events according to severity and storage policy - - Analyze health trends and detect anomalies - -3. **Event Processing:** - - Classify and timestamp all diagnostic events - - Apply filtering and correlation rules - - Persist events to appropriate storage (NVS/SD) - - Distribute events to interested components - -4. **Session Management:** - - Handle engineering session requests and authentication - - Provide secure access to diagnostic data and system health - - Log all diagnostic session activities for audit - - Enforce session timeouts and access controls - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **Storage Full** | Storage capacity monitoring | Implement retention policy, discard oldest events | -| **SD Card Failure** | Write operation failure | Switch to NVS-only storage, log degradation | -| **Memory Exhaustion** | Heap monitoring | Reduce buffer sizes, increase event filtering | -| **Session Timeout** | Activity monitoring | Close session, clear authentication | -| **Authentication Failure** | Credential validation | Reject session, log security event | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Initialize storage, load existing events, start monitoring | -| **RUNNING** | Full diagnostic functionality, continuous health monitoring | -| **WARNING** | Enhanced monitoring, increased event generation | -| **FAULT** | Critical diagnostics only, preserve fault information | -| **OTA_UPDATE** | Suspend monitoring, log OTA-related events | -| **TEARDOWN** | Flush pending events, preserve diagnostic state | -| **SERVICE** | Full diagnostic access, engineering session support | -| **SD_DEGRADED** | NVS-only storage, reduced event retention | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Event Processing:** Maximum 10ms from generation to storage -- **Health Monitoring:** 10-second monitoring cycle with ±1 second tolerance -- **Session Response:** Maximum 500ms for diagnostic queries -- **Storage Operations:** Maximum 100ms for event persistence - -### 6.2 Resource Constraints - -- **Memory Usage:** Maximum 32KB for diagnostic buffers and storage -- **Event Storage:** Maximum 10,000 events or 30 days retention -- **Session Limit:** Maximum 2 concurrent diagnostic sessions -- **CPU Usage:** Maximum 5% of available CPU time for diagnostics - -### 6.3 Security Constraints - -- **Session Authentication:** All diagnostic access must be authenticated -- **Data Protection:** Diagnostic data encrypted when stored -- **Access Logging:** All diagnostic activities logged for audit -- **Privilege Separation:** Role-based access to diagnostic functions - -## 7. Interface Specifications - -### 7.1 Diagnostics Task Public API - -```c -// Initialization and control -bool diagTask_initialize(void); -bool diagTask_start(void); -bool diagTask_stop(void); -bool diagTask_isRunning(void); - -// Event management -bool diagTask_reportEvent(const diagnostic_event_t* event); -bool diagTask_getEvents(const diagnostic_filter_t* filter, - diagnostic_event_t* events, size_t* count); -bool diagTask_clearEvents(const diagnostic_filter_t* filter); -bool diagTask_exportEvents(export_format_t format, uint8_t* buffer, size_t* size); - -// Health monitoring -bool diagTask_getSystemHealth(system_health_t* health); -bool diagTask_getHealthHistory(health_history_t* history, size_t* count); -bool diagTask_resetHealthMetrics(void); - -// Session management -session_id_t diagTask_createSession(session_type_t type); -bool diagTask_authenticateSession(session_id_t session, const auth_credentials_t* creds); -bool diagTask_closeSession(session_id_t session); -bool diagTask_isSessionValid(session_id_t session); -``` - -### 7.2 Error Handler API - -```c -// Error reporting -bool errorHandler_reportError(component_id_t source, error_code_t code, - const char* description, const uint8_t* context_data); -bool errorHandler_reportWarning(component_id_t source, warning_code_t code, - const char* description); -bool errorHandler_reportInfo(component_id_t source, info_code_t code, - const char* description); - -// Error classification -diagnostic_severity_t errorHandler_classifyError(error_code_t code); -diagnostic_category_t errorHandler_categorizeError(component_id_t source, error_code_t code); -bool errorHandler_isErrorCritical(error_code_t code); - -// Error statistics -bool errorHandler_getErrorStatistics(error_statistics_t* stats); -bool errorHandler_resetErrorStatistics(void); -``` - -### 7.3 Health Monitor API - -```c -// Health monitoring -bool healthMonitor_initialize(void); -bool healthMonitor_startMonitoring(void); -bool healthMonitor_stopMonitoring(void); -bool healthMonitor_getCurrentHealth(system_health_t* health); - -// Metric collection -bool healthMonitor_collectMetrics(void); -bool healthMonitor_updateMetric(health_metric_id_t metric_id, float value); -bool healthMonitor_getMetricHistory(health_metric_id_t metric_id, - metric_history_t* history, size_t* count); - -// Anomaly detection -bool healthMonitor_setThreshold(health_metric_id_t metric_id, float threshold); -bool healthMonitor_enableAnomalyDetection(health_metric_id_t metric_id, bool enable); -bool healthMonitor_getAnomalies(anomaly_t* anomalies, size_t* count); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Event Generation:** Diagnostic event creation and classification -- **Storage Management:** Event persistence and retrieval operations -- **Health Monitoring:** Metric collection and anomaly detection -- **Session Management:** Authentication and access control - -### 8.2 Integration Testing - -- **Cross-Component Events:** Diagnostic events from all system components -- **Storage Integration:** NVS and SD card storage operations -- **Event Distribution:** Event system integration and notification -- **Session Integration:** Engineering access via multiple interfaces - -### 8.3 System Testing - -- **Long-Duration Monitoring:** 48-hour continuous diagnostic operation -- **Storage Stress Testing:** High-frequency event generation and storage -- **Session Security Testing:** Authentication bypass attempts -- **Fault Injection Testing:** Component failure simulation and detection - -### 8.4 Acceptance Criteria - -- All diagnostic events properly classified and stored -- Health monitoring detects system anomalies within timing constraints -- Engineering sessions provide secure access to diagnostic data -- Storage management maintains data integrity under all conditions -- No diagnostic overhead impact on core system functionality -- Complete audit trail of all diagnostic activities - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **Event System:** Diagnostic event distribution and coordination -- **Data Persistence:** Storage abstraction for diagnostic data -- **Security Manager:** Session authentication and access control -- **State Manager:** System state awareness for state-dependent diagnostics - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** NVS, SD card, and system monitoring APIs -- **FreeRTOS:** Task scheduling and system resource monitoring -- **Hardware Components:** SD card, NVS flash, UART interface -- **System Components:** All components for health metric collection - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Predictive Analytics:** Machine learning for failure prediction -- **Advanced Correlation:** Multi-component fault correlation analysis -- **Remote Diagnostics:** Cloud-based diagnostic data analysis -- **Automated Recovery:** Self-healing mechanisms based on diagnostics - -### 10.2 Scalability Considerations - -- **Distributed Diagnostics:** Cross-hub diagnostic correlation -- **Cloud Integration:** Real-time diagnostic streaming to cloud -- **Advanced Analytics:** Big data analytics for fleet-wide diagnostics -- **Mobile Interface:** Smartphone app for field diagnostic access - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-DIAG, SWR-DIAG) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-DQC_Data_Quality_Calibration.md b/draft- to be removed SW/features/F-DQC_Data_Quality_Calibration.md deleted file mode 100644 index 42b0715..0000000 --- a/draft- to be removed SW/features/F-DQC_Data_Quality_Calibration.md +++ /dev/null @@ -1,528 +0,0 @@ -# Feature Specification: Data Quality & Calibration -# Feature ID: F-DQC (F-DQC-001 to F-DQC-005) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Data Quality & Calibration - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Data Quality & Calibration feature ensures that all sensor data generated by the ASF Sensor Hub is valid, trustworthy, correctly classified, and calibrated throughout the system lifecycle. This feature provides mechanisms for automatic sensor identification, compatibility enforcement, failure detection, and centralized calibration management. - -### 1.2 Feature Scope - -**In Scope:** -- Automatic sensor detection and identification -- Sensor-slot compatibility enforcement -- Real-time sensor failure detection and isolation -- Machine constants and calibration parameter management -- Redundant sensor support and sensor fusion - -**Out of Scope:** -- Sensor hardware manufacturing and design -- External calibration equipment and procedures -- Main Hub calibration algorithms -- Sensor replacement and maintenance procedures - -## 2. Sub-Features - -### 2.1 F-DQC-001: Automatic Sensor Detection - -**Description:** Dynamic detection and identification of connected sensors using hardware-based presence detection mechanisms. - -**Detection Methods:** -- **GPIO Presence Pins:** Dedicated detection signals per sensor slot -- **I2C Device Scanning:** Automatic I2C address enumeration -- **Device ID Reading:** Sensor-specific identification protocols -- **Electrical Signature:** Voltage/resistance-based detection - -**Detection Process:** -```mermaid -sequenceDiagram - participant SM as Sensor Manager - participant DD as Device Detector - participant SD as Sensor Driver - participant MC as Machine Constants - - Note over SM,MC: Sensor Detection Cycle - - SM->>DD: scanForSensors() - - loop For each sensor slot - DD->>DD: checkPresencePin(slot_id) - alt Presence detected - DD->>SD: probeSensorType(slot_id) - SD->>SD: readDeviceID() - SD-->>DD: sensor_type_info - DD->>MC: validateSensorSlot(slot_id, sensor_type) - MC-->>DD: validation_result - end - end - - DD-->>SM: detected_sensors_list - SM->>SM: updateSensorRegistry() -``` - -### 2.2 F-DQC-002: Sensor Type Enforcement - -**Description:** Enforcement of sensor-slot compatibility to prevent incorrect sensor installation and configuration errors. - -**Enforcement Mechanisms:** -- **Physical Slot Design:** Mechanical keying for sensor types -- **Electrical Validation:** Pin configuration verification -- **Software Validation:** Machine constants cross-reference -- **Protocol Validation:** Communication interface verification - -**Slot Mapping Table:** -| Slot ID | Sensor Type | Interface | Detection Pin | Validation Method | -|---------|-------------|-----------|---------------|-------------------| -| SLOT_01 | Temperature | I2C/Analog | GPIO_12 | Device ID + Range | -| SLOT_02 | Humidity | I2C | GPIO_13 | Device ID + Protocol | -| SLOT_03 | CO2 | UART/I2C | GPIO_14 | Device ID + Calibration | -| SLOT_04 | NH3 | Analog/I2C | GPIO_15 | Range + Sensitivity | -| SLOT_05 | VOC | I2C | GPIO_16 | Device ID + Algorithm | -| SLOT_06 | PM | UART/I2C | GPIO_17 | Protocol + Range | -| SLOT_07 | Light | Analog/I2C | GPIO_18 | Range + Spectral | - -### 2.3 F-DQC-003: Sensor Failure Detection - -**Description:** Continuous monitoring of sensor behavior to detect and isolate failures in real-time. - -**Failure Detection Methods:** -- **Communication Timeouts:** I2C/UART/SPI response monitoring -- **Range Validation:** Out-of-specification value detection -- **Trend Analysis:** Abnormal rate-of-change detection -- **Cross-Validation:** Multi-sensor consistency checking -- **Health Monitoring:** Sensor self-diagnostic features - -**Failure Classification:** -```c -typedef enum { - SENSOR_FAILURE_NONE = 0, - SENSOR_FAILURE_COMMUNICATION, // Timeout, NACK, protocol error - SENSOR_FAILURE_OUT_OF_RANGE, // Values outside physical limits - SENSOR_FAILURE_STUCK_VALUE, // No change over time - SENSOR_FAILURE_ERRATIC, // Excessive noise or variation - SENSOR_FAILURE_CALIBRATION, // Drift beyond acceptable limits - SENSOR_FAILURE_HARDWARE, // Self-diagnostic failure - SENSOR_FAILURE_UNKNOWN // Unclassified failure -} sensor_failure_type_t; -``` - -### 2.4 F-DQC-004: Machine Constants & Calibration Management - -**Description:** Centralized management of sensor configuration, calibration parameters, and system identity information. - -**Machine Constants Structure:** -```c -typedef struct { - // System Identity - char device_id[32]; - char site_id[16]; - char house_id[16]; - uint32_t firmware_version; - - // Sensor Configuration - sensor_config_t sensors[MAX_SENSORS]; - - // Calibration Parameters - calibration_params_t calibration[MAX_SENSORS]; - - // Communication Settings - comm_config_t communication; - - // System Limits - system_limits_t limits; - - // Validation - uint32_t checksum; - uint64_t timestamp; -} machine_constants_t; - -typedef struct { - uint8_t sensor_id; - sensor_type_t type; - bool enabled; - uint32_t sampling_rate; - filter_config_t filter; - float min_value, max_value; - char unit[8]; -} sensor_config_t; - -typedef struct { - float offset; - float scale; - float[] polynomial_coeffs; - uint8_t coeff_count; - uint64_t calibration_date; - uint32_t calibration_interval; -} calibration_params_t; -``` - -### 2.5 F-DQC-005: Redundant Sensor Support - -**Description:** Support for redundant sensors and sensor fusion for critical measurements. - -**Redundancy Strategies:** -- **Dual Sensors:** Two sensors of same type for critical parameters -- **Cross-Validation:** Different sensor types measuring related parameters -- **Voting Logic:** Majority voting for multiple sensors -- **Graceful Degradation:** Fallback to single sensor operation - -**Sensor Fusion Algorithm:** -```mermaid -graph TB - subgraph "Sensor Fusion Process" - S1[Sensor 1] --> V[Validator] - S2[Sensor 2] --> V - S3[Sensor 3] --> V - V --> F[Fusion Algorithm] - F --> O[Output Value] - F --> C[Confidence Level] - end - - subgraph "Fusion Methods" - AVG[Weighted Average] - MED[Median Filter] - KAL[Kalman Filter] - VOT[Voting Logic] - end - - F --> AVG - F --> MED - F --> KAL - F --> VOT -``` - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-DQC-001** | SR-DQC-001, SR-DQC-002 | Automatic sensor detection and enumeration | -| **F-DQC-002** | SR-DQC-003, SR-DQC-004 | Sensor type enforcement and slot validation | -| **F-DQC-003** | SR-DQC-005, SR-DQC-006 | Failure detection and isolation | -| **F-DQC-004** | SR-DQC-007, SR-DQC-008 | Machine constants management and persistence | -| **F-DQC-005** | SR-DQC-009, SR-DQC-010 | Redundant sensor support and fusion | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-DQC-001** | SWR-DQC-001, SWR-DQC-002, SWR-DQC-003 | Detection algorithms, device probing, registry management | -| **F-DQC-002** | SWR-DQC-004, SWR-DQC-005, SWR-DQC-006 | Slot mapping, validation logic, error reporting | -| **F-DQC-003** | SWR-DQC-007, SWR-DQC-008, SWR-DQC-009 | Health monitoring, failure classification, isolation | -| **F-DQC-004** | SWR-DQC-010, SWR-DQC-011, SWR-DQC-012 | MC structure, persistence, update mechanisms | -| **F-DQC-005** | SWR-DQC-013, SWR-DQC-014, SWR-DQC-015 | Fusion algorithms, redundancy management, voting logic | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **Machine Constant Manager** | MC loading, validation, update coordination | `application_layer/business_stack/machine_constant_manager/` | -| **Sensor Manager** | Detection coordination, failure monitoring | `application_layer/business_stack/sensor_manager/` | -| **Device Detector** | Hardware detection, sensor probing | `drivers/device_detector/` | -| **Calibration Manager** | Calibration algorithms, parameter management | `application_layer/calibration/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Sensor Drivers** | Hardware interface, device identification | `drivers/sensors/` | -| **Event System** | Detection events, failure notifications | `application_layer/business_stack/event_system/` | -| **Data Persistence** | MC storage, calibration data persistence | `application_layer/DP_stack/persistence/` | -| **Diagnostics Task** | Failure logging, health reporting | `application_layer/diag_task/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "Data Quality & Calibration Feature" - MCM[Machine Constant Manager] - SM[Sensor Manager] - DD[Device Detector] - CAL[Calibration Manager] - end - - subgraph "Supporting Components" - SD[Sensor Drivers] - ES[Event System] - DP[Data Persistence] - DIAG[Diagnostics Task] - end - - subgraph "Hardware" - SENSORS[Physical Sensors] - GPIO[Detection Pins] - I2C[I2C Bus] - UART[UART Interface] - end - - MCM <--> DP - MCM --> SM - MCM --> CAL - - SM <--> ES - SM --> DD - SM --> DIAG - - DD --> SD - DD --> GPIO - - CAL --> MCM - CAL <--> DP - - SD --> I2C - SD --> UART - SD --> SENSORS - - ES -.->|Detection Events| SM - ES -.->|Failure Events| DIAG - DIAG -.->|Health Data| SM -``` - -### 4.4 Detection and Validation Flow - -```mermaid -sequenceDiagram - participant HW as Hardware - participant DD as Device Detector - participant SD as Sensor Driver - participant SM as Sensor Manager - participant MCM as MC Manager - participant ES as Event System - participant DIAG as Diagnostics - - Note over HW,DIAG: Sensor Detection and Validation - - SM->>DD: initiateSensorScan() - - loop For each sensor slot - DD->>HW: checkPresencePin(slot_id) - HW-->>DD: presence_status - - alt Sensor present - DD->>SD: probeSensorType(slot_id) - SD->>HW: readDeviceID() - HW-->>SD: device_info - SD-->>DD: sensor_type_info - - DD->>MCM: validateSensorSlot(slot_id, sensor_type) - MCM-->>DD: validation_result - - alt Validation successful - DD->>SM: registerSensor(slot_id, sensor_info) - SM->>ES: publish(SENSOR_DETECTED, sensor_info) - else Validation failed - DD->>DIAG: reportValidationError(slot_id, error) - DIAG->>ES: publish(SENSOR_VALIDATION_FAILED, error) - end - end - end - - DD-->>SM: scanComplete(detected_sensors) - SM->>ES: publish(SENSOR_SCAN_COMPLETE, summary) -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **System Initialization:** - - Load machine constants from persistent storage - - Validate MC integrity and version compatibility - - Initialize sensor detection and calibration systems - - Perform initial sensor scan and validation - -2. **Sensor Detection Cycle:** - - Scan all sensor slots for presence - - Identify sensor types and validate compatibility - - Register detected sensors in system registry - - Configure sensors according to machine constants - -3. **Continuous Monitoring:** - - Monitor sensor health and communication status - - Detect failures and classify failure types - - Apply calibration corrections to sensor data - - Manage redundant sensors and sensor fusion - -4. **Configuration Management:** - - Handle machine constants updates from Main Hub - - Validate new configurations before application - - Coordinate system teardown for MC updates - - Persist updated configurations to storage - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **Sensor Mismatch** | Type validation against MC | Reject sensor, log diagnostic event | -| **Communication Failure** | Timeout or protocol error | Mark sensor as faulty, continue with others | -| **Calibration Drift** | Value trend analysis | Flag for recalibration, continue operation | -| **MC Corruption** | Checksum validation | Use backup MC, request update from Main Hub | -| **Detection Hardware Failure** | GPIO or I2C failure | Disable detection, use last known configuration | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Load MC, detect sensors, validate configuration | -| **RUNNING** | Continuous monitoring, failure detection, calibration | -| **WARNING** | Enhanced monitoring, diagnostic reporting | -| **FAULT** | Minimal operation, preserve sensor states | -| **MC_UPDATE** | Stop monitoring, update MC, re-detect sensors | -| **SERVICE** | Full diagnostic access, manual sensor control | -| **SD_DEGRADED** | Continue operation, no MC persistence | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Detection Cycle:** Maximum 5 seconds for complete sensor scan -- **Failure Detection:** Maximum 3 seconds to detect communication failure -- **MC Update:** Maximum 30 seconds for complete MC reload -- **Calibration Application:** Maximum 100ms per sensor - -### 6.2 Resource Constraints - -- **Memory Usage:** Maximum 8KB for MC data and sensor registry -- **Detection Frequency:** Maximum once per minute for presence scan -- **Calibration Storage:** Maximum 1KB per sensor for calibration data -- **Failure History:** Maximum 100 failure events in memory - -### 6.3 Quality Constraints - -- **Detection Accuracy:** 99.9% accurate sensor presence detection -- **Type Validation:** 100% prevention of incorrect sensor installation -- **Failure Detection:** 95% of failures detected within 10 seconds -- **Calibration Accuracy:** Within ±2% of reference standards - -## 7. Interface Specifications - -### 7.1 Machine Constant Manager API - -```c -// Machine constants management -bool mcMgr_initialize(void); -bool mcMgr_loadMachineConstants(machine_constants_t* mc); -bool mcMgr_validateMachineConstants(const machine_constants_t* mc); -bool mcMgr_updateMachineConstants(const machine_constants_t* new_mc); -bool mcMgr_backupMachineConstants(void); - -// Sensor configuration access -bool mcMgr_getSensorConfig(uint8_t sensor_id, sensor_config_t* config); -bool mcMgr_getCalibrationParams(uint8_t sensor_id, calibration_params_t* params); -bool mcMgr_validateSensorSlot(uint8_t slot_id, sensor_type_t sensor_type); - -// System configuration -bool mcMgr_getSystemIdentity(system_identity_t* identity); -bool mcMgr_getCommunicationConfig(comm_config_t* config); -bool mcMgr_getSystemLimits(system_limits_t* limits); -``` - -### 7.2 Device Detector API - -```c -// Detection operations -bool detector_initialize(void); -bool detector_scanSensors(detected_sensor_t* sensors, size_t* count); -bool detector_probeSensorType(uint8_t slot_id, sensor_type_info_t* info); -bool detector_validateSensorPresence(uint8_t slot_id); - -// Hardware interface -bool detector_checkPresencePin(uint8_t slot_id); -bool detector_readDeviceID(uint8_t slot_id, device_id_t* id); -bool detector_testCommunication(uint8_t slot_id, comm_interface_t interface); -``` - -### 7.3 Calibration Manager API - -```c -// Calibration operations -bool cal_initialize(void); -bool cal_applyCalibratio(uint8_t sensor_id, float raw_value, float* calibrated_value); -bool cal_updateCalibrationParams(uint8_t sensor_id, const calibration_params_t* params); -bool cal_validateCalibration(uint8_t sensor_id, validation_result_t* result); - -// Calibration management -bool cal_scheduleRecalibration(uint8_t sensor_id, uint32_t interval_days); -bool cal_isCalibrationExpired(uint8_t sensor_id); -bool cal_getCalibrationStatus(uint8_t sensor_id, calibration_status_t* status); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Detection Logic:** Mock hardware for detection algorithm testing -- **Validation Rules:** Sensor-slot compatibility matrix testing -- **Calibration Math:** Known input/output calibration validation -- **MC Management:** Configuration loading and validation testing - -### 8.2 Integration Testing - -- **Hardware Detection:** Real sensor hardware detection testing -- **Communication Interfaces:** I2C, UART, SPI sensor communication -- **Event Integration:** Detection and failure event publication -- **Persistence Integration:** MC storage and retrieval testing - -### 8.3 System Testing - -- **Multi-Sensor Detection:** All 7 sensor types simultaneously -- **Failure Scenarios:** Sensor disconnection and failure injection -- **MC Update Testing:** Complete configuration update scenarios -- **Long-Duration Testing:** 48-hour continuous monitoring - -### 8.4 Acceptance Criteria - -- All supported sensor types correctly detected and identified -- 100% prevention of incorrect sensor-slot configurations -- Failure detection within specified timing constraints -- Machine constants updates complete without data loss -- Calibration accuracy within specified tolerances -- No false positive or negative detection events - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **Sensor Manager:** Sensor lifecycle and state management -- **Event System:** Detection and failure event communication -- **Data Persistence:** Machine constants and calibration storage -- **Diagnostics Task:** Failure logging and health reporting - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** GPIO, I2C, UART, SPI drivers -- **Hardware Sensors:** Physical sensor devices and interfaces -- **Detection Hardware:** Presence pins and identification circuits -- **Main Hub:** Machine constants updates and calibration data - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **AI-Based Detection:** Machine learning for sensor identification -- **Predictive Calibration:** Drift prediction and automatic correction -- **Advanced Fusion:** Multi-sensor data fusion algorithms -- **Remote Calibration:** Over-the-air calibration updates - -### 10.2 Scalability Considerations - -- **Additional Sensor Types:** Framework supports easy extension -- **Enhanced Validation:** Multi-level validation mechanisms -- **Cloud Calibration:** Cloud-based calibration management -- **Sensor Networks:** Cross-hub sensor validation and fusion - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-DQC, SWR-DQC) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-HW_Hardware_Abstraction.md b/draft- to be removed SW/features/F-HW_Hardware_Abstraction.md deleted file mode 100644 index f888938..0000000 --- a/draft- to be removed SW/features/F-HW_Hardware_Abstraction.md +++ /dev/null @@ -1,650 +0,0 @@ -# Feature Specification: Hardware Abstraction -# Feature ID: F-HW (F-HW-001 to F-HW-002) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Hardware Abstraction - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Hardware Abstraction feature provides a clean separation between application logic and hardware interfaces for the ASF Sensor Hub. This feature ensures hardware independence, maintainability, and testability by abstracting all hardware access through well-defined interfaces and preventing direct hardware access from the application layer. - -### 1.2 Feature Scope - -**In Scope:** -- Sensor Abstraction Layer (SAL) for uniform sensor access -- Hardware interface abstraction for I2C, SPI, UART, ADC, GPIO -- Storage interface abstraction for SD Card and NVM -- Display and user interface abstraction -- GPIO discipline enforcement and resource conflict detection - -**Out of Scope:** -- Hardware driver implementation details (delegated to ESP-IDF) -- Hardware-specific performance optimizations -- Physical hardware design and pin assignments -- Low-level hardware debugging interfaces - -## 2. Sub-Features - -### 2.1 F-HW-001: Sensor Abstraction Layer (SAL) - -**Description:** Comprehensive sensor abstraction layer providing uniform access to all sensor types while maintaining hardware independence and enabling runtime sensor management. - -**Sensor Abstraction Interface:** -```c -typedef struct { - uint8_t sensor_id; // Unique sensor identifier - sensor_type_t type; // Sensor type enumeration - char name[32]; // Human-readable sensor name - char unit[8]; // Measurement unit (°C, %, ppm, etc.) - float min_value; // Minimum valid measurement - float max_value; // Maximum valid measurement - float accuracy; // Sensor accuracy specification - uint32_t warmup_time_ms; // Required warmup time - uint32_t sampling_interval_ms; // Minimum sampling interval - sensor_interface_t interface; // Hardware interface type -} sensor_metadata_t; - -typedef enum { - SENSOR_TYPE_TEMPERATURE = 0, // Temperature sensors - SENSOR_TYPE_HUMIDITY = 1, // Humidity sensors - SENSOR_TYPE_CO2 = 2, // Carbon dioxide sensors - SENSOR_TYPE_AMMONIA = 3, // Ammonia sensors - SENSOR_TYPE_VOC = 4, // Volatile organic compounds - SENSOR_TYPE_LIGHT = 5, // Light intensity sensors - SENSOR_TYPE_PARTICULATE = 6 // Particulate matter sensors -} sensor_type_t; - -typedef enum { - SENSOR_INTERFACE_I2C = 0, // I2C interface - SENSOR_INTERFACE_SPI = 1, // SPI interface - SENSOR_INTERFACE_UART = 2, // UART interface - SENSOR_INTERFACE_ADC = 3, // Analog ADC interface - SENSOR_INTERFACE_GPIO = 4 // Digital GPIO interface -} sensor_interface_t; -``` - -**Sensor State Management:** -```c -typedef enum { - SENSOR_STATE_UNKNOWN = 0, // Initial state, not detected - SENSOR_STATE_DETECTED = 1, // Presence confirmed - SENSOR_STATE_INITIALIZED = 2, // Driver loaded and configured - SENSOR_STATE_WARMUP = 3, // Warming up, not stable - SENSOR_STATE_STABLE = 4, // Operational and stable - SENSOR_STATE_ENABLED = 5, // Active data acquisition - SENSOR_STATE_DISABLED = 6, // Present but not acquiring - SENSOR_STATE_DEGRADED = 7, // Operational but degraded - SENSOR_STATE_FAULTY = 8, // Detected failure condition - SENSOR_STATE_REMOVED = 9 // Previously present, now absent -} sensor_state_t; - -typedef struct { - sensor_state_t current_state; // Current sensor state - sensor_state_t previous_state; // Previous sensor state - uint64_t state_change_time; // Last state change timestamp - uint32_t state_change_count; // Total state changes - uint32_t fault_count; // Number of faults detected - uint32_t recovery_count; // Number of successful recoveries - float last_valid_reading; // Last known good reading - uint64_t last_reading_time; // Timestamp of last reading -} sensor_state_info_t; -``` - -**Sensor State Machine:** -```mermaid -stateDiagram-v2 - [*] --> UNKNOWN - UNKNOWN --> DETECTED : Presence detected - DETECTED --> INITIALIZED : Driver loaded - INITIALIZED --> WARMUP : Acquisition started - WARMUP --> STABLE : Warmup complete - STABLE --> ENABLED : Enable command - ENABLED --> DISABLED : Disable command - DISABLED --> ENABLED : Enable command - ENABLED --> DEGRADED : Performance degradation - DEGRADED --> ENABLED : Performance restored - ENABLED --> FAULTY : Failure detected - DEGRADED --> FAULTY : Failure detected - FAULTY --> ENABLED : Recovery successful - FAULTY --> REMOVED : Hardware removed - ENABLED --> REMOVED : Hardware removed - DISABLED --> REMOVED : Hardware removed - DEGRADED --> REMOVED : Hardware removed - REMOVED --> DETECTED : Hardware restored -``` - -**Uniform Sensor API:** -```c -// Sensor lifecycle management -bool sal_initializeSensor(uint8_t sensor_id); -bool sal_enableSensor(uint8_t sensor_id); -bool sal_disableSensor(uint8_t sensor_id); -bool sal_resetSensor(uint8_t sensor_id); - -// Sensor data operations -bool sal_readSensor(uint8_t sensor_id, float* value); -bool sal_calibrateSensor(uint8_t sensor_id, const calibration_data_t* cal_data); -bool sal_validateReading(uint8_t sensor_id, float value); -bool sal_performHealthCheck(uint8_t sensor_id); - -// Sensor information and status -bool sal_getSensorMetadata(uint8_t sensor_id, sensor_metadata_t* metadata); -sensor_state_t sal_getSensorState(uint8_t sensor_id); -bool sal_getSensorStateInfo(uint8_t sensor_id, sensor_state_info_t* info); -bool sal_isSensorPresent(uint8_t sensor_id); -bool sal_isSensorHealthy(uint8_t sensor_id); -``` - -**Sensor Driver Interface:** -```c -typedef struct { - // Driver identification - char driver_name[32]; // Driver name - char driver_version[16]; // Driver version - sensor_type_t supported_type; // Supported sensor type - - // Driver operations - bool (*initialize)(uint8_t sensor_id); - bool (*read_raw)(uint8_t sensor_id, uint32_t* raw_value); - bool (*convert_value)(uint32_t raw_value, float* converted_value); - bool (*calibrate)(uint8_t sensor_id, const calibration_data_t* cal_data); - bool (*health_check)(uint8_t sensor_id); - bool (*reset)(uint8_t sensor_id); - - // Driver configuration - sensor_metadata_t metadata; // Sensor metadata - void* driver_config; // Driver-specific configuration -} sensor_driver_interface_t; -``` - -### 2.2 F-HW-002: Hardware Interface Abstraction - -**Description:** Comprehensive abstraction of all hardware interfaces to prevent direct hardware access from the application layer and ensure consistent interface usage across the system. - -**GPIO Discipline and Management:** -```c -typedef struct { - uint8_t gpio_number; // Physical GPIO pin number - gpio_function_t function; // Assigned function - gpio_direction_t direction; // Input/Output direction - gpio_pull_t pull_config; // Pull-up/Pull-down configuration - bool is_strapping_pin; // Strapping pin flag - bool is_reserved; // Reserved for system use - char assigned_component[32]; // Component using this GPIO -} gpio_pin_config_t; - -typedef enum { - GPIO_FUNC_UNUSED = 0, // Pin not used - GPIO_FUNC_I2C_SDA = 1, // I2C data line - GPIO_FUNC_I2C_SCL = 2, // I2C clock line - GPIO_FUNC_SPI_MOSI = 3, // SPI master out, slave in - GPIO_FUNC_SPI_MISO = 4, // SPI master in, slave out - GPIO_FUNC_SPI_CLK = 5, // SPI clock - GPIO_FUNC_SPI_CS = 6, // SPI chip select - GPIO_FUNC_UART_TX = 7, // UART transmit - GPIO_FUNC_UART_RX = 8, // UART receive - GPIO_FUNC_ADC_INPUT = 9, // ADC analog input - GPIO_FUNC_DIGITAL_INPUT = 10, // Digital input - GPIO_FUNC_DIGITAL_OUTPUT = 11, // Digital output - GPIO_FUNC_PWM_OUTPUT = 12 // PWM output -} gpio_function_t; - -// Strapping pins that must be avoided for general-purpose I/O -#define GPIO_STRAPPING_PINS {0, 3, 45, 46} -``` - -**I2C Interface Abstraction:** -```c -typedef struct { - uint8_t i2c_port; // I2C port number (0 or 1) - uint8_t sda_pin; // SDA pin assignment - uint8_t scl_pin; // SCL pin assignment - uint32_t frequency_hz; // I2C frequency (100kHz, 400kHz) - bool pullup_enabled; // Internal pull-up enable - uint32_t timeout_ms; // Transaction timeout -} i2c_config_t; - -// I2C abstraction API -bool hw_i2c_initialize(uint8_t port, const i2c_config_t* config); -bool hw_i2c_write(uint8_t port, uint8_t device_addr, const uint8_t* data, size_t len); -bool hw_i2c_read(uint8_t port, uint8_t device_addr, uint8_t* data, size_t len); -bool hw_i2c_write_read(uint8_t port, uint8_t device_addr, - const uint8_t* write_data, size_t write_len, - uint8_t* read_data, size_t read_len); -bool hw_i2c_scan_devices(uint8_t port, uint8_t* found_devices, size_t* count); -``` - -**SPI Interface Abstraction:** -```c -typedef struct { - uint8_t spi_host; // SPI host (SPI2_HOST, SPI3_HOST) - uint8_t mosi_pin; // MOSI pin assignment - uint8_t miso_pin; // MISO pin assignment - uint8_t sclk_pin; // Clock pin assignment - uint8_t cs_pin; // Chip select pin - uint32_t frequency_hz; // SPI frequency - uint8_t mode; // SPI mode (0-3) - uint8_t bit_order; // MSB/LSB first -} spi_config_t; - -// SPI abstraction API -bool hw_spi_initialize(uint8_t host, const spi_config_t* config); -bool hw_spi_transmit(uint8_t host, const uint8_t* tx_data, size_t len); -bool hw_spi_receive(uint8_t host, uint8_t* rx_data, size_t len); -bool hw_spi_transmit_receive(uint8_t host, const uint8_t* tx_data, - uint8_t* rx_data, size_t len); -``` - -**ADC Interface Abstraction:** -```c -typedef struct { - adc_unit_t adc_unit; // ADC1 or ADC2 (ADC1 only when Wi-Fi active) - adc_channel_t channel; // ADC channel - adc_atten_t attenuation; // Input attenuation - adc_bitwidth_t resolution; // ADC resolution - uint32_t sample_count; // Samples for averaging -} adc_config_t; - -// ADC abstraction API -bool hw_adc_initialize(const adc_config_t* config); -bool hw_adc_read_raw(adc_unit_t unit, adc_channel_t channel, uint32_t* raw_value); -bool hw_adc_read_voltage(adc_unit_t unit, adc_channel_t channel, float* voltage); -bool hw_adc_calibrate(adc_unit_t unit, adc_channel_t channel); -``` - -**Storage Interface Abstraction:** -```c -// SD Card abstraction -typedef struct { - uint8_t mosi_pin; // SD card MOSI pin - uint8_t miso_pin; // SD card MISO pin - uint8_t clk_pin; // SD card clock pin - uint8_t cs_pin; // SD card chip select pin - uint32_t frequency_hz; // SD card SPI frequency - bool format_if_mount_failed; // Auto-format on mount failure -} sd_card_config_t; - -bool hw_sd_initialize(const sd_card_config_t* config); -bool hw_sd_mount(const char* mount_point); -bool hw_sd_unmount(void); -bool hw_sd_get_info(sd_card_info_t* info); - -// NVM (NVS) abstraction -bool hw_nvs_initialize(void); -bool hw_nvs_write_blob(const char* namespace, const char* key, - const void* data, size_t size); -bool hw_nvs_read_blob(const char* namespace, const char* key, - void* data, size_t* size); -bool hw_nvs_erase_key(const char* namespace, const char* key); -bool hw_nvs_get_stats(nvs_stats_t* stats); -``` - -**GPIO Map Management:** -```c -typedef struct { - gpio_pin_config_t pins[GPIO_NUM_MAX]; // All GPIO pin configurations - uint32_t used_pin_count; // Number of used pins - uint32_t conflict_count; // Number of detected conflicts - bool map_validated; // GPIO map validation status -} gpio_map_t; - -// GPIO map management API -bool hw_gpio_initialize_map(void); -bool hw_gpio_reserve_pin(uint8_t gpio_num, gpio_function_t function, - const char* component_name); -bool hw_gpio_release_pin(uint8_t gpio_num); -bool hw_gpio_validate_map(void); -bool hw_gpio_detect_conflicts(gpio_conflict_t* conflicts, size_t* count); -bool hw_gpio_get_map(gpio_map_t* map); -``` - -**Hardware Resource Conflict Detection:** -```c -typedef enum { - HW_CONFLICT_GPIO_DUPLICATE = 0, // Same GPIO used by multiple components - HW_CONFLICT_I2C_ADDRESS = 1, // I2C address conflict - HW_CONFLICT_SPI_CS = 2, // SPI chip select conflict - HW_CONFLICT_ADC_WIFI = 3, // ADC2 used with Wi-Fi active - HW_CONFLICT_STRAPPING_PIN = 4, // Strapping pin used for I/O - HW_CONFLICT_POWER_DOMAIN = 5 // Power domain conflict -} hw_conflict_type_t; - -typedef struct { - hw_conflict_type_t type; // Conflict type - uint8_t resource_id; // Conflicting resource ID - char component1[32]; // First component involved - char component2[32]; // Second component involved - char description[128]; // Human-readable description -} hw_conflict_t; -``` - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-HW-001** | SR-HW-001, SR-HW-002, SR-HW-003, SR-HW-004 | Sensor abstraction layer and state management | -| **F-HW-002** | SR-HW-005, SR-HW-006, SR-HW-007, SR-HW-008 | Hardware interface abstraction and GPIO discipline | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-HW-001** | SWR-HW-001, SWR-HW-002, SWR-HW-003 | SAL interface, sensor drivers, state machine | -| **F-HW-002** | SWR-HW-004, SWR-HW-005, SWR-HW-006 | Interface abstraction, GPIO management, conflict detection | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **Sensor Abstraction Layer** | Uniform sensor interface, state management | `drivers/sensor_abstraction/` | -| **Hardware Interface Manager** | Interface abstraction, resource management | `drivers/hw_interface_mgr/` | -| **GPIO Manager** | GPIO discipline, conflict detection | `drivers/gpio_manager/` | -| **Sensor Drivers** | Hardware-specific sensor implementations | `drivers/sensors/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **ESP-IDF Wrappers** | Low-level hardware access | `ESP_IDF_FW_wrappers/` | -| **Diagnostics** | Hardware fault reporting | `application_layer/diag_task/` | -| **Machine Constant Manager** | Hardware configuration management | `application_layer/business_stack/machine_constant_manager/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "Hardware Abstraction Feature" - SAL[Sensor Abstraction Layer] - HW_MGR[Hardware Interface Manager] - GPIO_MGR[GPIO Manager] - SENSOR_DRV[Sensor Drivers] - end - - subgraph "Application Layer" - SENSOR_MGR[Sensor Manager] - PERSIST[Persistence] - DIAG[Diagnostics] - end - - subgraph "ESP-IDF Wrappers" - I2C_WRAP[I2C Wrapper] - SPI_WRAP[SPI Wrapper] - UART_WRAP[UART Wrapper] - ADC_WRAP[ADC Wrapper] - GPIO_WRAP[GPIO Wrapper] - end - - subgraph "Physical Hardware" - SENSORS[Physical Sensors] - SD_CARD[SD Card] - OLED[OLED Display] - BUTTONS[Buttons] - end - - SENSOR_MGR --> SAL - SAL --> SENSOR_DRV - SENSOR_DRV --> HW_MGR - - HW_MGR --> I2C_WRAP - HW_MGR --> SPI_WRAP - HW_MGR --> UART_WRAP - HW_MGR --> ADC_WRAP - - GPIO_MGR --> GPIO_WRAP - - I2C_WRAP --> SENSORS - SPI_WRAP --> SD_CARD - UART_WRAP --> SENSORS - ADC_WRAP --> SENSORS - GPIO_WRAP --> BUTTONS - GPIO_WRAP --> OLED - - SAL -.->|Hardware Events| DIAG - HW_MGR -.->|Resource Conflicts| DIAG -``` - -### 4.4 Sensor Abstraction Flow - -```mermaid -sequenceDiagram - participant APP as Application - participant SAL as Sensor Abstraction Layer - participant DRV as Sensor Driver - participant HW as Hardware Interface - participant SENSOR as Physical Sensor - - Note over APP,SENSOR: Sensor Access Through Abstraction - - APP->>SAL: sal_readSensor(sensor_id) - SAL->>SAL: validateSensorState(sensor_id) - - alt Sensor State Valid - SAL->>DRV: driver_read_raw(sensor_id) - DRV->>HW: hw_i2c_read(port, addr, data) - HW->>SENSOR: I2C transaction - SENSOR-->>HW: sensor_data - HW-->>DRV: raw_value - DRV->>DRV: convert_value(raw_value) - DRV-->>SAL: converted_value - SAL->>SAL: validateReading(converted_value) - SAL-->>APP: sensor_reading - else Sensor State Invalid - SAL->>SAL: attemptSensorRecovery(sensor_id) - SAL-->>APP: error_sensor_not_ready - end -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **System Initialization:** - - Initialize GPIO map and validate pin assignments - - Detect hardware resource conflicts and report violations - - Initialize hardware interface abstractions (I2C, SPI, UART, ADC) - - Scan for connected sensors and initialize sensor drivers - - Establish sensor abstraction layer and state management - -2. **Sensor Management:** - - Maintain sensor state machine for all detected sensors - - Provide uniform access interface regardless of hardware interface - - Handle sensor failures and recovery attempts - - Monitor sensor health and performance metrics - -3. **Hardware Interface Management:** - - Enforce GPIO discipline and prevent strapping pin usage - - Manage shared resources and prevent conflicts - - Provide consistent interface abstraction across all hardware types - - Monitor interface health and detect hardware failures - -4. **Resource Conflict Prevention:** - - Validate GPIO assignments during initialization - - Detect and report hardware resource conflicts - - Enforce ADC1/ADC2 separation when Wi-Fi is active - - Maintain canonical GPIO map as single source of truth - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **GPIO Conflict** | Pin assignment validation | Report conflict, prevent initialization | -| **Sensor Communication Failure** | Interface timeout/error | Mark sensor as faulty, attempt recovery | -| **Hardware Interface Failure** | Transaction failure | Report hardware fault, disable interface | -| **Strapping Pin Usage** | GPIO map validation | Prevent usage, report configuration error | -| **ADC2/Wi-Fi Conflict** | Resource validation | Force ADC1 usage, report conflict | -| **I2C Address Conflict** | Device scanning | Report conflict, disable conflicting devices | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Initialize hardware abstractions, detect sensors | -| **RUNNING** | Full hardware abstraction, continuous sensor monitoring | -| **WARNING** | Enhanced hardware monitoring, sensor health checks | -| **FAULT** | Critical hardware functions only, preserve sensor states | -| **OTA_UPDATE** | Maintain hardware state, suspend sensor operations | -| **TEARDOWN** | Graceful hardware shutdown, preserve configurations | -| **SERVICE** | Limited hardware access for diagnostics | -| **SD_DEGRADED** | Continue sensor operations, report storage degradation | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Sensor State Transitions:** Maximum 100ms for state changes -- **Hardware Interface Operations:** Bounded timeouts for all transactions -- **GPIO Conflict Detection:** Complete during system initialization -- **Sensor Recovery Attempts:** Maximum 3 attempts with exponential backoff - -### 6.2 Resource Constraints - -- **GPIO Usage:** Enforce strapping pin restrictions and conflict prevention -- **I2C Pull-ups:** Physical pull-ups required (2.2kΩ - 4.7kΩ for 3.3V) -- **ADC Constraints:** ADC1 only when Wi-Fi active, ADC2 when Wi-Fi inactive -- **Memory Usage:** Maximum 32KB for abstraction layer buffers and state - -### 6.3 Hardware Constraints - -- **ESP32-S3 Limitations:** Respect hardware capabilities and restrictions -- **Interface Speeds:** I2C up to 400kHz, SPI up to 80MHz -- **Voltage Levels:** 3.3V logic levels for all interfaces -- **Current Limitations:** Respect GPIO current drive capabilities - -## 7. Interface Specifications - -### 7.1 Sensor Abstraction Layer API - -```c -// SAL initialization and management -bool sal_initialize(void); -bool sal_detectSensors(void); -bool sal_getSensorCount(uint8_t* count); -bool sal_getSensorList(uint8_t* sensor_ids, size_t* count); - -// Sensor operations -bool sal_readSensor(uint8_t sensor_id, float* value); -bool sal_readMultipleSensors(uint8_t* sensor_ids, size_t count, - sensor_reading_t* readings); -bool sal_calibrateSensor(uint8_t sensor_id, const calibration_data_t* cal_data); -bool sal_resetSensor(uint8_t sensor_id); - -// Sensor state and health -sensor_state_t sal_getSensorState(uint8_t sensor_id); -bool sal_getSensorHealth(uint8_t sensor_id, sensor_health_t* health); -bool sal_performSensorDiagnostics(uint8_t sensor_id, sensor_diagnostics_t* diag); -``` - -### 7.2 Hardware Interface Manager API - -```c -// Interface initialization -bool hwMgr_initialize(void); -bool hwMgr_initializeI2C(uint8_t port, const i2c_config_t* config); -bool hwMgr_initializeSPI(uint8_t host, const spi_config_t* config); -bool hwMgr_initializeUART(uint8_t port, const uart_config_t* config); -bool hwMgr_initializeADC(const adc_config_t* config); - -// Resource management -bool hwMgr_reserveResource(hw_resource_type_t type, uint8_t resource_id, - const char* component_name); -bool hwMgr_releaseResource(hw_resource_type_t type, uint8_t resource_id); -bool hwMgr_validateResources(void); -bool hwMgr_getResourceConflicts(hw_conflict_t* conflicts, size_t* count); -``` - -### 7.3 GPIO Manager API - -```c -// GPIO management -bool gpioMgr_initialize(void); -bool gpioMgr_reservePin(uint8_t gpio_num, gpio_function_t function, - const char* component_name); -bool gpioMgr_releasePin(uint8_t gpio_num); -bool gpioMgr_configurePin(uint8_t gpio_num, const gpio_config_t* config); - -// GPIO validation and conflict detection -bool gpioMgr_validateGPIOMap(void); -bool gpioMgr_isStrappingPin(uint8_t gpio_num); -bool gpioMgr_detectConflicts(gpio_conflict_t* conflicts, size_t* count); -bool gpioMgr_getGPIOMap(gpio_map_t* map); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Sensor Abstraction:** All sensor types and state transitions -- **Interface Abstraction:** I2C, SPI, UART, ADC operations -- **GPIO Management:** Pin assignment and conflict detection -- **Resource Management:** Resource allocation and validation - -### 8.2 Integration Testing - -- **Cross-Interface Testing:** Multiple interfaces operating simultaneously -- **Sensor Integration:** All sensor types through abstraction layer -- **Resource Conflict Testing:** Deliberate conflict scenarios -- **State Coordination:** Hardware abstraction with system states - -### 8.3 System Testing - -- **Hardware Compatibility:** All supported sensor hardware configurations -- **Performance Testing:** Interface throughput and timing constraints -- **Fault Injection:** Hardware failure simulation and recovery -- **Long-Duration Testing:** Extended operation with hardware monitoring - -### 8.4 Acceptance Criteria - -- All sensor types accessible through uniform SAL interface -- Hardware interfaces properly abstracted from application layer -- GPIO conflicts detected and prevented during initialization -- No direct hardware access from application components -- Sensor state management operates correctly under all conditions -- Hardware resource conflicts properly detected and reported -- Complete hardware abstraction maintains system performance - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **Sensor Manager:** Primary consumer of sensor abstraction layer -- **Diagnostics:** Hardware fault reporting and event logging -- **Machine Constant Manager:** Hardware configuration management -- **State Manager:** Hardware behavior coordination across system states - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** Low-level hardware drivers and HAL -- **Hardware Components:** Physical sensors, interfaces, and peripherals -- **FreeRTOS:** Task coordination and resource management -- **Hardware Design:** GPIO assignments and interface configurations - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Dynamic Sensor Discovery:** Runtime sensor detection and configuration -- **Advanced Sensor Fusion:** Multi-sensor data correlation and validation -- **Hardware Health Monitoring:** Predictive hardware failure detection -- **Plug-and-Play Support:** Hot-swappable sensor support - -### 10.2 Scalability Considerations - -- **Additional Sensor Types:** Framework supports easy sensor type extension -- **Multiple Interface Support:** Support for additional hardware interfaces -- **Advanced GPIO Management:** Dynamic GPIO allocation and optimization -- **Hardware Virtualization:** Virtual hardware interfaces for testing - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-HW, SWR-HW) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-OTA_Firmware_Update.md b/draft- to be removed SW/features/F-OTA_Firmware_Update.md deleted file mode 100644 index f0b65f2..0000000 --- a/draft- to be removed SW/features/F-OTA_Firmware_Update.md +++ /dev/null @@ -1,749 +0,0 @@ -# Feature Specification: Firmware Update (OTA) -# Feature ID: F-OTA (F-OTA-001 to F-OTA-005) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Firmware Update (OTA) - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Firmware Update (OTA) feature provides secure, reliable over-the-air firmware update capabilities for the ASF Sensor Hub. This feature enables controlled firmware lifecycle management, ensuring system availability, data integrity, and fault containment during firmware update operations. - -### 1.2 Feature Scope - -**In Scope:** -- OTA negotiation and readiness validation with Main Hub -- Secure firmware reception over encrypted communication channels -- Firmware integrity validation using cryptographic verification -- Safe firmware activation with A/B partitioning and automatic rollback -- Controlled system teardown and data preservation during updates - -**Out of Scope:** -- Firmware generation and cryptographic signing infrastructure -- Cloud-side firmware distribution and management -- Main Hub OTA coordination logic -- Hardware-level secure boot implementation (dependency) - -## 2. Sub-Features - -### 2.1 F-OTA-001: OTA Update Negotiation - -**Description:** Comprehensive negotiation phase between Sensor Hub and Main Hub to establish OTA readiness and coordinate update initiation. - -**Readiness Validation Criteria:** -```c -typedef struct { - system_state_t current_state; // Must be RUNNING - bool power_stable; // Power supply stable - bool storage_available; // SD card accessible with sufficient space - bool communication_stable; // Network connection stable - uint32_t free_sd_space_mb; // Available SD card space - uint32_t free_nvs_entries; // Available NVS entries - float supply_voltage; // Current supply voltage - uint32_t uptime_seconds; // System uptime for stability -} ota_readiness_t; - -typedef enum { - OTA_READY_ACCEPT = 0, // System ready for OTA - OTA_READY_REJECT_STATE = 1, // Invalid system state - OTA_READY_REJECT_POWER = 2, // Power instability - OTA_READY_REJECT_STORAGE = 3, // Storage unavailable - OTA_READY_REJECT_COMM = 4, // Communication unstable - OTA_READY_REJECT_RESOURCES = 5 // Insufficient resources -} ota_readiness_result_t; -``` - -**Negotiation Sequence:** -```mermaid -sequenceDiagram - participant MH as Main Hub - participant API as Main Hub APIs - participant OTA as OTA Manager - participant STM as State Manager - participant DIAG as Diagnostics - - MH->>API: OTA_AVAILABILITY_NOTIFICATION - API->>OTA: otaAvailabilityReceived(metadata) - OTA->>OTA: validateSystemReadiness() - - alt System Ready - OTA->>STM: requestStateTransition(OTA_PREP) - STM->>STM: validateTransition() - STM-->>OTA: transitionAccepted() - OTA->>API: otaResponse(ACCEPT, readiness_info) - API->>MH: OTA_NEGOTIATION_RESPONSE(ACCEPT) - else System Not Ready - OTA->>DIAG: logDiagnosticEvent(OTA_REJECTED, reason) - OTA->>API: otaResponse(REJECT, rejection_reason) - API->>MH: OTA_NEGOTIATION_RESPONSE(REJECT) - end -``` - -**Readiness Validation Logic:** -- **System State Check:** Must be in RUNNING state (not WARNING/FAULT/SERVICE/SD_DEGRADED) -- **Power Stability:** Supply voltage within 3.0V-3.6V range for >30 seconds -- **Storage Availability:** SD card accessible with >100MB free space -- **Communication Stability:** Network connection stable for >60 seconds -- **Resource Availability:** Sufficient NVS entries and heap memory - -### 2.2 F-OTA-002: Firmware Reception and Storage - -**Description:** Secure reception of firmware image from Main Hub with chunked download, progress monitoring, and temporary storage management. - -**Download Configuration:** -```c -typedef struct { - uint32_t chunk_size; // 4096 bytes (optimized for flash page) - uint32_t total_size; // Total firmware size - uint32_t total_chunks; // Number of chunks - char firmware_version[32]; // Target firmware version - uint8_t sha256_hash[32]; // Expected SHA-256 hash - uint32_t timeout_seconds; // Download timeout (600 seconds) -} ota_download_config_t; - -typedef struct { - uint32_t chunks_received; // Number of chunks received - uint32_t bytes_received; // Total bytes received - uint32_t chunks_failed; // Failed chunk count - uint32_t retries_performed; // Retry attempts - uint64_t start_time_ms; // Download start timestamp - uint64_t last_chunk_time_ms; // Last chunk received timestamp - ota_download_state_t state; // Current download state -} ota_download_progress_t; - -typedef enum { - OTA_DOWNLOAD_IDLE = 0, - OTA_DOWNLOAD_ACTIVE = 1, - OTA_DOWNLOAD_PAUSED = 2, - OTA_DOWNLOAD_COMPLETE = 3, - OTA_DOWNLOAD_FAILED = 4, - OTA_DOWNLOAD_TIMEOUT = 5 -} ota_download_state_t; -``` - -**Storage Management:** -- **Temporary Storage:** SD card path `/ota/firmware_temp.bin` -- **Chunk Verification:** Per-chunk CRC32 validation -- **Progress Persistence:** Download state persisted to NVS for recovery -- **Timeout Handling:** 10-minute maximum download duration -- **Retry Logic:** Up to 3 retries per failed chunk - -**Download Flow:** -```mermaid -sequenceDiagram - participant MH as Main Hub - participant NET as Network Stack - participant OTA as OTA Manager - participant SD as SD Card Storage - participant NVS as NVS Storage - - Note over MH,NVS: Firmware Download Phase - - MH->>NET: firmwareChunk(chunk_id, data, crc32) - NET->>OTA: chunkReceived(chunk_id, data, crc32) - OTA->>OTA: validateChunkCRC(data, crc32) - - alt CRC Valid - OTA->>SD: writeChunk(chunk_id, data) - SD-->>OTA: writeComplete() - OTA->>NVS: updateProgress(chunks_received++) - OTA->>NET: chunkAck(chunk_id, SUCCESS) - NET->>MH: CHUNK_ACK(chunk_id, SUCCESS) - else CRC Invalid - OTA->>NET: chunkAck(chunk_id, RETRY) - NET->>MH: CHUNK_ACK(chunk_id, RETRY) - end - - OTA->>OTA: checkDownloadComplete() - - alt All Chunks Received - OTA->>OTA: transitionToValidation() - end -``` - -### 2.3 F-OTA-003: Firmware Integrity Validation - -**Description:** Comprehensive firmware integrity and authenticity validation using cryptographic verification before activation. - -**Validation Methods:** -```c -typedef struct { - bool size_valid; // Firmware size matches metadata - bool sha256_valid; // SHA-256 hash verification - bool signature_valid; // Digital signature verification (if available) - bool partition_valid; // Partition table validation - bool version_valid; // Version number validation - bool compatibility_valid; // Hardware compatibility check -} ota_validation_result_t; - -typedef enum { - OTA_VALIDATION_PENDING = 0, - OTA_VALIDATION_IN_PROGRESS = 1, - OTA_VALIDATION_SUCCESS = 2, - OTA_VALIDATION_FAILED_SIZE = 3, - OTA_VALIDATION_FAILED_HASH = 4, - OTA_VALIDATION_FAILED_SIGNATURE = 5, - OTA_VALIDATION_FAILED_PARTITION = 6, - OTA_VALIDATION_FAILED_VERSION = 7, - OTA_VALIDATION_FAILED_COMPATIBILITY = 8 -} ota_validation_status_t; -``` - -**Validation Sequence:** -1. **Size Validation:** Verify received firmware size matches metadata -2. **SHA-256 Verification:** Calculate and compare full image hash -3. **Partition Table Validation:** Verify partition structure compatibility -4. **Version Validation:** Ensure version progression (anti-rollback) -5. **Hardware Compatibility:** Verify target platform compatibility - -**Validation Flow:** -```mermaid -sequenceDiagram - participant OTA as OTA Manager - participant SD as SD Card Storage - participant SEC as Security Manager - participant DIAG as Diagnostics - participant API as Main Hub APIs - - Note over OTA,API: Firmware Validation Phase - - OTA->>SD: readFirmwareImage() - SD-->>OTA: firmware_data - - OTA->>OTA: validateSize(firmware_data) - - alt Size Valid - OTA->>SEC: calculateSHA256(firmware_data) - SEC-->>OTA: calculated_hash - OTA->>OTA: compareSHA256(calculated_hash, expected_hash) - - alt Hash Valid - OTA->>SEC: validateSignature(firmware_data) - SEC-->>OTA: signature_result - - alt Signature Valid - OTA->>OTA: validatePartitionTable(firmware_data) - OTA->>OTA: validateVersion(firmware_data) - OTA->>OTA: validateCompatibility(firmware_data) - OTA->>API: validationComplete(SUCCESS) - else Signature Invalid - OTA->>DIAG: logDiagnosticEvent(OTA_VALIDATION_FAILED) - OTA->>API: validationComplete(FAILED_SIGNATURE) - end - else Hash Invalid - OTA->>DIAG: logDiagnosticEvent(OTA_HASH_MISMATCH) - OTA->>API: validationComplete(FAILED_HASH) - end - else Size Invalid - OTA->>DIAG: logDiagnosticEvent(OTA_SIZE_MISMATCH) - OTA->>API: validationComplete(FAILED_SIZE) - end -``` - -### 2.4 F-OTA-004: Safe Firmware Activation - -**Description:** Controlled firmware activation with system teardown, data preservation, and safe transition to new firmware. - -**Activation Sequence:** -```c -typedef enum { - OTA_ACTIVATION_IDLE = 0, - OTA_ACTIVATION_TEARDOWN = 1, - OTA_ACTIVATION_DATA_FLUSH = 2, - OTA_ACTIVATION_FLASHING = 3, - OTA_ACTIVATION_PARTITION_UPDATE = 4, - OTA_ACTIVATION_REBOOT = 5, - OTA_ACTIVATION_COMPLETE = 6, - OTA_ACTIVATION_FAILED = 7 -} ota_activation_state_t; - -typedef struct { - bool sensor_data_flushed; // Latest sensor data preserved - bool diagnostics_flushed; // Diagnostic events preserved - bool machine_constants_flushed; // Machine constants preserved - bool calibration_data_flushed; // Calibration data preserved - bool system_state_flushed; // System state preserved -} ota_data_flush_status_t; -``` - -**Activation Flow:** -```mermaid -sequenceDiagram - participant OTA as OTA Manager - participant STM as State Manager - participant PERSIST as Persistence - participant FLASH as Flash Manager - participant BOOT as Boot Manager - - Note over OTA,BOOT: Firmware Activation Phase - - OTA->>STM: requestStateTransition(TEARDOWN) - STM->>STM: initiateTeardown() - STM->>PERSIST: flushCriticalData() - - PERSIST->>PERSIST: flushSensorData() - PERSIST->>PERSIST: flushDiagnostics() - PERSIST->>PERSIST: flushMachineConstants() - PERSIST->>PERSIST: flushCalibrationData() - PERSIST-->>STM: flushComplete() - - STM->>OTA: teardownComplete() - OTA->>STM: requestStateTransition(OTA_UPDATE) - - OTA->>FLASH: flashFirmwareToInactivePartition() - FLASH-->>OTA: flashingComplete() - - OTA->>BOOT: updatePartitionTable() - BOOT-->>OTA: partitionTableUpdated() - - OTA->>STM: systemReboot() -``` - -**Data Preservation Priority:** -1. **Critical System Data:** Machine constants, calibration data -2. **Diagnostic Data:** Recent diagnostic events and system health -3. **Sensor Data:** Latest sensor readings and statistics -4. **System State:** Current system state and configuration - -### 2.5 F-OTA-005: A/B Partitioning with Rollback - -**Description:** A/B partitioning implementation with automatic rollback capability for safe firmware updates. - -**Partition Management:** -```c -typedef enum { - OTA_PARTITION_A = 0, // Primary partition (ota_0) - OTA_PARTITION_B = 1, // Secondary partition (ota_1) - OTA_PARTITION_FACTORY = 2 // Factory partition (rescue) -} ota_partition_t; - -typedef struct { - ota_partition_t active_partition; // Currently running partition - ota_partition_t inactive_partition; // Target for next update - char active_version[32]; // Version of active firmware - char inactive_version[32]; // Version of inactive firmware - uint32_t boot_count; // Boot attempts since activation - uint64_t activation_time; // Activation timestamp - bool rollback_pending; // Rollback flag -} ota_partition_status_t; -``` - -**Rollback Triggers:** -- **Boot Failure:** System fails to boot within 60 seconds -- **Health Check Failure:** No health report within 120 seconds after boot -- **Application Crash:** Critical application failure during confirmation period -- **Manual Rollback:** Explicit rollback command from Main Hub - -**Rollback Flow:** -```mermaid -sequenceDiagram - participant BOOT as Boot Manager - participant APP as Application - participant HEALTH as Health Monitor - participant OTA as OTA Manager - participant DIAG as Diagnostics - - Note over BOOT,DIAG: Firmware Rollback Scenario - - BOOT->>APP: startApplication() - - alt Boot Successful - APP->>HEALTH: startHealthMonitoring() - HEALTH->>HEALTH: waitForConfirmationWindow(120s) - - alt Health Report Received - HEALTH->>OTA: confirmFirmwareStability() - OTA->>OTA: markFirmwareAsValid() - else No Health Report - HEALTH->>OTA: firmwareValidationTimeout() - OTA->>OTA: triggerRollback(HEALTH_TIMEOUT) - end - else Boot Failed - BOOT->>OTA: bootFailureDetected() - OTA->>OTA: triggerRollback(BOOT_FAILURE) - end - - alt Rollback Triggered - OTA->>BOOT: switchToInactivePartition() - OTA->>DIAG: logDiagnosticEvent(FIRMWARE_ROLLBACK) - OTA->>BOOT: systemReboot() - end -``` - -**Rollback Process:** -1. **Failure Detection:** Detect rollback trigger condition -2. **Partition Switch:** Update partition table to boot from previous partition -3. **Diagnostic Logging:** Record rollback event and reason -4. **System Reboot:** Restart system with previous firmware -5. **Rollback Notification:** Report rollback to Main Hub after recovery - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-OTA-001** | SR-OTA-001, SR-OTA-002, SR-OTA-003 | OTA negotiation and readiness validation | -| **F-OTA-002** | SR-OTA-004, SR-OTA-005, SR-OTA-006 | Firmware reception and temporary storage | -| **F-OTA-003** | SR-OTA-007, SR-OTA-008, SR-OTA-009 | Firmware integrity and authenticity validation | -| **F-OTA-004** | SR-OTA-010, SR-OTA-011, SR-OTA-012, SR-OTA-013 | Safe firmware activation and data preservation | -| **F-OTA-005** | SR-OTA-014, SR-OTA-015, SR-OTA-016 | A/B partitioning and automatic rollback | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-OTA-001** | SWR-OTA-001, SWR-OTA-002, SWR-OTA-003 | Readiness validation, negotiation protocol, state coordination | -| **F-OTA-002** | SWR-OTA-004, SWR-OTA-005, SWR-OTA-006 | Chunked download, progress tracking, storage management | -| **F-OTA-003** | SWR-OTA-007, SWR-OTA-008, SWR-OTA-009 | SHA-256 validation, signature verification, compatibility checks | -| **F-OTA-004** | SWR-OTA-010, SWR-OTA-011, SWR-OTA-012 | Teardown coordination, data flush, firmware flashing | -| **F-OTA-005** | SWR-OTA-013, SWR-OTA-014, SWR-OTA-015 | Partition management, rollback detection, recovery procedures | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **OTA Manager** | OTA coordination, validation, activation | `application_layer/business_stack/fw_upgrader/` | -| **State Manager** | System state coordination, teardown management | `application_layer/business_stack/STM/` | -| **Persistence** | Data flush, firmware storage | `application_layer/DP_stack/persistence/` | -| **Security Manager** | Cryptographic validation, signature verification | `application_layer/security/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Main Hub APIs** | OTA communication protocol, message handling | `application_layer/business_stack/main_hub_apis/` | -| **Network Stack** | Secure firmware download transport | `drivers/network_stack/` | -| **SD Card Driver** | Temporary firmware storage | `drivers/SDcard/` | -| **NVM Driver** | Progress persistence, partition management | `drivers/nvm/` | -| **Diagnostics** | OTA event logging, failure reporting | `application_layer/diag_task/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "OTA Firmware Update Feature" - OTA[OTA Manager] - STM[State Manager] - PERSIST[Persistence] - SEC[Security Manager] - end - - subgraph "Communication Components" - API[Main Hub APIs] - NET[Network Stack] - end - - subgraph "Storage Components" - SD[SD Card Driver] - NVM[NVM Driver] - end - - subgraph "System Components" - DIAG[Diagnostics] - BOOT[Boot Manager] - HEALTH[Health Monitor] - end - - subgraph "External Interfaces" - MH[Main Hub] - FLASH[Flash Memory] - PART[Partition Table] - end - - MH <-->|OTA Protocol| API - API <--> OTA - OTA <--> STM - OTA <--> PERSIST - OTA <--> SEC - - OTA --> NET - NET -->|Firmware Download| MH - - PERSIST --> SD - PERSIST --> NVM - - OTA --> DIAG - OTA --> BOOT - OTA --> HEALTH - - BOOT --> FLASH - BOOT --> PART - - STM -.->|State Events| DIAG - SEC -.->|Validation Events| DIAG -``` - -### 4.4 OTA Update Sequence - -```mermaid -sequenceDiagram - participant MH as Main Hub - participant API as Main Hub APIs - participant OTA as OTA Manager - participant STM as State Manager - participant PERSIST as Persistence - participant SEC as Security Manager - participant BOOT as Boot Manager - - Note over MH,BOOT: Complete OTA Update Flow - - MH->>API: OTA_AVAILABILITY_NOTIFICATION - API->>OTA: otaAvailabilityReceived() - OTA->>OTA: validateReadiness() - OTA->>STM: requestStateTransition(OTA_PREP) - OTA->>API: otaResponse(ACCEPT) - - loop Firmware Download - MH->>API: firmwareChunk(data) - API->>OTA: chunkReceived(data) - OTA->>PERSIST: storeChunk(data) - end - - OTA->>SEC: validateFirmware() - SEC-->>OTA: validationResult(SUCCESS) - - OTA->>STM: requestStateTransition(TEARDOWN) - STM->>PERSIST: flushCriticalData() - PERSIST-->>STM: flushComplete() - - OTA->>BOOT: flashFirmwareToInactivePartition() - OTA->>BOOT: updatePartitionTable() - OTA->>STM: systemReboot() - - Note over MH,BOOT: System Reboots with New Firmware - - BOOT->>BOOT: bootFromNewPartition() - BOOT->>OTA: firmwareActivated() - OTA->>API: otaStatus(ACTIVATION_SUCCESS) - API->>MH: OTA_STATUS_REPORT(SUCCESS) -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **OTA Availability Phase:** - - Receive OTA availability notification from Main Hub - - Validate system readiness (state, power, storage, communication) - - Negotiate OTA acceptance or rejection with detailed reasons - - Transition to OTA_PREP state if accepted - -2. **Firmware Download Phase:** - - Receive firmware in 4KB chunks over secure channel - - Validate each chunk with CRC32 verification - - Store chunks to SD card temporary location - - Track download progress and handle retries - - Enforce 10-minute download timeout - -3. **Validation Phase:** - - Perform comprehensive firmware integrity validation - - Verify SHA-256 hash, digital signature, and compatibility - - Report validation results to Main Hub - - Proceed to activation only if all validations pass - -4. **Activation Phase:** - - Coordinate system teardown with State Manager - - Flush all critical data to persistent storage - - Flash validated firmware to inactive partition - - Update partition table for next boot - - Perform controlled system reboot - -5. **Confirmation Phase:** - - Boot with new firmware and start health monitoring - - Confirm firmware stability within 120-second window - - Mark firmware as valid or trigger automatic rollback - - Report final OTA status to Main Hub - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **System Not Ready** | Readiness validation failure | Reject OTA request, report specific reason | -| **Download Timeout** | 10-minute timeout exceeded | Abort download, clean up temporary files | -| **Chunk Corruption** | CRC32 validation failure | Request chunk retransmission (up to 3 retries) | -| **Validation Failure** | Integrity check failure | Abort OTA, report validation error | -| **Flash Failure** | Firmware flashing error | Abort OTA, maintain current firmware | -| **Boot Failure** | New firmware boot failure | Automatic rollback to previous firmware | -| **Health Check Failure** | No health report within window | Automatic rollback to previous firmware | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | OTA Manager initialization, partition status check | -| **RUNNING** | Accept OTA requests, perform readiness validation | -| **WARNING** | Reject OTA requests (system not stable) | -| **FAULT** | Reject OTA requests (system in fault state) | -| **OTA_PREP** | Prepare for OTA, coordinate with other components | -| **OTA_UPDATE** | Execute OTA download, validation, and activation | -| **TEARDOWN** | Coordinate data flush before firmware activation | -| **SERVICE** | Reject OTA requests (maintenance mode) | -| **SD_DEGRADED** | Reject OTA requests (storage unavailable) | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Negotiation Response:** Maximum 5 seconds for readiness validation -- **Download Timeout:** Maximum 10 minutes for complete firmware download -- **Validation Time:** Maximum 2 minutes for integrity validation -- **Activation Time:** Maximum 5 minutes for firmware activation -- **Confirmation Window:** 120 seconds for firmware stability confirmation - -### 6.2 Resource Constraints - -- **Storage Requirements:** Minimum 100MB free space on SD card -- **Memory Usage:** Maximum 64KB for OTA buffers and state -- **Network Bandwidth:** Optimized for 4KB chunk size -- **Flash Wear:** Minimize flash write cycles during activation - -### 6.3 Security Constraints - -- **Encrypted Transport:** All firmware data must be transmitted over TLS -- **Integrity Validation:** SHA-256 verification mandatory -- **Anti-Rollback:** Version progression enforcement via eFuse -- **Secure Storage:** Temporary firmware files encrypted on SD card - -## 7. Interface Specifications - -### 7.1 OTA Manager Public API - -```c -// OTA lifecycle management -bool otaMgr_initialize(void); -bool otaMgr_isReady(void); -ota_status_t otaMgr_getStatus(void); - -// OTA operations -bool otaMgr_handleAvailabilityNotification(const ota_metadata_t* metadata); -bool otaMgr_receiveFirmwareChunk(uint32_t chunk_id, const uint8_t* data, - size_t size, uint32_t crc32); -bool otaMgr_validateFirmware(void); -bool otaMgr_activateFirmware(void); - -// Rollback operations -bool otaMgr_triggerRollback(rollback_reason_t reason); -bool otaMgr_confirmFirmwareStability(void); -bool otaMgr_isRollbackPending(void); - -// Status and diagnostics -bool otaMgr_getDownloadProgress(ota_download_progress_t* progress); -bool otaMgr_getValidationResult(ota_validation_result_t* result); -bool otaMgr_getPartitionStatus(ota_partition_status_t* status); -``` - -### 7.2 State Manager Integration - -**State Transitions:** -- `RUNNING → OTA_PREP`: OTA request accepted -- `OTA_PREP → TEARDOWN`: Firmware validated, ready for activation -- `TEARDOWN → OTA_UPDATE`: Data flushed, ready for flashing -- `OTA_UPDATE → REBOOT`: Firmware activated, system restart - -**State Coordination:** -```c -// State transition requests -bool otaMgr_requestStateTransition(system_state_t target_state, - transition_reason_t reason); -bool otaMgr_onStateChanged(system_state_t new_state, system_state_t old_state); - -// Teardown coordination -bool otaMgr_initiateTeardown(teardown_reason_t reason); -bool otaMgr_onTeardownComplete(void); -``` - -### 7.3 Security Manager Integration - -**Validation Interface:** -```c -// Firmware integrity validation -bool secMgr_calculateSHA256(const uint8_t* data, size_t size, uint8_t* hash); -bool secMgr_validateSignature(const uint8_t* firmware, size_t size, - const uint8_t* signature); -bool secMgr_validateAntiRollback(const char* version); - -// Secure storage -bool secMgr_encryptFirmwareChunk(const uint8_t* plaintext, size_t size, - uint8_t* ciphertext); -bool secMgr_decryptFirmwareChunk(const uint8_t* ciphertext, size_t size, - uint8_t* plaintext); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Readiness Validation:** All readiness criteria and rejection scenarios -- **Chunk Processing:** Chunk reception, validation, and storage -- **Integrity Validation:** SHA-256, signature, and compatibility checks -- **Rollback Logic:** All rollback triggers and recovery procedures - -### 8.2 Integration Testing - -- **End-to-End OTA:** Complete OTA flow from negotiation to confirmation -- **State Coordination:** Integration with State Manager and other components -- **Security Integration:** Cryptographic validation and secure storage -- **Network Integration:** Firmware download over encrypted channels - -### 8.3 System Testing - -- **Fault Injection:** Network failures, power loss, corruption scenarios -- **Performance Testing:** Large firmware downloads and timing constraints -- **Security Testing:** Malicious firmware rejection and rollback scenarios -- **Long-Duration Testing:** Multiple OTA cycles and partition wear - -### 8.4 Acceptance Criteria - -- OTA negotiation completes within timing constraints -- Firmware download handles all error conditions gracefully -- Integrity validation rejects all invalid firmware images -- Activation preserves all critical data during transition -- Rollback mechanism recovers from all failure scenarios -- No security vulnerabilities in OTA process -- Complete audit trail of all OTA activities - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **State Manager:** System state coordination and teardown management -- **Persistence:** Data flush and firmware storage operations -- **Security Manager:** Cryptographic validation and secure storage -- **Main Hub APIs:** OTA communication protocol implementation -- **Diagnostics:** OTA event logging and failure reporting - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** Partition management and flash operations -- **Secure Boot:** Hardware-enforced firmware authentication -- **Network Stack:** Secure communication transport (TLS/DTLS) -- **Hardware Components:** SD card, NVS flash, network interface - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Delta Updates:** Incremental firmware updates to reduce download size -- **Compression:** Firmware compression to optimize storage and bandwidth -- **Multi-Stage Rollback:** Graduated rollback with multiple recovery points -- **Predictive Validation:** Pre-validation of firmware compatibility - -### 10.2 Scalability Considerations - -- **Fleet Management:** Coordinated OTA updates across multiple sensor hubs -- **Cloud Integration:** Direct cloud-based firmware distribution -- **Advanced Analytics:** OTA success rate monitoring and optimization -- **Automated Testing:** Continuous integration with automated OTA testing - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-OTA, SWR-OTA) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-PWR_Power_Fault_Handling.md b/draft- to be removed SW/features/F-PWR_Power_Fault_Handling.md deleted file mode 100644 index 28b1aec..0000000 --- a/draft- to be removed SW/features/F-PWR_Power_Fault_Handling.md +++ /dev/null @@ -1,586 +0,0 @@ -# Feature Specification: Power & Fault Handling -# Feature ID: F-PWR (F-PWR-001 to F-PWR-002) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Power & Fault Handling - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Power & Fault Handling feature provides comprehensive power management and fault recovery capabilities for the ASF Sensor Hub. This feature ensures reliable operation under power fluctuations, graceful recovery from power interruptions, and protection of critical data during power loss events. - -### 1.2 Feature Scope - -**In Scope:** -- Hardware-based brownout detection and response -- Power-loss data protection with supercapacitor backup -- Graceful shutdown and recovery procedures -- Power quality monitoring and reporting -- Critical data preservation during power events - -**Out of Scope:** -- Battery-powered operation modes (system assumes continuous power) -- Advanced power management for low-power modes -- External power supply design and regulation -- Hardware power supply fault diagnosis - -## 2. Sub-Features - -### 2.1 F-PWR-001: Brownout Detection and Handling - -**Description:** Hardware-based brownout detection with immediate response to protect system integrity and preserve critical data during power supply fluctuations. - -**Brownout Detection Configuration:** -```c -typedef struct { - float brownout_threshold_v; // 3.0V threshold (configurable) - uint32_t detection_delay_ms; // 10ms detection delay - bool hardware_detection_enabled; // ESP32-S3 BOD enabled - brownout_response_t response; // Immediate response action - uint32_t supercap_runtime_ms; // Available supercapacitor runtime -} brownout_config_t; - -typedef enum { - BROWNOUT_RESPONSE_IMMEDIATE_FLUSH = 0, // Flush critical data immediately - BROWNOUT_RESPONSE_GRACEFUL_SHUTDOWN = 1, // Attempt graceful shutdown - BROWNOUT_RESPONSE_EMERGENCY_SAVE = 2 // Emergency data save only -} brownout_response_t; - -typedef struct { - bool brownout_detected; // Current brownout status - uint64_t brownout_start_time; // Brownout detection timestamp - uint32_t brownout_duration_ms; // Duration of current brownout - uint32_t brownout_count; // Total brownout events - float min_voltage_recorded; // Minimum voltage during event - power_loss_severity_t severity; // Brownout severity classification -} brownout_status_t; - -typedef enum { - POWER_LOSS_MINOR = 0, // Brief voltage dip, no action needed - POWER_LOSS_MODERATE = 1, // Voltage drop, flush critical data - POWER_LOSS_SEVERE = 2, // Extended brownout, emergency shutdown - POWER_LOSS_CRITICAL = 3 // Imminent power loss, immediate save -} power_loss_severity_t; -``` - -**Hardware Configuration:** -- **Brownout Detector:** ESP32-S3 hardware BOD with 3.0V threshold -- **Supercapacitor:** 0.5-1.0F capacitor providing 1-2 seconds runtime at 3.3V -- **Detection ISR:** High-priority interrupt service routine for immediate response -- **Voltage Monitoring:** Continuous ADC monitoring of supply voltage - -**Brownout Response Flow:** -```mermaid -sequenceDiagram - participant PWR as Power Supply - participant BOD as Brownout Detector - participant ISR as Brownout ISR - participant PWR_MGR as Power Manager - participant PERSIST as Persistence - participant DIAG as Diagnostics - - Note over PWR,DIAG: Brownout Detection and Response - - PWR->>PWR: voltageDropBelow3.0V() - PWR->>BOD: triggerBrownoutDetection() - BOD->>ISR: brownoutInterrupt() - - ISR->>ISR: setPowerLossFlag() - ISR->>PWR_MGR: notifyBrownoutDetected() - - PWR_MGR->>PWR_MGR: assessSeverity(voltage, duration) - - alt Severity >= MODERATE - PWR_MGR->>PERSIST: flushCriticalDataImmediate() - PERSIST->>PERSIST: flushMachineConstants() - PERSIST->>PERSIST: flushCalibrationData() - PERSIST->>PERSIST: flushDiagnosticEvents() - PERSIST-->>PWR_MGR: criticalDataFlushed() - end - - alt Severity >= SEVERE - PWR_MGR->>PWR_MGR: initiateGracefulShutdown() - PWR_MGR->>DIAG: logPowerEvent(BROWNOUT_SHUTDOWN) - end - - PWR->>PWR: voltageRestored() - BOD->>ISR: brownoutCleared() - ISR->>PWR_MGR: notifyBrownoutCleared() - PWR_MGR->>PWR_MGR: initiatePowerRecovery() -``` - -**Critical Data Flush Priority:** -1. **Machine Constants:** System configuration and calibration parameters -2. **Diagnostic Events:** Recent fault and warning events -3. **Sensor Calibration:** Current sensor calibration data -4. **System State:** Current system state and operational parameters -5. **Recent Sensor Data:** Latest sensor readings (if time permits) - -**Supercapacitor Runtime Management:** -```c -typedef struct { - float capacitance_f; // Supercapacitor capacitance (0.5-1.0F) - float initial_voltage_v; // Initial charge voltage (3.3V) - float cutoff_voltage_v; // Minimum operating voltage (2.7V) - uint32_t estimated_runtime_ms; // Calculated runtime at current load - uint32_t flush_time_budget_ms; // Time allocated for data flush - bool supercap_present; // Supercapacitor detection status -} supercapacitor_config_t; - -// Runtime calculation: t = C * (V_initial - V_cutoff) / I_load -uint32_t calculateSupercapRuntime(float capacitance, float v_init, - float v_cutoff, float current_ma); -``` - -### 2.2 F-PWR-002: Power-Loss Recovery - -**Description:** Comprehensive power-loss recovery system that detects power restoration, performs system integrity checks, and restores normal operation with full data consistency validation. - -**Recovery Configuration:** -```c -typedef struct { - uint32_t power_stabilization_delay_ms; // 100ms stabilization wait - uint32_t recovery_timeout_ms; // 30s maximum recovery time - bool integrity_check_required; // Data integrity validation - bool state_restoration_enabled; // System state restoration - recovery_mode_t recovery_mode; // Recovery behavior mode -} power_recovery_config_t; - -typedef enum { - RECOVERY_MODE_FAST = 0, // Quick recovery, minimal checks - RECOVERY_MODE_SAFE = 1, // Full integrity checks - RECOVERY_MODE_DIAGNOSTIC = 2 // Extended diagnostics during recovery -} recovery_mode_t; - -typedef struct { - bool power_restored; // Power restoration status - uint64_t power_loss_start; // Power loss start timestamp - uint64_t power_loss_duration; // Total power loss duration - uint32_t recovery_attempts; // Number of recovery attempts - recovery_status_t status; // Current recovery status - data_integrity_result_t integrity; // Data integrity check results -} power_recovery_status_t; - -typedef enum { - RECOVERY_STATUS_PENDING = 0, // Recovery not started - RECOVERY_STATUS_IN_PROGRESS = 1, // Recovery in progress - RECOVERY_STATUS_SUCCESS = 2, // Recovery completed successfully - RECOVERY_STATUS_FAILED = 3, // Recovery failed - RECOVERY_STATUS_PARTIAL = 4 // Partial recovery (degraded mode) -} recovery_status_t; -``` - -**Data Integrity Validation:** -```c -typedef struct { - bool machine_constants_valid; // MC data integrity - bool calibration_data_valid; // Calibration integrity - bool diagnostic_logs_valid; // Diagnostic data integrity - bool system_state_valid; // State data integrity - bool sensor_data_valid; // Sensor data integrity - uint32_t corrupted_files; // Number of corrupted files - uint32_t recovered_files; // Number of recovered files -} data_integrity_result_t; - -typedef enum { - INTEGRITY_CHECK_PASS = 0, // All data intact - INTEGRITY_CHECK_MINOR_LOSS = 1, // Minor data loss, recoverable - INTEGRITY_CHECK_MAJOR_LOSS = 2, // Major data loss, degraded operation - INTEGRITY_CHECK_CRITICAL_LOSS = 3 // Critical data loss, requires intervention -} integrity_check_result_t; -``` - -**Power Recovery Flow:** -```mermaid -sequenceDiagram - participant PWR as Power Supply - participant PWR_MGR as Power Manager - participant PERSIST as Persistence - participant DIAG as Diagnostics - participant STM as State Manager - participant SENSOR as Sensor Manager - - Note over PWR,SENSOR: Power Recovery Sequence - - PWR->>PWR: powerRestored() - PWR->>PWR_MGR: notifyPowerRestoration() - - PWR_MGR->>PWR_MGR: waitForStabilization(100ms) - PWR_MGR->>PWR_MGR: detectPowerLossDuration() - - PWR_MGR->>PERSIST: performIntegrityCheck() - PERSIST->>PERSIST: validateMachineConstants() - PERSIST->>PERSIST: validateCalibrationData() - PERSIST->>PERSIST: validateDiagnosticLogs() - PERSIST-->>PWR_MGR: integrityResults() - - alt Integrity Check PASS - PWR_MGR->>STM: restoreSystemState() - STM->>STM: transitionToRunningState() - PWR_MGR->>SENSOR: restoreSensorConfiguration() - PWR_MGR->>DIAG: logPowerEvent(RECOVERY_SUCCESS) - else Integrity Check MINOR_LOSS - PWR_MGR->>PERSIST: attemptDataRecovery() - PWR_MGR->>STM: transitionToWarningState() - PWR_MGR->>DIAG: logPowerEvent(RECOVERY_PARTIAL) - else Integrity Check MAJOR_LOSS - PWR_MGR->>STM: transitionToFaultState() - PWR_MGR->>DIAG: logPowerEvent(RECOVERY_FAILED) - end - - PWR_MGR->>PWR_MGR: reportRecoveryStatus() -``` - -**Recovery Validation Steps:** -1. **Power Stabilization:** Wait 100ms for power supply stabilization -2. **System Clock Recovery:** Restore system time from RTC (if available) -3. **Data Integrity Check:** Validate all persistent data structures -4. **Configuration Restoration:** Reload machine constants and calibration -5. **State Restoration:** Restore system state and component configuration -6. **Sensor Reinitialization:** Reinitialize sensors and resume acquisition -7. **Communication Recovery:** Re-establish network connections -8. **Recovery Reporting:** Log recovery status and any data loss - -**RTC Battery Support (Optional):** -```c -typedef struct { - bool rtc_battery_present; // External RTC battery detected - float rtc_battery_voltage; // Current RTC battery voltage - uint64_t time_before_loss; // Time before power loss - uint64_t time_after_recovery; // Time after power recovery - bool time_accuracy_maintained; // Time accuracy status -} rtc_battery_status_t; - -// RTC battery specifications: CR2032, 3V, 220mAh -// Maintains time accuracy during power loss up to several months -``` - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-PWR-001** | SR-PWR-001, SR-PWR-002, SR-PWR-003, SR-PWR-004 | Brownout detection, data flush, graceful shutdown, clean reboot | -| **F-PWR-002** | SR-PWR-005, SR-PWR-006, SR-PWR-007, SR-PWR-008 | Power recovery, integrity validation, state restoration, event reporting | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-PWR-001** | SWR-PWR-001, SWR-PWR-002, SWR-PWR-003 | BOD configuration, ISR handling, supercapacitor management | -| **F-PWR-002** | SWR-PWR-004, SWR-PWR-005, SWR-PWR-006 | Recovery procedures, integrity checks, state restoration | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **Power Manager** | Power event coordination, recovery management | `application_layer/power_manager/` | -| **Error Handler** | Power fault classification, escalation | `application_layer/error_handler/` | -| **Persistence** | Critical data flush, integrity validation | `application_layer/DP_stack/persistence/` | -| **State Manager** | System state coordination during power events | `application_layer/business_stack/STM/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Diagnostics** | Power event logging, recovery reporting | `application_layer/diag_task/` | -| **Sensor Manager** | Sensor state preservation and restoration | `application_layer/business_stack/sensor_manager/` | -| **Machine Constant Manager** | Configuration preservation and restoration | `application_layer/business_stack/machine_constant_manager/` | -| **ADC Driver** | Voltage monitoring, supercapacitor status | `ESP_IDF_FW_wrappers/adc/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "Power & Fault Handling Feature" - PWR_MGR[Power Manager] - ERR[Error Handler] - PERSIST[Persistence] - STM[State Manager] - end - - subgraph "System Components" - DIAG[Diagnostics] - SENSOR[Sensor Manager] - MC_MGR[MC Manager] - end - - subgraph "Hardware Interfaces" - BOD[Brownout Detector] - ADC[ADC Driver] - SUPERCAP[Supercapacitor] - RTC[RTC Battery] - end - - subgraph "Storage" - NVS[NVS Flash] - SD[SD Card] - end - - BOD -->|Brownout ISR| PWR_MGR - ADC -->|Voltage Monitoring| PWR_MGR - SUPERCAP -->|Runtime Power| PWR_MGR - RTC -->|Time Backup| PWR_MGR - - PWR_MGR <--> STM - PWR_MGR <--> ERR - PWR_MGR <--> PERSIST - - PWR_MGR --> DIAG - PWR_MGR --> SENSOR - PWR_MGR --> MC_MGR - - PERSIST --> NVS - PERSIST --> SD - - ERR -.->|Power Faults| DIAG - STM -.->|State Events| DIAG -``` - -### 4.4 Power Event Sequence - -```mermaid -sequenceDiagram - participant HW as Hardware - participant BOD as Brownout Detector - participant PWR as Power Manager - participant PERSIST as Persistence - participant STM as State Manager - participant DIAG as Diagnostics - - Note over HW,DIAG: Complete Power Event Cycle - - HW->>BOD: voltageDropDetected(2.9V) - BOD->>PWR: brownoutISR() - PWR->>PWR: assessPowerLossSeverity() - - alt Critical Power Loss - PWR->>PERSIST: emergencyDataFlush() - PERSIST->>NVS: flushCriticalData() - PWR->>STM: notifyPowerLoss(CRITICAL) - PWR->>DIAG: logPowerEvent(BROWNOUT_CRITICAL) - end - - Note over HW,DIAG: Power Loss Period - - HW->>HW: powerLost() - - Note over HW,DIAG: Power Restoration - - HW->>PWR: powerRestored() - PWR->>PWR: waitForStabilization() - PWR->>PERSIST: performIntegrityCheck() - - alt Data Integrity OK - PWR->>STM: restoreSystemState() - STM->>STM: transitionToRunning() - PWR->>DIAG: logPowerEvent(RECOVERY_SUCCESS) - else Data Corruption Detected - PWR->>STM: transitionToFault() - PWR->>DIAG: logPowerEvent(RECOVERY_FAILED) - end -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **Continuous Monitoring:** - - Monitor supply voltage using ADC and hardware brownout detector - - Track supercapacitor charge level and estimated runtime - - Maintain power quality statistics and trend analysis - - Report power events to diagnostics system - -2. **Brownout Response:** - - Detect voltage drop below 3.0V threshold within 10ms - - Assess brownout severity based on voltage level and duration - - Execute immediate data flush for critical system data - - Coordinate graceful shutdown if extended brownout detected - -3. **Power Recovery:** - - Detect power restoration and wait for stabilization - - Perform comprehensive data integrity validation - - Restore system state and component configuration - - Resume normal operation or enter degraded mode if data loss detected - -4. **Event Reporting:** - - Log all power events with timestamps and severity - - Report power quality metrics to Main Hub - - Maintain power event history for trend analysis - - Generate diagnostic alerts for recurring power issues - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **Supercapacitor Failure** | Voltage monitoring, runtime calculation | Log warning, reduce flush scope | -| **Data Flush Timeout** | Flush operation timeout | Abort flush, log partial completion | -| **Recovery Failure** | Integrity check failure | Enter fault state, request intervention | -| **RTC Battery Low** | Battery voltage monitoring | Log warning, continue without RTC | -| **Repeated Brownouts** | Event frequency analysis | Escalate to system fault, notify Main Hub | -| **Critical Data Loss** | Integrity validation failure | Enter fault state, preserve remaining data | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Initialize power monitoring, configure brownout detection | -| **RUNNING** | Full power monitoring, immediate brownout response | -| **WARNING** | Enhanced power monitoring, preemptive data flush | -| **FAULT** | Critical power functions only, preserve fault data | -| **OTA_UPDATE** | Reject OTA if power unstable, maintain power monitoring | -| **TEARDOWN** | Coordinate with teardown, ensure data preservation | -| **SERVICE** | Limited power monitoring for diagnostics | -| **SD_DEGRADED** | NVS-only data flush, reduced recovery capabilities | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Brownout Detection:** Maximum 10ms detection delay -- **Data Flush:** Must complete within supercapacitor runtime (1-2 seconds) -- **Power Stabilization:** 100ms wait after power restoration -- **Recovery Timeout:** Maximum 30 seconds for complete recovery - -### 6.2 Resource Constraints - -- **Supercapacitor Runtime:** 1-2 seconds at 3.3V with 0.5-1.0F capacitance -- **Critical Data Size:** Maximum data that can be flushed within runtime -- **Memory Usage:** Maximum 16KB for power management buffers -- **Flash Wear:** Minimize NVS writes during frequent brownouts - -### 6.3 Hardware Constraints - -- **Brownout Threshold:** 3.0V ±0.1V (ESP32-S3 BOD limitation) -- **Voltage Monitoring:** ADC accuracy ±50mV -- **Supercapacitor Leakage:** Account for self-discharge over time -- **RTC Battery Life:** CR2032 provides several months of timekeeping - -## 7. Interface Specifications - -### 7.1 Power Manager Public API - -```c -// Power management initialization -bool powerMgr_initialize(void); -bool powerMgr_configureBrownoutDetection(const brownout_config_t* config); -bool powerMgr_configureRecovery(const power_recovery_config_t* config); - -// Power monitoring -bool powerMgr_getCurrentVoltage(float* voltage); -bool powerMgr_getSupercapStatus(supercapacitor_status_t* status); -bool powerMgr_getPowerQuality(power_quality_metrics_t* metrics); - -// Power event handling -bool powerMgr_isBrownoutActive(void); -bool powerMgr_isRecoveryInProgress(void); -bool powerMgr_getPowerEventHistory(power_event_t* events, size_t* count); - -// Emergency operations -bool powerMgr_triggerEmergencyFlush(void); -bool powerMgr_estimateFlushTime(uint32_t* estimated_ms); -``` - -### 7.2 Brownout ISR Interface - -```c -// Brownout interrupt service routine -void IRAM_ATTR brownout_isr_handler(void* arg); - -// ISR-safe operations -void IRAM_ATTR powerMgr_setBrownoutFlag(void); -void IRAM_ATTR powerMgr_recordBrownoutTime(void); -void IRAM_ATTR powerMgr_triggerEmergencyResponse(void); -``` - -### 7.3 Recovery Validation Interface - -```c -// Data integrity validation -bool powerMgr_validateDataIntegrity(data_integrity_result_t* result); -bool powerMgr_attemptDataRecovery(const char* data_type); -bool powerMgr_restoreSystemConfiguration(void); - -// Recovery status -recovery_status_t powerMgr_getRecoveryStatus(void); -bool powerMgr_isRecoveryComplete(void); -bool powerMgr_getRecoveryReport(recovery_report_t* report); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Brownout Detection:** Simulated voltage drops and ISR response -- **Data Flush:** Critical data preservation under time constraints -- **Recovery Logic:** Data integrity validation and state restoration -- **Supercapacitor Management:** Runtime calculation and monitoring - -### 8.2 Integration Testing - -- **End-to-End Power Cycle:** Complete brownout and recovery sequence -- **State Coordination:** Integration with State Manager during power events -- **Data Persistence:** Integration with Persistence component for data flush -- **Diagnostic Integration:** Power event logging and reporting - -### 8.3 System Testing - -- **Hardware Power Testing:** Real power supply interruptions and brownouts -- **Stress Testing:** Repeated power cycles and brownout events -- **Data Integrity Testing:** Validation of data preservation under various scenarios -- **Performance Testing:** Timing constraints under different system loads - -### 8.4 Acceptance Criteria - -- Brownout detection responds within 10ms of voltage drop -- Critical data successfully preserved during power loss events -- System recovers gracefully from power interruptions -- Data integrity maintained across power cycles -- No data corruption during normal power events -- Power quality monitoring provides accurate metrics -- Complete audit trail of all power events - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **State Manager:** System state coordination during power events -- **Persistence:** Critical data flush and integrity validation -- **Error Handler:** Power fault classification and escalation -- **Diagnostics:** Power event logging and reporting - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** Brownout detector, ADC, NVS, RTC -- **Hardware Components:** Supercapacitor, RTC battery, voltage regulators -- **FreeRTOS:** ISR handling, task coordination -- **Power Supply:** Stable 3.3V supply with brownout protection - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Predictive Power Management:** Machine learning for power failure prediction -- **Advanced Supercapacitor Management:** Dynamic runtime optimization -- **Power Quality Analytics:** Advanced power supply analysis and reporting -- **Battery Backup Support:** Optional battery backup for extended operation - -### 10.2 Scalability Considerations - -- **Fleet Power Monitoring:** Centralized power quality monitoring across hubs -- **Predictive Maintenance:** Power supply health monitoring and replacement alerts -- **Advanced Recovery:** Multi-level recovery strategies based on data loss severity -- **Energy Harvesting:** Integration with renewable energy sources - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-PWR, SWR-PWR) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-SEC_Security_Safety.md b/draft- to be removed SW/features/F-SEC_Security_Safety.md deleted file mode 100644 index 09826bc..0000000 --- a/draft- to be removed SW/features/F-SEC_Security_Safety.md +++ /dev/null @@ -1,693 +0,0 @@ -# Feature Specification: Security & Safety -# Feature ID: F-SEC (F-SEC-001 to F-SEC-004) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** Security & Safety - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The Security & Safety feature provides comprehensive security enforcement and safety mechanisms for the ASF Sensor Hub. This feature ensures that only trusted firmware executes, sensitive data is protected at rest and in transit, and all communications maintain confidentiality and integrity through cryptographic mechanisms. - -### 1.2 Feature Scope - -**In Scope:** -- Hardware-enforced secure boot with cryptographic verification -- Flash encryption for sensitive data protection at rest -- Mutual TLS (mTLS) for secure communication channels -- Security violation detection and response mechanisms -- Device identity management and authentication - -**Out of Scope:** -- Cloud server security policies and infrastructure -- User identity management and access control systems -- Physical tamper detection hardware (future enhancement) -- Cryptographic key generation and signing infrastructure - -## 2. Sub-Features - -### 2.1 F-SEC-001: Secure Boot - -**Description:** Hardware-enforced secure boot implementation using Secure Boot V2 to ensure only authenticated and authorized firmware images execute on the Sensor Hub. - -**Secure Boot Configuration:** -```c -typedef struct { - secure_boot_version_t version; // Secure Boot V2 - signature_algorithm_t algorithm; // RSA-3072 or ECDSA-P256 - uint8_t root_key_hash[32]; // Root-of-trust key hash (eFuse) - bool anti_rollback_enabled; // eFuse-based anti-rollback - uint32_t security_version; // Current security version - boot_verification_mode_t mode; // Hardware-enforced verification -} secure_boot_config_t; - -typedef enum { - SECURE_BOOT_V2 = 2 // Only supported version -} secure_boot_version_t; - -typedef enum { - SIG_ALG_RSA_3072 = 0, // RSA-3072 signature - SIG_ALG_ECDSA_P256 = 1 // ECDSA-P256 signature -} signature_algorithm_t; - -typedef enum { - BOOT_MODE_DEVELOPMENT = 0, // Development mode (key revocable) - BOOT_MODE_PRODUCTION = 1 // Production mode (key permanent) -} boot_verification_mode_t; -``` - -**Boot Verification Flow:** -```mermaid -sequenceDiagram - participant PWR as Power On - participant ROM as ROM Bootloader - participant SB as Secure Boot V2 - participant EFUSE as eFuse Storage - participant APP as Application - participant DIAG as Diagnostics - - PWR->>ROM: System Reset/Power On - ROM->>SB: Load Firmware Image - SB->>EFUSE: readRootKeyHash() - EFUSE-->>SB: root_key_hash - - SB->>SB: verifyFirmwareSignature(root_key_hash) - - alt Signature Valid - SB->>SB: checkAntiRollback() - alt Version Valid - SB->>APP: jumpToApplication() - APP->>DIAG: logBootEvent(SECURE_BOOT_SUCCESS) - else Version Invalid - SB->>SB: enterBootFailureState() - SB->>DIAG: logBootEvent(ANTI_ROLLBACK_VIOLATION) - end - else Signature Invalid - SB->>SB: enterBootFailureState() - SB->>DIAG: logBootEvent(SECURE_BOOT_FAILURE) - end -``` - -**Root-of-Trust Management:** -- **Key Storage:** Root public key hash stored in eFuse (one-time programmable) -- **Key Revocation:** Not supported in production mode (permanent key) -- **Anti-Rollback:** eFuse-based security version enforcement -- **Verification:** Every boot cycle (cold and warm boots) - -**Boot Failure Handling:** -- **BOOT_FAILURE State:** System enters safe state, no application execution -- **Diagnostic Logging:** Boot failure events logged to NVS (if accessible) -- **Recovery:** Manual intervention required (re-flashing with valid firmware) - -### 2.2 F-SEC-002: Secure Flash Storage - -**Description:** Comprehensive flash encryption implementation using AES-256 to protect sensitive data stored in internal flash and external storage devices. - -**Flash Encryption Configuration:** -```c -typedef struct { - encryption_algorithm_t algorithm; // AES-256 - encryption_mode_t mode; // Release mode (recommended) - uint8_t encryption_key[32]; // Hardware-derived key (eFuse) - bool transparent_decryption; // Automatic decryption on read - flash_encryption_scope_t scope; // Encrypted regions -} flash_encryption_config_t; - -typedef enum { - ENCRYPT_AES_256 = 0 // AES-256 encryption -} encryption_algorithm_t; - -typedef enum { - ENCRYPT_MODE_DEVELOPMENT = 0, // Development mode (key readable) - ENCRYPT_MODE_RELEASE = 1 // Release mode (key protected) -} encryption_mode_t; - -typedef struct { - bool firmware_encrypted; // Application partitions - bool nvs_encrypted; // NVS partition - bool machine_constants_encrypted; // MC data - bool calibration_encrypted; // Calibration data - bool diagnostics_encrypted; // Diagnostic logs -} flash_encryption_scope_t; -``` - -**Encrypted Data Categories:** -| Data Type | Storage Location | Encryption Method | Access Control | -|-----------|------------------|-------------------|----------------| -| **Firmware Images** | Flash partitions | Hardware AES-256 | Transparent | -| **Machine Constants** | NVS partition | Hardware AES-256 | Component-mediated | -| **Calibration Data** | NVS partition | Hardware AES-256 | Component-mediated | -| **Cryptographic Keys** | eFuse/Secure NVS | Hardware AES-256 | Restricted access | -| **Diagnostic Logs** | NVS partition | Hardware AES-256 | Component-mediated | -| **SD Card Data** | External storage | Software AES-256 | Optional encryption | - -**External Storage Encryption:** -```c -typedef struct { - bool sd_encryption_enabled; // SD card encryption flag - uint8_t sd_encryption_key[32]; // SD-specific encryption key - encryption_algorithm_t algorithm; // AES-256 for SD card - file_encryption_policy_t policy; // Per-file encryption policy -} external_storage_encryption_t; - -typedef enum { - FILE_ENCRYPT_NONE = 0, // No encryption - FILE_ENCRYPT_SENSITIVE = 1, // Encrypt sensitive files only - FILE_ENCRYPT_ALL = 2 // Encrypt all files -} file_encryption_policy_t; -``` - -**Encryption Flow:** -```mermaid -sequenceDiagram - participant APP as Application - participant PERSIST as Persistence - participant ENCRYPT as Encryption Engine - participant NVS as NVS Storage - participant SD as SD Card - - Note over APP,SD: Secure Data Storage Flow - - APP->>PERSIST: storeSensitiveData(data, type) - PERSIST->>PERSIST: classifyDataSensitivity(type) - - alt Critical Data (NVS) - PERSIST->>ENCRYPT: encryptData(data, NVS_KEY) - ENCRYPT-->>PERSIST: encrypted_data - PERSIST->>NVS: writeEncrypted(encrypted_data) - NVS-->>PERSIST: writeComplete() - else Regular Data (SD Card) - alt SD Encryption Enabled - PERSIST->>ENCRYPT: encryptData(data, SD_KEY) - ENCRYPT-->>PERSIST: encrypted_data - PERSIST->>SD: writeEncrypted(encrypted_data) - else SD Encryption Disabled - PERSIST->>SD: writePlaintext(data) - end - end - - PERSIST-->>APP: storageComplete() -``` - -### 2.3 F-SEC-003: Encrypted Communication - -**Description:** Mutual TLS (mTLS) implementation for secure communication with Main Hub and peer devices, ensuring confidentiality, integrity, and authenticity of all transmitted data. - -**Device Identity and Authentication:** -```c -typedef struct { - uint8_t device_certificate[2048]; // X.509 device certificate (max 2KB) - uint8_t private_key[256]; // Device private key (RSA-2048/ECDSA-P256) - uint8_t ca_certificate[2048]; // Certificate Authority certificate - char device_id[64]; // Unique device identifier - uint64_t certificate_expiry; // Certificate expiration timestamp - bool certificate_valid; // Certificate validation status -} device_identity_t; - -typedef struct { - tls_version_t version; // TLS 1.2 minimum - cipher_suite_t cipher_suite; // Supported cipher suites - bool mutual_auth_required; // mTLS enforcement - uint32_t session_timeout; // TLS session timeout - bool session_resumption; // Session resumption support -} tls_config_t; - -typedef enum { - TLS_VERSION_1_2 = 0x0303, // TLS 1.2 (minimum required) - TLS_VERSION_1_3 = 0x0304 // TLS 1.3 (preferred) -} tls_version_t; -``` - -**Supported Cipher Suites:** -| Cipher Suite | Key Exchange | Encryption | MAC | Recommended | -|-------------|-------------|------------|-----|-------------| -| **TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384** | ECDHE-RSA | AES-256-GCM | SHA384 | Yes | -| **TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384** | ECDHE-ECDSA | AES-256-GCM | SHA384 | Yes | -| **TLS_RSA_WITH_AES_256_GCM_SHA384** | RSA | AES-256-GCM | SHA384 | Fallback | - -**mTLS Handshake Flow:** -```mermaid -sequenceDiagram - participant SH as Sensor Hub - participant MH as Main Hub - participant CA as Certificate Authority - - Note over SH,CA: Mutual TLS Handshake - - SH->>MH: ClientHello + SupportedCipherSuites - MH->>SH: ServerHello + SelectedCipherSuite - MH->>SH: ServerCertificate - MH->>SH: CertificateRequest - MH->>SH: ServerHelloDone - - SH->>SH: validateServerCertificate() - SH->>CA: verifyCertificateChain(server_cert) - CA-->>SH: validationResult(VALID) - - SH->>MH: ClientCertificate - SH->>MH: ClientKeyExchange - SH->>MH: CertificateVerify - SH->>MH: ChangeCipherSpec - SH->>MH: Finished - - MH->>MH: validateClientCertificate() - MH->>CA: verifyCertificateChain(client_cert) - CA-->>MH: validationResult(VALID) - - MH->>SH: ChangeCipherSpec - MH->>SH: Finished - - Note over SH,MH: Secure Channel Established - - SH<->>MH: EncryptedApplicationData -``` - -**Certificate Management:** -- **Device Certificate:** Unique X.509 certificate per device (max 2KB) -- **Private Key:** RSA-2048 or ECDSA-P256 stored securely in eFuse/NVS -- **Certificate Chain:** Root CA and intermediate certificates -- **Certificate Rotation:** Managed on broker/server side -- **Revocation:** Certificate Revocation Lists (CRL) or broker-side denylists - -**Key Lifecycle Management:** -| Phase | Mechanism | Responsibility | -|-------|-----------|----------------| -| **Manufacturing** | Device certificate and private key injection | Manufacturing process | -| **Provisioning** | Certificate validation and registration | Onboarding system | -| **Operation** | TLS session key generation and management | Runtime TLS stack | -| **Rotation** | Certificate renewal and update | Server-side management | -| **Revocation** | Certificate invalidation and replacement | Certificate Authority | - -### 2.4 F-SEC-004: Security Violation Handling - -**Description:** Comprehensive security violation detection, classification, and response system to handle security threats and maintain system integrity. - -**Security Violation Types:** -```c -typedef enum { - SEC_VIOLATION_BOOT_FAILURE = 0x1001, // Secure boot verification failure - SEC_VIOLATION_AUTH_FAILURE = 0x1002, // Authentication failure - SEC_VIOLATION_CERT_INVALID = 0x1003, // Certificate validation failure - SEC_VIOLATION_MESSAGE_TAMPER = 0x1004, // Message integrity violation - SEC_VIOLATION_UNAUTHORIZED_ACCESS = 0x1005, // Unauthorized access attempt - SEC_VIOLATION_ROLLBACK_ATTEMPT = 0x1006, // Anti-rollback violation - SEC_VIOLATION_KEY_COMPROMISE = 0x1007, // Cryptographic key compromise - SEC_VIOLATION_REPLAY_ATTACK = 0x1008 // Message replay attack -} security_violation_type_t; - -typedef struct { - security_violation_type_t type; // Violation type - diagnostic_severity_t severity; // FATAL, ERROR, WARNING - uint64_t timestamp; // Violation timestamp - char source_component[32]; // Component that detected violation - char description[128]; // Human-readable description - uint8_t context_data[64]; // Violation-specific context - uint32_t occurrence_count; // Number of occurrences - bool escalation_triggered; // Escalation flag -} security_violation_event_t; -``` - -**Violation Response Matrix:** -| Violation Type | Severity | Immediate Response | Escalation Action | -|---------------|----------|-------------------|-------------------| -| **Boot Failure** | FATAL | Enter BOOT_FAILURE state | System halt, manual recovery | -| **Auth Failure** | ERROR | Reject connection, log event | Escalate to FATAL after 3 failures | -| **Cert Invalid** | ERROR | Reject connection, log event | Escalate to FATAL if persistent | -| **Message Tamper** | WARNING | Discard message, log event | Escalate to ERROR if repeated | -| **Unauthorized Access** | FATAL | Deny access, log event | System lockdown | -| **Rollback Attempt** | FATAL | Prevent rollback, log event | System halt | -| **Key Compromise** | FATAL | Revoke keys, log event | System lockdown | -| **Replay Attack** | WARNING | Discard message, log event | Escalate to ERROR if persistent | - -**Security Event Flow:** -```mermaid -sequenceDiagram - participant COMP as Security Component - participant SEC as Security Manager - participant DIAG as Diagnostics - participant STM as State Manager - participant LOG as Security Logger - - Note over COMP,LOG: Security Violation Detection and Response - - COMP->>SEC: reportSecurityViolation(type, context) - SEC->>SEC: classifyViolation(type) - SEC->>SEC: determineResponse(type, severity) - - alt Severity == FATAL - SEC->>STM: triggerStateTransition(FAULT) - SEC->>LOG: logSecurityEvent(FATAL, details) - SEC->>DIAG: reportDiagnosticEvent(FATAL, violation) - else Severity == ERROR - SEC->>SEC: checkEscalationCriteria() - alt Escalation Required - SEC->>STM: triggerStateTransition(WARNING) - end - SEC->>LOG: logSecurityEvent(ERROR, details) - SEC->>DIAG: reportDiagnosticEvent(ERROR, violation) - else Severity == WARNING - SEC->>LOG: logSecurityEvent(WARNING, details) - SEC->>DIAG: reportDiagnosticEvent(WARNING, violation) - end - - SEC->>SEC: updateViolationStatistics() - SEC->>SEC: checkPatterns() -``` - -**Escalation Criteria:** -- **Authentication Failures:** 3 consecutive failures within 5 minutes -- **Message Tampering:** 5 tampered messages within 1 minute -- **Certificate Violations:** Persistent certificate validation failures -- **Pattern Detection:** Coordinated attack patterns across multiple violation types - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-SEC-001** | SR-SEC-001, SR-SEC-002, SR-SEC-003, SR-SEC-004 | Secure boot verification and root-of-trust protection | -| **F-SEC-002** | SR-SEC-005, SR-SEC-006, SR-SEC-007, SR-SEC-008 | Flash encryption and secure storage | -| **F-SEC-003** | SR-SEC-009, SR-SEC-010, SR-SEC-011, SR-SEC-012 | Encrypted communication and mTLS | -| **F-SEC-004** | SR-SEC-013, SR-SEC-014, SR-SEC-015 | Security violation handling and response | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-SEC-001** | SWR-SEC-001, SWR-SEC-002, SWR-SEC-003 | Boot verification, signature validation, anti-rollback | -| **F-SEC-002** | SWR-SEC-004, SWR-SEC-005, SWR-SEC-006 | AES-256 encryption, key management, storage protection | -| **F-SEC-003** | SWR-SEC-007, SWR-SEC-008, SWR-SEC-009 | mTLS implementation, certificate management, session security | -| **F-SEC-004** | SWR-SEC-010, SWR-SEC-011, SWR-SEC-012 | Violation detection, response coordination, escalation logic | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **Security Manager** | Security policy enforcement, violation handling | `application_layer/security/` | -| **Secure Boot** | Boot-time firmware verification | `bootloader/secure_boot/` | -| **Encryption Engine** | Cryptographic operations, key management | `application_layer/security/crypto/` | -| **Certificate Manager** | Certificate validation, lifecycle management | `application_layer/security/cert_mgr/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Network Stack** | TLS/DTLS transport layer | `drivers/network_stack/` | -| **NVM Driver** | Secure storage access | `drivers/nvm/` | -| **Diagnostics** | Security event logging | `application_layer/diag_task/` | -| **State Manager** | Security-triggered state transitions | `application_layer/business_stack/STM/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "Security & Safety Feature" - SEC[Security Manager] - BOOT[Secure Boot] - CRYPTO[Encryption Engine] - CERT[Certificate Manager] - end - - subgraph "System Components" - STM[State Manager] - DIAG[Diagnostics] - NET[Network Stack] - NVM[NVM Driver] - end - - subgraph "Hardware Security" - EFUSE[eFuse Storage] - HWCRYPTO[Hardware Crypto] - FLASH[Flash Memory] - end - - subgraph "External Interfaces" - MH[Main Hub] - CA[Certificate Authority] - end - - BOOT --> EFUSE - BOOT --> HWCRYPTO - BOOT --> SEC - - SEC <--> STM - SEC <--> DIAG - SEC --> CRYPTO - SEC --> CERT - - CRYPTO --> HWCRYPTO - CRYPTO --> NVM - - CERT --> NET - CERT --> CA - - NET <-->|mTLS| MH - - SEC -.->|Security Events| DIAG - STM -.->|State Changes| SEC -``` - -### 4.4 Security Enforcement Flow - -```mermaid -sequenceDiagram - participant BOOT as Secure Boot - participant SEC as Security Manager - participant CRYPTO as Encryption Engine - participant CERT as Certificate Manager - participant NET as Network Stack - participant MH as Main Hub - - Note over BOOT,MH: Security Enforcement Flow - - BOOT->>BOOT: verifyFirmwareSignature() - BOOT->>SEC: secureBootComplete(SUCCESS) - SEC->>SEC: initializeSecurityPolicies() - - SEC->>CRYPTO: initializeEncryption() - CRYPTO->>CRYPTO: loadEncryptionKeys() - - SEC->>CERT: initializeCertificates() - CERT->>CERT: validateDeviceCertificate() - - NET->>CERT: establishTLSConnection(main_hub) - CERT->>CERT: performMutualAuthentication() - CERT-->>NET: tlsConnectionEstablished() - - NET<->>MH: secureDataExchange() - - alt Security Violation Detected - SEC->>SEC: handleSecurityViolation(type) - SEC->>DIAG: logSecurityEvent(violation) - SEC->>STM: triggerSecurityResponse(action) - end -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **Boot-Time Security:** - - Secure Boot V2 verifies firmware signature using root-of-trust - - Anti-rollback mechanism prevents firmware downgrade attacks - - Flash encryption automatically decrypts application code - - Security Manager initializes and loads security policies - -2. **Runtime Security:** - - All communication channels use mTLS with mutual authentication - - Sensitive data encrypted before storage using AES-256 - - Certificate validation performed for all external connections - - Security violations monitored and logged continuously - -3. **Communication Security:** - - Device certificate presented during TLS handshake - - Server certificate validated against trusted CA chain - - Encrypted data exchange using negotiated cipher suite - - Session keys rotated according to security policy - -4. **Violation Response:** - - Security violations detected and classified by severity - - Immediate response actions taken based on violation type - - Escalation logic applied for repeated or coordinated attacks - - Security events logged for audit and analysis - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **Boot Verification Failure** | Signature validation failure | Enter BOOT_FAILURE state, halt system | -| **Certificate Validation Failure** | X.509 validation error | Reject connection, log security event | -| **Encryption Key Failure** | Key derivation/access error | Enter FAULT state, disable encryption | -| **TLS Handshake Failure** | Protocol negotiation failure | Retry with fallback, log failure | -| **Message Integrity Failure** | MAC/signature verification failure | Discard message, log tampering event | -| **Anti-Rollback Violation** | Version check failure | Prevent boot, log violation | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Initialize security components, load certificates and keys | -| **RUNNING** | Full security enforcement, continuous violation monitoring | -| **WARNING** | Enhanced security monitoring, stricter validation | -| **FAULT** | Critical security functions only, preserve security logs | -| **OTA_UPDATE** | Secure OTA validation, maintain security during update | -| **TEARDOWN** | Secure data flush, maintain encryption during shutdown | -| **SERVICE** | Limited security access for diagnostics | -| **BOOT_FAILURE** | Security violation state, no application execution | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **Boot Verification:** Maximum 5 seconds for secure boot completion -- **TLS Handshake:** Maximum 10 seconds for mTLS establishment -- **Certificate Validation:** Maximum 2 seconds per certificate -- **Violation Response:** Maximum 100ms for immediate response actions - -### 6.2 Resource Constraints - -- **Certificate Storage:** Maximum 2KB per certificate (device, CA) -- **Key Storage:** Secure storage in eFuse or encrypted NVS -- **Memory Usage:** Maximum 64KB for security buffers and state -- **CPU Usage:** Maximum 10% for cryptographic operations - -### 6.3 Security Constraints - -- **Root-of-Trust:** eFuse-based, one-time programmable -- **Key Protection:** Hardware-protected keys, no plaintext exposure -- **Certificate Validation:** Full chain validation required -- **Encryption Strength:** AES-256 minimum for all encryption - -## 7. Interface Specifications - -### 7.1 Security Manager Public API - -```c -// Security initialization and control -bool secMgr_initialize(void); -bool secMgr_isSecurityEnabled(void); -security_status_t secMgr_getSecurityStatus(void); - -// Violation handling -bool secMgr_reportViolation(security_violation_type_t type, - const char* source, const uint8_t* context); -bool secMgr_getViolationHistory(security_violation_event_t* events, size_t* count); -bool secMgr_clearViolationHistory(void); - -// Security policy management -bool secMgr_setSecurityPolicy(const security_policy_t* policy); -bool secMgr_getSecurityPolicy(security_policy_t* policy); -bool secMgr_enforceSecurityPolicy(void); -``` - -### 7.2 Encryption Engine API - -```c -// Encryption operations -bool crypto_encrypt(const uint8_t* plaintext, size_t plaintext_len, - const uint8_t* key, uint8_t* ciphertext, size_t* ciphertext_len); -bool crypto_decrypt(const uint8_t* ciphertext, size_t ciphertext_len, - const uint8_t* key, uint8_t* plaintext, size_t* plaintext_len); - -// Hash operations -bool crypto_sha256(const uint8_t* data, size_t data_len, uint8_t* hash); -bool crypto_hmac_sha256(const uint8_t* data, size_t data_len, - const uint8_t* key, size_t key_len, uint8_t* hmac); - -// Key management -bool crypto_generateKey(key_type_t type, uint8_t* key, size_t key_len); -bool crypto_deriveKey(const uint8_t* master_key, const char* context, - uint8_t* derived_key, size_t key_len); -``` - -### 7.3 Certificate Manager API - -```c -// Certificate operations -bool certMgr_loadDeviceCertificate(const uint8_t* cert_data, size_t cert_len); -bool certMgr_validateCertificate(const uint8_t* cert_data, size_t cert_len); -bool certMgr_getCertificateInfo(certificate_info_t* info); - -// TLS integration -bool certMgr_setupTLSContext(tls_context_t* ctx); -bool certMgr_validatePeerCertificate(const uint8_t* peer_cert, size_t cert_len); -bool certMgr_getTLSCredentials(tls_credentials_t* credentials); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **Secure Boot:** Firmware signature validation with valid/invalid signatures -- **Encryption:** AES-256 encryption/decryption with known test vectors -- **Certificate Validation:** X.509 certificate parsing and validation -- **Violation Handling:** All violation types and response actions - -### 8.2 Integration Testing - -- **End-to-End Security:** Complete security flow from boot to communication -- **mTLS Integration:** Full TLS handshake with certificate validation -- **State Integration:** Security behavior across all system states -- **Cross-Component Security:** Security enforcement across all components - -### 8.3 System Testing - -- **Security Penetration Testing:** Simulated attacks and vulnerability assessment -- **Performance Testing:** Cryptographic operations under load -- **Fault Injection:** Security behavior under hardware/software faults -- **Long-Duration Testing:** Security stability over extended operation - -### 8.4 Acceptance Criteria - -- Secure boot prevents execution of unsigned firmware -- All sensitive data encrypted at rest and in transit -- mTLS successfully established with valid certificates -- Security violations properly detected and responded to -- No security vulnerabilities identified in penetration testing -- Performance impact of security features within acceptable limits -- Complete audit trail of all security events - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **State Manager:** Security-triggered state transitions -- **Diagnostics:** Security event logging and audit trail -- **Network Stack:** TLS/DTLS transport implementation -- **NVM Driver:** Secure storage for keys and certificates - -### 9.2 External Dependencies - -- **ESP-IDF Security Features:** Secure Boot V2, Flash Encryption, eFuse -- **Hardware Security Module:** Hardware-accelerated cryptography -- **Certificate Authority:** Certificate validation and management -- **Cryptographic Libraries:** mbedTLS or equivalent for TLS implementation - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Hardware Security Module:** Dedicated HSM for key management -- **Physical Tamper Detection:** Hardware-based tamper detection -- **Advanced Threat Detection:** Machine learning-based anomaly detection -- **Quantum-Resistant Cryptography:** Post-quantum cryptographic algorithms - -### 10.2 Scalability Considerations - -- **Fleet Security Management:** Centralized security policy management -- **Certificate Automation:** Automated certificate lifecycle management -- **Security Analytics:** Advanced security event correlation and analysis -- **Zero-Trust Architecture:** Comprehensive zero-trust security model - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-SEC, SWR-SEC) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/F-SYS_System_Management.md b/draft- to be removed SW/features/F-SYS_System_Management.md deleted file mode 100644 index a16e570..0000000 --- a/draft- to be removed SW/features/F-SYS_System_Management.md +++ /dev/null @@ -1,640 +0,0 @@ -# Feature Specification: System Management -# Feature ID: F-SYS (F-SYS-001 to F-SYS-005) - -**Document Type:** Feature Specification -**Version:** 1.0 -**Date:** 2025-01-19 -**Feature Category:** System Management - -## 1. Feature Overview - -### 1.1 Feature Purpose - -The System Management feature provides comprehensive control over the ASF Sensor Hub's operational lifecycle, state management, local human-machine interface, and engineering access capabilities. This feature acts as the supervisory layer governing all other functional domains. - -### 1.2 Feature Scope - -**In Scope:** -- System finite state machine implementation and control -- Controlled teardown sequences for safe transitions -- Local OLED-based human-machine interface -- Engineering and diagnostic access sessions -- GPIO discipline and hardware resource management - -**Out of Scope:** -- Main Hub system management -- Cloud-based management interfaces -- User authentication and role management -- Remote control of other Sub-Hubs - -## 2. Sub-Features - -### 2.1 F-SYS-001: System State Management - -**Description:** Comprehensive finite state machine controlling all system operations and transitions. - -**System States (11 Total):** - -| State | Description | Entry Conditions | Exit Conditions | -|-------|-------------|------------------|-----------------| -| **INIT** | Hardware and software initialization | Power-on, reset | Initialization complete or failure | -| **BOOT_FAILURE** | Secure boot verification failed | Boot verification failure | Manual recovery or reset | -| **RUNNING** | Normal sensor acquisition and communication | Successful initialization | Fault detected, update requested | -| **WARNING** | Non-fatal fault detected, degraded operation | Recoverable fault | Fault cleared or escalated | -| **FAULT** | Fatal error, core functionality disabled | Critical fault | Manual recovery or reset | -| **OTA_PREP** | OTA preparation phase | OTA request accepted | Teardown complete or OTA cancelled | -| **OTA_UPDATE** | Firmware update in progress | OTA preparation complete | Update complete or failed | -| **MC_UPDATE** | Machine constants update in progress | MC update request | Update complete or failed | -| **TEARDOWN** | Controlled shutdown sequence | Update request, fault escalation | Teardown complete | -| **SERVICE** | Engineering or diagnostic interaction | Service request | Service session ended | -| **SD_DEGRADED** | SD card failure detected, fallback mode | SD card failure | SD card restored or replaced | - -**State Transition Matrix:** -```mermaid -stateDiagram-v2 - [*] --> INIT - INIT --> RUNNING : Initialization Success - INIT --> BOOT_FAILURE : Boot Verification Failed - BOOT_FAILURE --> INIT : Manual Recovery - - RUNNING --> WARNING : Non-Fatal Fault - RUNNING --> FAULT : Fatal Fault - RUNNING --> OTA_PREP : OTA Request - RUNNING --> MC_UPDATE : MC Update Request - RUNNING --> SERVICE : Service Request - RUNNING --> SD_DEGRADED : SD Card Failure - - WARNING --> RUNNING : Fault Cleared - WARNING --> FAULT : Fault Escalated - WARNING --> SERVICE : Service Request - - FAULT --> INIT : Manual Recovery - FAULT --> SERVICE : Service Request - - OTA_PREP --> TEARDOWN : Ready for OTA - OTA_PREP --> RUNNING : OTA Cancelled - - TEARDOWN --> OTA_UPDATE : OTA Teardown - TEARDOWN --> MC_UPDATE : MC Teardown - TEARDOWN --> INIT : Reset Teardown - - OTA_UPDATE --> INIT : Update Complete - OTA_UPDATE --> FAULT : Update Failed - - MC_UPDATE --> RUNNING : Update Success - MC_UPDATE --> FAULT : Update Failed - - SERVICE --> RUNNING : Service Complete - SERVICE --> FAULT : Service Error - - SD_DEGRADED --> RUNNING : SD Restored - SD_DEGRADED --> FAULT : Critical SD Error -``` - -### 2.2 F-SYS-002: Controlled Teardown Mechanism - -**Description:** Safe system shutdown ensuring data consistency and resource cleanup. - -**Teardown Triggers:** -- Firmware update (OTA) request -- Machine constants update request -- Fatal system fault escalation -- Manual engineering command -- System reset request - -**Teardown Sequence (Mandatory Order):** -1. **Stop Active Operations** - - Halt sensor acquisition tasks - - Pause communication activities - - Suspend diagnostic operations - -2. **Data Preservation** - - Flush pending sensor data via DP component - - Persist current system state - - Save diagnostic events and logs - - Update machine constants if modified - -3. **Resource Cleanup** - - Close active communication sessions - - Release hardware resources (I2C, SPI, UART) - - Stop non-essential tasks - - Clear temporary buffers - -4. **State Transition** - - Verify data persistence completion - - Update system state to target state - - Signal teardown completion - - Enter target operational mode - -**Teardown Verification:** -```mermaid -sequenceDiagram - participant STM as State Manager - participant SM as Sensor Manager - participant DP as Data Persistence - participant COM as Communication - participant ES as Event System - - Note over STM,ES: Teardown Initiation - STM->>ES: publish(TEARDOWN_INITIATED) - - STM->>SM: stopAcquisition() - SM-->>STM: acquisitionStopped() - - STM->>COM: closeSessions() - COM-->>STM: sessionsClosed() - - STM->>DP: flushCriticalData() - DP->>DP: persistSensorData() - DP->>DP: persistSystemState() - DP->>DP: persistDiagnostics() - DP-->>STM: flushComplete() - - STM->>STM: releaseResources() - STM->>ES: publish(TEARDOWN_COMPLETE) - - Note over STM,ES: Ready for Target State -``` - -### 2.3 F-SYS-003: Local Human-Machine Interface (HMI) - -**Description:** OLED-based local interface with three-button navigation for system status and diagnostics. - -**Hardware Components:** -- **OLED Display:** 128x64 pixels, I2C interface (SSD1306 compatible) -- **Navigation Buttons:** 3 physical buttons (Up, Down, Select) -- **Status Indicators:** Software-based status display - -**Main Screen Display:** -``` -┌─────────────────────────┐ -│ ASF Sensor Hub v1.0 │ -│ Status: RUNNING │ -│ ─────────────────────── │ -│ WiFi: Connected (75%) │ -│ Sensors: 6/7 Active │ -│ Storage: 2.1GB Free │ -│ Time: 14:32:15 │ -│ │ -│ [SELECT] for Menu │ -└─────────────────────────┘ -``` - -**Menu Structure:** -```mermaid -graph TD - MAIN[Main Screen] --> MENU{Main Menu} - MENU --> DIAG[Diagnostics] - MENU --> SENSORS[Sensors] - MENU --> HEALTH[System Health] - MENU --> NETWORK[Network Status] - MENU --> SERVICE[Service Mode] - - DIAG --> DIAG_ACTIVE[Active Diagnostics] - DIAG --> DIAG_HISTORY[Diagnostic History] - DIAG --> DIAG_CLEAR[Clear Diagnostics] - - SENSORS --> SENSOR_LIST[Sensor List] - SENSORS --> SENSOR_STATUS[Sensor Status] - SENSORS --> SENSOR_DATA[Latest Data] - - HEALTH --> HEALTH_CPU[CPU Usage] - HEALTH --> HEALTH_MEM[Memory Usage] - HEALTH --> HEALTH_STORAGE[Storage Status] - HEALTH --> HEALTH_UPTIME[System Uptime] - - NETWORK --> NET_WIFI[WiFi Status] - NETWORK --> NET_MAIN[Main Hub Conn] - NETWORK --> NET_PEER[Peer Status] - - SERVICE --> SERVICE_AUTH[Authentication] - SERVICE --> SERVICE_LOGS[View Logs] - SERVICE --> SERVICE_REBOOT[System Reboot] -``` - -**Button Navigation Logic:** -- **UP Button:** Navigate up in menus, scroll up in lists -- **DOWN Button:** Navigate down in menus, scroll down in lists -- **SELECT Button:** Enter submenu, confirm action, return to main - -### 2.4 F-SYS-004: Engineering Access Sessions - -**Description:** Secure engineering and diagnostic access for system maintenance and troubleshooting. - -**Session Types:** - -| Session Type | Access Level | Capabilities | Authentication | -|-------------|-------------|--------------|----------------| -| **Diagnostic Session** | Read-only | Log retrieval, status inspection | Basic PIN | -| **Engineering Session** | Read-write | Configuration, controlled commands | Certificate-based | -| **Service Session** | Full access | System control, firmware access | Multi-factor | - -**Supported Access Methods:** -- **Local UART:** Direct serial connection for field service -- **Network Session:** Encrypted connection via Main Hub -- **Local HMI:** Limited diagnostic access via OLED interface - -**Engineering Commands:** -```c -// System information -CMD_GET_SYSTEM_INFO -CMD_GET_SENSOR_STATUS -CMD_GET_DIAGNOSTIC_LOGS -CMD_GET_PERFORMANCE_STATS - -// Configuration management -CMD_GET_MACHINE_CONSTANTS -CMD_UPDATE_MACHINE_CONSTANTS -CMD_VALIDATE_CONFIGURATION -CMD_BACKUP_CONFIGURATION - -// System control -CMD_REBOOT_SYSTEM -CMD_INITIATE_TEARDOWN -CMD_CLEAR_DIAGNOSTICS -CMD_RESET_STATISTICS - -// Debug operations -CMD_ENABLE_DEBUG_LOGGING -CMD_DUMP_MEMORY_USAGE -CMD_TRIGGER_DIAGNOSTIC_TEST -CMD_MONITOR_REAL_TIME -``` - -### 2.5 F-SYS-005: GPIO Discipline and Hardware Management - -**Description:** Centralized GPIO resource management and hardware access control. - -**GPIO Ownership Model:** -```c -typedef enum { - GPIO_OWNER_NONE = 0, - GPIO_OWNER_SENSOR_I2C, - GPIO_OWNER_SENSOR_SPI, - GPIO_OWNER_SENSOR_UART, - GPIO_OWNER_SENSOR_ADC, - GPIO_OWNER_COMMUNICATION, - GPIO_OWNER_STORAGE, - GPIO_OWNER_HMI, - GPIO_OWNER_SYSTEM, - GPIO_OWNER_DEBUG -} gpio_owner_t; - -typedef struct { - uint8_t pin_number; - gpio_owner_t owner; - gpio_mode_t mode; - bool is_allocated; - char description[32]; -} gpio_resource_t; -``` - -**Resource Allocation Rules:** -- Each GPIO pin has single owner at any time -- Ownership must be requested and granted before use -- Automatic release on component shutdown -- Conflict detection and resolution - -## 3. Requirements Coverage - -### 3.1 System Requirements (SR-XXX) - -| Feature | System Requirements | Description | -|---------|-------------------|-------------| -| **F-SYS-001** | SR-SYS-001 | Finite state machine with 11 defined states | -| **F-SYS-002** | SR-SYS-002, SR-SYS-003 | State-aware operation and controlled teardown | -| **F-SYS-003** | SR-SYS-004 | Local HMI with OLED display and button navigation | -| **F-SYS-004** | SR-SYS-005 | Engineering access sessions with authentication | -| **F-SYS-005** | SR-HW-003 | GPIO discipline and hardware resource management | - -### 3.2 Software Requirements (SWR-XXX) - -| Feature | Software Requirements | Implementation Details | -|---------|---------------------|----------------------| -| **F-SYS-001** | SWR-SYS-001, SWR-SYS-002, SWR-SYS-003 | FSM implementation, state validation, transition logic | -| **F-SYS-002** | SWR-SYS-007, SWR-SYS-008, SWR-SYS-009 | Teardown sequence, resource cleanup, completion verification | -| **F-SYS-003** | SWR-SYS-010, SWR-SYS-011, SWR-SYS-012 | OLED driver, button handling, menu navigation | -| **F-SYS-004** | SWR-SYS-013, SWR-SYS-014, SWR-SYS-015 | Session authentication, command interface, access control | -| **F-SYS-005** | SWR-HW-007, SWR-HW-008, SWR-HW-009 | GPIO ownership, access control, conflict prevention | - -## 4. Component Implementation Mapping - -### 4.1 Primary Components - -| Component | Responsibility | Location | -|-----------|---------------|----------| -| **State Manager (STM)** | FSM implementation, state transitions, teardown coordination | `application_layer/business_stack/STM/` | -| **HMI Controller** | OLED display management, button handling, menu navigation | `application_layer/hmi/` | -| **Engineering Session Manager** | Session authentication, command processing, access control | `application_layer/engineering/` | -| **GPIO Manager** | Hardware resource allocation, ownership management | `drivers/gpio_manager/` | - -### 4.2 Supporting Components - -| Component | Support Role | Interface | -|-----------|-------------|-----------| -| **Event System** | State change notifications, component coordination | `application_layer/business_stack/event_system/` | -| **Data Persistence** | State persistence, configuration storage | `application_layer/DP_stack/persistence/` | -| **Diagnostics Task** | System health monitoring, diagnostic reporting | `application_layer/diag_task/` | -| **Security Manager** | Session authentication, access validation | `application_layer/security/` | - -### 4.3 Component Interaction Diagram - -```mermaid -graph TB - subgraph "System Management Feature" - STM[State Manager] - HMI[HMI Controller] - ESM[Engineering Session Manager] - GPIO[GPIO Manager] - end - - subgraph "Core Components" - ES[Event System] - DP[Data Persistence] - DIAG[Diagnostics Task] - SEC[Security Manager] - end - - subgraph "Hardware Interfaces" - OLED[OLED Display] - BUTTONS[Navigation Buttons] - UART[UART Interface] - PINS[GPIO Pins] - end - - STM <--> ES - STM --> DP - STM --> DIAG - - HMI --> OLED - HMI --> BUTTONS - HMI <--> ES - HMI --> DIAG - - ESM --> UART - ESM <--> SEC - ESM <--> STM - ESM --> DP - - GPIO --> PINS - GPIO <--> ES - - ES -.->|State Events| HMI - ES -.->|System Events| ESM - DIAG -.->|Health Data| HMI -``` - -### 4.4 State Management Flow - -```mermaid -sequenceDiagram - participant EXT as External Trigger - participant STM as State Manager - participant ES as Event System - participant COMP as System Components - participant DP as Data Persistence - - Note over EXT,DP: State Transition Request - - EXT->>STM: requestStateTransition(target_state, reason) - STM->>STM: validateTransition(current, target) - - alt Valid Transition - STM->>ES: publish(STATE_TRANSITION_STARTING) - STM->>COMP: prepareForStateChange(target_state) - COMP-->>STM: preparationComplete() - - alt Requires Teardown - STM->>STM: initiateTeardown() - STM->>COMP: stopOperations() - STM->>DP: flushCriticalData() - DP-->>STM: flushComplete() - end - - STM->>STM: transitionToState(target_state) - STM->>ES: publish(STATE_CHANGED, new_state) - STM->>DP: persistSystemState(new_state) - - else Invalid Transition - STM->>ES: publish(STATE_TRANSITION_REJECTED) - STM-->>EXT: transitionRejected(reason) - end -``` - -## 5. Feature Behavior - -### 5.1 Normal Operation Flow - -1. **System Initialization:** - - Power-on self-test and hardware verification - - Load system configuration and machine constants - - Initialize all components and establish communication - - Transition to RUNNING state upon successful initialization - -2. **State Management:** - - Monitor system health and component status - - Process state transition requests from components - - Validate transitions against state machine rules - - Coordinate teardown sequences when required - -3. **HMI Operation:** - - Continuously update main screen with system status - - Process button inputs for menu navigation - - Display diagnostic information and system health - - Provide local access to system functions - -4. **Engineering Access:** - - Authenticate engineering session requests - - Process authorized commands and queries - - Provide secure access to system configuration - - Log all engineering activities for audit - -### 5.2 Error Handling - -| Error Condition | Detection Method | Response Action | -|----------------|------------------|-----------------| -| **Invalid State Transition** | State validation logic | Reject transition, log diagnostic event | -| **Teardown Timeout** | Teardown completion timer | Force transition, log warning | -| **HMI Hardware Failure** | I2C communication failure | Disable HMI, continue operation | -| **Authentication Failure** | Session validation | Reject access, log security event | -| **GPIO Conflict** | Resource allocation check | Deny allocation, report conflict | - -### 5.3 State-Dependent Behavior - -| System State | Feature Behavior | -|-------------|------------------| -| **INIT** | Initialize components, load configuration, establish communication | -| **RUNNING** | Normal state management, full HMI functionality, engineering access | -| **WARNING** | Enhanced monitoring, diagnostic display, limited operations | -| **FAULT** | Minimal operations, fault display, engineering access only | -| **OTA_UPDATE** | Suspend normal operations, display update progress | -| **MC_UPDATE** | Suspend operations, reload configuration after update | -| **TEARDOWN** | Execute teardown sequence, display progress | -| **SERVICE** | Engineering mode, enhanced diagnostic access | -| **SD_DEGRADED** | Continue operations without persistence, display warning | - -## 6. Feature Constraints - -### 6.1 Timing Constraints - -- **State Transition:** Maximum 5 seconds for normal transitions -- **Teardown Sequence:** Maximum 30 seconds for complete teardown -- **HMI Response:** Maximum 200ms for button response -- **Engineering Command:** Maximum 10 seconds for command execution - -### 6.2 Resource Constraints - -- **Memory Usage:** Maximum 16KB for state management data -- **Display Update:** Maximum 50ms for screen refresh -- **GPIO Resources:** Centralized allocation, no conflicts allowed -- **Session Limit:** Maximum 2 concurrent engineering sessions - -### 6.3 Security Constraints - -- **Authentication:** All engineering access must be authenticated -- **Command Validation:** All commands validated before execution -- **Audit Logging:** All engineering activities logged -- **Access Control:** Role-based access to system functions - -## 7. Interface Specifications - -### 7.1 State Manager Public API - -```c -// State management -system_state_t stm_getCurrentState(void); -bool stm_requestStateTransition(system_state_t target_state, transition_reason_t reason); -bool stm_isTransitionValid(system_state_t from_state, system_state_t to_state); -const char* stm_getStateName(system_state_t state); - -// Teardown coordination -bool stm_initiateTeardown(teardown_reason_t reason); -bool stm_isTeardownInProgress(void); -bool stm_isTeardownComplete(void); -teardown_status_t stm_getTeardownStatus(void); - -// Component registration -bool stm_registerStateListener(state_change_callback_t callback); -bool stm_unregisterStateListener(state_change_callback_t callback); -bool stm_registerTeardownParticipant(teardown_participant_t* participant); - -// System control -bool stm_requestSystemReboot(reboot_reason_t reason); -bool stm_requestSystemReset(reset_reason_t reason); -``` - -### 7.2 HMI Controller Public API - -```c -// Display management -bool hmi_initialize(void); -bool hmi_updateMainScreen(const system_status_t* status); -bool hmi_displayMessage(const char* message, uint32_t duration_ms); -bool hmi_displayMenu(const menu_item_t* items, size_t item_count); - -// Button handling -bool hmi_processButtonInput(button_event_t event); -bool hmi_setButtonCallback(button_callback_t callback); - -// Menu navigation -bool hmi_enterMenu(menu_id_t menu_id); -bool hmi_exitMenu(void); -bool hmi_navigateMenu(navigation_direction_t direction); -bool hmi_selectMenuItem(void); - -// Status display -bool hmi_showSystemStatus(const system_status_t* status); -bool hmi_showDiagnostics(const diagnostic_summary_t* diagnostics); -bool hmi_showSensorStatus(const sensor_status_t* sensors); -``` - -### 7.3 Engineering Session API - -```c -// Session management -session_handle_t eng_createSession(session_type_t type, const auth_credentials_t* creds); -bool eng_authenticateSession(session_handle_t session, const auth_token_t* token); -bool eng_closeSession(session_handle_t session); -bool eng_isSessionValid(session_handle_t session); - -// Command execution -bool eng_executeCommand(session_handle_t session, const command_t* cmd, command_result_t* result); -bool eng_querySystemInfo(session_handle_t session, system_info_t* info); -bool eng_getDiagnosticLogs(session_handle_t session, diagnostic_log_t* logs, size_t* count); - -// Configuration access -bool eng_getMachineConstants(session_handle_t session, machine_constants_t* mc); -bool eng_updateMachineConstants(session_handle_t session, const machine_constants_t* mc); -bool eng_validateConfiguration(session_handle_t session, validation_result_t* result); -``` - -## 8. Testing and Validation - -### 8.1 Unit Testing - -- **State Machine:** All state transitions and edge cases -- **Teardown Logic:** Sequence execution and timeout handling -- **HMI Components:** Display updates and button handling -- **GPIO Management:** Resource allocation and conflict detection - -### 8.2 Integration Testing - -- **State Coordination:** Cross-component state awareness -- **Event System Integration:** State change notifications -- **HMI Integration:** Real hardware display and buttons -- **Engineering Access:** Authentication and command execution - -### 8.3 System Testing - -- **Full State Machine:** All states and transitions under load -- **Teardown Scenarios:** OTA, MC update, fault conditions -- **HMI Usability:** Complete menu navigation and display -- **Security Testing:** Authentication bypass attempts - -### 8.4 Acceptance Criteria - -- All 11 system states implemented and functional -- State transitions complete within timing constraints -- Teardown sequences preserve data integrity -- HMI provides complete system visibility -- Engineering access properly authenticated and logged -- GPIO conflicts prevented and resolved - -## 9. Dependencies - -### 9.1 Internal Dependencies - -- **Event System:** State change notifications and coordination -- **Data Persistence:** State and configuration storage -- **Diagnostics Task:** System health monitoring -- **Security Manager:** Authentication and access control - -### 9.2 External Dependencies - -- **ESP-IDF Framework:** GPIO, I2C, UART drivers -- **FreeRTOS:** Task scheduling and synchronization -- **Hardware Components:** OLED display, buttons, GPIO pins -- **Network Stack:** Engineering session communication - -## 10. Future Enhancements - -### 10.1 Planned Improvements - -- **Advanced HMI:** Graphical status displays and charts -- **Remote Management:** Web-based engineering interface -- **Predictive State Management:** AI-based state prediction -- **Enhanced Security:** Biometric authentication support - -### 10.2 Scalability Considerations - -- **Multi-Hub Management:** Coordinated state management -- **Cloud Integration:** Remote state monitoring and control -- **Advanced Diagnostics:** Predictive maintenance integration -- **Mobile Interface:** Smartphone app for field service - ---- - -**Document Status:** Final for Implementation Phase -**Component Dependencies:** Verified against architecture -**Requirements Traceability:** Complete (SR-SYS, SWR-SYS) -**Next Review:** After component implementation \ No newline at end of file diff --git a/draft- to be removed SW/features/README.md b/draft- to be removed SW/features/README.md deleted file mode 100644 index 154e016..0000000 --- a/draft- to be removed SW/features/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# Features Directory -# ASF Sensor Hub (Sub-Hub) System Features - -**Document Type:** Feature Organization Index -**Version:** 1.0 -**Date:** 2025-01-19 - -## Overview - -This directory contains the complete feature specifications for the ASF Sensor Hub system. Each feature is documented with: - -- Feature description and behavior -- Covered System Requirements (SR-XXX) -- Covered Software Requirements (SWR-XXX) -- Component implementation mapping -- Feature-level constraints -- Mermaid diagrams showing component interactions - -## Feature Organization - -### Feature Categories - -| Category | Feature ID Range | Description | -|----------|------------------|-------------| -| **Sensor Data Acquisition** | F-DAQ-001 to F-DAQ-005 | Environmental sensor data collection and processing | -| **Data Quality & Calibration** | F-DQC-001 to F-DQC-005 | Sensor validation, calibration, and quality assurance | -| **Communication** | F-COM-001 to F-COM-005 | Main Hub and peer communication capabilities | -| **Diagnostics & Health Monitoring** | F-DIAG-001 to F-DIAG-004 | System health monitoring and diagnostic reporting | -| **Persistence & Data Management** | F-DATA-001 to F-DATA-005 | Data storage and persistence management | -| **Firmware Update (OTA)** | F-OTA-001 to F-OTA-005 | Over-the-air firmware update capabilities | -| **Security & Safety** | F-SEC-001 to F-SEC-004 | Security enforcement and safety mechanisms | -| **System Management** | F-SYS-001 to F-SYS-005 | System state management and control | -| **Power & Fault Handling** | F-PWR-001 to F-PWR-004 | Power management and fault handling | -| **Hardware Abstraction** | F-HW-001 to F-HW-003 | Hardware interface abstraction | - -### Feature Files - -| Feature File | Features Covered | Component Dependencies | Status | -|--------------|------------------|----------------------|--------| -| `F-DAQ_Sensor_Data_Acquisition.md` | F-DAQ-001 to F-DAQ-005 | Sensor Manager, Sensor Drivers, Event System | ✅ Complete | -| `F-DQC_Data_Quality_Calibration.md` | F-DQC-001 to F-DQC-005 | Machine Constant Manager, Sensor Manager | ✅ Complete | -| `F-COM_Communication.md` | F-COM-001 to F-COM-005 | Main Hub APIs, Network Stack, Event System | ✅ Complete | -| `F-DIAG_Diagnostics_Health.md` | F-DIAG-001 to F-DIAG-004 | Diagnostics Task, Error Handler, Persistence | ✅ Complete | -| `F-DATA_Persistence_Management.md` | F-DATA-001 to F-DATA-005 | Data Pool, Persistence, Storage Drivers | ✅ Complete | -| `F-OTA_Firmware_Update.md` | F-OTA-001 to F-OTA-005 | OTA Manager, State Manager, Security | ✅ Complete | -| `F-SEC_Security_Safety.md` | F-SEC-001 to F-SEC-004 | Security Manager, Boot System, Encryption | ✅ Complete | -| `F-SYS_System_Management.md` | F-SYS-001 to F-SYS-005 | State Manager, HMI, Event System | ✅ Complete | -| `F-PWR_Power_Fault_Handling.md` | F-PWR-001 to F-PWR-002 | Power Manager, Error Handler, Persistence | ✅ Complete | -| `F-HW_Hardware_Abstraction.md` | F-HW-001 to F-HW-002 | Sensor Abstraction Layer, GPIO Manager, Drivers | ✅ Complete | - -## Traceability - -### Requirements Coverage - -- **System Requirements:** All 45 SR-XXX requirements are covered by features -- **Software Requirements:** All 122 SWR-XXX requirements are mapped to features -- **Components:** All components are mapped to implementing features - -### Component Integration - -Each feature document includes: -- **Component Interaction Diagrams:** Mermaid diagrams showing how components work together -- **Interface Definitions:** Clear specification of component interfaces -- **Data Flow:** How data flows between components within the feature -- **State Dependencies:** How the feature behaves in different system states - -## Usage - -1. **For Requirements Analysis:** Use feature documents to understand how requirements are implemented -2. **For Architecture Review:** Use component mappings to understand system structure -3. **For Implementation Planning:** Use component interfaces and interactions for development -4. **For Testing:** Use feature behaviors and constraints for test case development - -## Document Standards - -All feature documents follow: -- ISO/IEC/IEEE 29148:2018 requirements engineering standards -- Consistent formatting and structure -- Complete traceability to requirements -- Mermaid diagrams for visual representation -- Clear component interface specifications - ---- - -**Next Steps:** -1. Review individual feature documents for completeness -2. Validate component mappings against architecture -3. Ensure all requirements are properly traced -4. Update component specifications based on feature requirements \ No newline at end of file