init
This commit is contained in:
273
About ASF.md
Normal file
273
About ASF.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# Project Description
|
||||
|
||||
## Distributed Intelligent Poultry Farm Environmental Control System (DIPFECS)
|
||||
|
||||
## 1\. Purpose of the System
|
||||
|
||||
The purpose of the **Distributed Intelligent Poultry Farm Environmental Control System (DIPFECS)** is to provide **continuous monitoring, real-time control, and data-driven optimization** of indoor poultry farm environments using a **hierarchical IoT architecture**, **edge computing**, and **cloud-based analytics and machine learning (ML)**.
|
||||
|
||||
The system is designed to **maximize animal welfare, production efficiency, energy efficiency, and operational reliability**, while ensuring **scalability across multiple farms and geographical locations**.
|
||||
|
||||
## 2\. System Scope
|
||||
|
||||
The system covers **indoor poultry houses** (broiler, layer, breeder, pullet) and includes:
|
||||
|
||||
* Environmental sensing
|
||||
|
||||
* Data acquisition and validation
|
||||
|
||||
* Local real-time control
|
||||
|
||||
* Actuator management
|
||||
|
||||
* Alarm handling
|
||||
|
||||
* Data logging and analytics
|
||||
|
||||
* Cross-farm optimization via cloud services
|
||||
|
||||
|
||||
The system explicitly **excludes** open-house farms and manual-only operations.
|
||||
|
||||
## 3\. System Architecture Overview
|
||||
|
||||
The system follows a **three-tier hierarchical architecture**:
|
||||
|
||||
1. **Sub-Hub Layer (Sensor Layer)**
|
||||
|
||||
2. **Main Hub Layer (Edge Control Layer)**
|
||||
|
||||
3. **Central Server Layer (Cloud Intelligence Layer)**
|
||||
|
||||
|
||||
Each tier has a **well-defined functional responsibility** and operates independently in case of upstream or downstream communication failures.
|
||||
|
||||
## 4\. System Decomposition
|
||||
|
||||
### 4.1 Sub-Hub Subsystem (SHS)
|
||||
|
||||
**Abbreviation:** SH
|
||||
**Typical Hardware:** ESP32 or equivalent MCU
|
||||
|
||||
#### 4.1.1 Functional Description
|
||||
|
||||
The Sub-Hub Subsystem (SHS) is responsible exclusively for **local data acquisition, basic preprocessing, and mini-calibration** of connected sensors.
|
||||
|
||||
SHS units are deployed in **high density** within each poultry house to provide **spatial granularity** of environmental data.
|
||||
|
||||
#### 4.1.2 Sensor Interfaces
|
||||
|
||||
Each Sub-Hub may interface with one or more of the following sensor types:
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Parameter</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Abbreviation</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Unit</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Air Temperature</p></td><td class="op-uc-table--cell"><p class="op-uc-p">T</p></td><td class="op-uc-table--cell"><p class="op-uc-p">°C</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Relative Humidity</p></td><td class="op-uc-table--cell"><p class="op-uc-p">RH</p></td><td class="op-uc-table--cell"><p class="op-uc-p">%</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Ammonia</p></td><td class="op-uc-table--cell"><p class="op-uc-p">NH₃</p></td><td class="op-uc-table--cell"><p class="op-uc-p">ppm</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Carbon Dioxide</p></td><td class="op-uc-table--cell"><p class="op-uc-p">CO₂</p></td><td class="op-uc-table--cell"><p class="op-uc-p">ppm</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Carbon Monoxide</p></td><td class="op-uc-table--cell"><p class="op-uc-p">CO</p></td><td class="op-uc-table--cell"><p class="op-uc-p">ppm</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Oxygen (optional)</p></td><td class="op-uc-table--cell"><p class="op-uc-p">O₂</p></td><td class="op-uc-table--cell"><p class="op-uc-p">%</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Light Intensity</p></td><td class="op-uc-table--cell"><p class="op-uc-p">LUX</p></td><td class="op-uc-table--cell"><p class="op-uc-p">lux</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Air Velocity (optional)</p></td><td class="op-uc-table--cell"><p class="op-uc-p">AV</p></td><td class="op-uc-table--cell"><p class="op-uc-p">m/s</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Static Pressure (optional)</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SP</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Pa</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Dust Particulate (optional)</p></td><td class="op-uc-table--cell"><p class="op-uc-p">PM₂.₅ / PM₁₀</p></td><td class="op-uc-table--cell"><p class="op-uc-p">µg/m³</p></td></tr></tbody></table></figure>
|
||||
|
||||
#### 4.1.3 Local Processing
|
||||
|
||||
The Sub-Hub shall perform:
|
||||
|
||||
* Sensor sampling
|
||||
|
||||
* Noise filtering
|
||||
|
||||
* Offset correction
|
||||
|
||||
* Basic plausibility checks
|
||||
|
||||
* Timestamping
|
||||
|
||||
|
||||
The Sub-Hub **shall not** perform any control decisions.
|
||||
|
||||
#### 4.1.4 Communication
|
||||
|
||||
* Wireless uplink to Main Hub
|
||||
|
||||
* Supported protocols (configurable):
|
||||
|
||||
* Wi-Fi
|
||||
|
||||
* Zigbee
|
||||
|
||||
* LoRa / LoRaWAN
|
||||
|
||||
* Proprietary RF
|
||||
|
||||
|
||||
### 4.2 Main Hub Subsystem (MHS)
|
||||
|
||||
**Abbreviation:** MH
|
||||
**Location:** One per poultry house / room
|
||||
|
||||
#### 4.2.1 Functional Description
|
||||
|
||||
The Main Hub Subsystem is the **primary real-time control unit** of the poultry house.
|
||||
|
||||
It aggregates sensor data from all Sub-Hubs, executes **control algorithms**, and drives physical actuators through a **wired control interface**.
|
||||
|
||||
#### 4.2.2 Data Aggregation
|
||||
|
||||
The Main Hub shall:
|
||||
|
||||
* Receive data from all connected Sub-Hubs
|
||||
|
||||
* Perform spatial averaging and zoning
|
||||
|
||||
* Detect anomalies and sensor faults
|
||||
|
||||
* Maintain a local historical buffer
|
||||
|
||||
|
||||
#### 4.2.3 Control Functions
|
||||
|
||||
The Main Hub shall execute:
|
||||
|
||||
* Closed-loop environmental control
|
||||
|
||||
* Rule-based logic
|
||||
|
||||
* PID / proportional control
|
||||
|
||||
* Fuzzy logic (optional)
|
||||
|
||||
* ML-assisted parameter adaptation (optional)
|
||||
|
||||
|
||||
#### 4.2.4 Actuator Interfaces
|
||||
|
||||
The Main Hub shall control the following actuators via a Control Board (CB):
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Actuator</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Abbreviation</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Ventilation Fans</p></td><td class="op-uc-table--cell"><p class="op-uc-p">FAN</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Air Inlets / Curtains</p></td><td class="op-uc-table--cell"><p class="op-uc-p">INL</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Heaters (Radiant / Forced)</p></td><td class="op-uc-table--cell"><p class="op-uc-p">HTR</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Cooling Pads / Foggers</p></td><td class="op-uc-table--cell"><p class="op-uc-p">CLG</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Lighting Systems</p></td><td class="op-uc-table--cell"><p class="op-uc-p">LGT</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Feeding Systems</p></td><td class="op-uc-table--cell"><p class="op-uc-p">FDR</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Drinking Systems</p></td><td class="op-uc-table--cell"><p class="op-uc-p">WTR</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Alarm Devices</p></td><td class="op-uc-table--cell"><p class="op-uc-p">ALM</p></td></tr></tbody></table></figure>
|
||||
|
||||
Control signals may include:
|
||||
|
||||
* Relay (ON/OFF)
|
||||
|
||||
* 0–10 V
|
||||
|
||||
* PWM
|
||||
|
||||
* Modbus RTU/TCP
|
||||
|
||||
* CAN Bus
|
||||
|
||||
|
||||
#### 4.2.5 Local Autonomy
|
||||
|
||||
The Main Hub shall maintain **full operational capability** during:
|
||||
|
||||
* Internet loss
|
||||
|
||||
* Cloud service unavailability
|
||||
|
||||
* Partial Sub-Hub failures
|
||||
|
||||
|
||||
### 4.3 Central Server Subsystem (CSS)
|
||||
|
||||
**Abbreviation:** CS
|
||||
**Deployment:** Cloud or Hybrid
|
||||
|
||||
#### 4.3.1 Functional Description
|
||||
|
||||
The Central Server Subsystem provides **cross-farm data aggregation, analytics, and intelligence**.
|
||||
|
||||
It is responsible for **learning from all farms collectively** and improving control strategies continuously.
|
||||
|
||||
#### 4.3.2 Data Management
|
||||
|
||||
The Central Server shall:
|
||||
|
||||
* Store time-series data
|
||||
|
||||
* Maintain farm profiles
|
||||
|
||||
* Support long-term historical analysis
|
||||
|
||||
* Enable benchmarking across farms
|
||||
|
||||
|
||||
#### 4.3.3 Machine Learning & Analytics
|
||||
|
||||
The Central Server shall:
|
||||
|
||||
* Train ML models using aggregated farm data
|
||||
|
||||
* Identify optimal environmental setpoints
|
||||
|
||||
* Detect patterns related to performance, health, and energy
|
||||
|
||||
* Generate optimized control parameters
|
||||
|
||||
|
||||
#### 4.3.4 Feedback Loop
|
||||
|
||||
The Central Server shall:
|
||||
|
||||
* Send updated control parameters or models to Main Hubs
|
||||
|
||||
* Support OTA firmware and configuration updates
|
||||
|
||||
* Allow gradual rollout and rollback of updates
|
||||
|
||||
|
||||
## 5\. Communication Architecture
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Link</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Direction</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Protocol</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Sensors → Sub-Hub</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Wired</p></td><td class="op-uc-table--cell"><p class="op-uc-p">I²C, SPI, UART, Analog</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Sub-Hub → Main Hub</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Wireless</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Wi-Fi / Zigbee / LoRa</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Main Hub → Control Board</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Wired</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Modbus, Relay, CAN</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Main Hub ↔ Central Server</p></td><td class="op-uc-table--cell"><p class="op-uc-p">IP-based</p></td><td class="op-uc-table--cell"><p class="op-uc-p">MQTT / HTTPS / TLS</p></td></tr></tbody></table></figure>
|
||||
|
||||
All external communications shall be **encrypted**.
|
||||
|
||||
## 6\. Alarm and Safety Management
|
||||
|
||||
The system shall support:
|
||||
|
||||
* Threshold-based alarms
|
||||
|
||||
* Rate-of-change alarms
|
||||
|
||||
* Sensor failure alarms
|
||||
|
||||
* Communication failure alarms
|
||||
|
||||
* Power failure alarms
|
||||
|
||||
|
||||
Alarms shall be:
|
||||
|
||||
* Local (audible/visual)
|
||||
|
||||
* Remote (SMS, email, app notification)
|
||||
|
||||
|
||||
## 7\. Scalability and Deployment
|
||||
|
||||
The system shall support:
|
||||
|
||||
* Multiple Sub-Hubs per house
|
||||
|
||||
* Multiple houses per farm
|
||||
|
||||
* Multiple farms per server
|
||||
|
||||
* Global multi-tenant operation
|
||||
|
||||
|
||||
## 8\. Compliance and Industry Alignment
|
||||
|
||||
The system design aligns with:
|
||||
|
||||
* Modern poultry automation practices (Big Dutchman, Fancom, SKOV, Hotraco)
|
||||
|
||||
* Animal welfare standards
|
||||
|
||||
* Environmental monitoring best practices
|
||||
|
||||
* Industrial IoT architectures (Edge + Cloud)
|
||||
|
||||
|
||||
## 9\. System Key Characteristics (Summary)
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Attribute</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Value</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Architecture</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Distributed, Hierarchical</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Control</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Local real-time + Cloud optimization</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Intelligence</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Edge + Central ML</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Reliability</p></td><td class="op-uc-table--cell"><p class="op-uc-p">High (local autonomy)</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Scalability</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Very High</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Vendor Lock-in</p></td><td class="op-uc-table--cell"><p class="op-uc-p">None</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Sensor Density</p></td><td class="op-uc-table--cell"><p class="op-uc-p">High</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Update Mechanism</p></td><td class="op-uc-table--cell"><p class="op-uc-p">OTA</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 10\. Project Vision Statement
|
||||
|
||||
**DIPFECS is designed to become a scalable, intelligent, and adaptive poultry farm control platform that continuously improves environmental control strategies by combining dense sensing, robust local automation, and global data intelligence.**
|
||||
130
System Design/Engineering Review Report.md
Normal file
130
System Design/Engineering Review Report.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Engineering Review Report
|
||||
|
||||
## A. Executive Summary
|
||||
|
||||
### Overall System Maturity Level
|
||||
The ASF Sensor Hub demonstrates a well-structured architecture with clear layering, defined responsibilities, and adherence to embedded system constraints. However, several critical gaps and risks need to be addressed before proceeding to the implementation phase.
|
||||
|
||||
### Major Risks (Top 5)
|
||||
1. **Cross-Feature Conflicts**: Potential timing conflicts between OTA updates and DAQ operations.
|
||||
2. **State Machine Completeness**: Undefined transitions for error handling and degraded states.
|
||||
3. **Data Integrity Risks**: Insufficient guarantees for data persistence during power loss.
|
||||
4. **Security Gaps**: Lack of detailed secure boot and cryptographic key management mechanisms.
|
||||
5. **Scalability Concerns**: Limited provisions for adding new sensor types or features.
|
||||
|
||||
### Go / No-Go Recommendation
|
||||
**No-Go**: Address the identified critical risks and gaps before proceeding to the implementation phase.
|
||||
|
||||
---
|
||||
|
||||
## B. Detailed Findings
|
||||
|
||||
### 1. Architecture
|
||||
|
||||
#### Findings:
|
||||
- **Layering & Separation of Concerns**: Proper abstraction boundaries are defined, but direct hardware access by features bypassing the System Manager is a risk. **Severity: Major**
|
||||
- **State Machine Validity**: Some states (e.g., ERROR, DEGRADED) lack defined transitions and behaviors. **Severity: Critical**
|
||||
|
||||
#### Recommendations:
|
||||
- Enforce strict access controls to hardware and persistence layers.
|
||||
- Define and document all state transitions and behaviors.
|
||||
|
||||
### 2. Requirements
|
||||
|
||||
#### Findings:
|
||||
- **Missing Requirements**: No explicit requirements for handling SD card wear or power loss scenarios. **Severity: Critical**
|
||||
- **Conflicting Requirements**: OTA updates may interfere with real-time DAQ operations. **Severity: Major**
|
||||
|
||||
#### Recommendations:
|
||||
- Add requirements for wear leveling and power loss recovery.
|
||||
- Define OTA timing constraints to avoid conflicts.
|
||||
|
||||
### 3. Performance
|
||||
|
||||
#### Findings:
|
||||
- **Memory Usage Risks**: High-frequency sampling and local filtering may exceed ESP32-S3 memory limits. **Severity: Major**
|
||||
|
||||
#### Recommendations:
|
||||
- Optimize memory usage by profiling and limiting buffer sizes.
|
||||
|
||||
### 4. Reliability
|
||||
|
||||
#### Findings:
|
||||
- **Fault Tolerance**: No defined behavior for sensor failures during runtime. **Severity: Major**
|
||||
|
||||
#### Recommendations:
|
||||
- Implement fallback mechanisms for failed sensors.
|
||||
|
||||
### 5. Security
|
||||
|
||||
#### Findings:
|
||||
- **Secure Boot**: No detailed mechanism for secure boot and firmware authenticity verification. **Severity: Critical**
|
||||
|
||||
#### Recommendations:
|
||||
- Implement secure boot and cryptographic verification for firmware.
|
||||
|
||||
### 6. Maintainability
|
||||
|
||||
#### Findings:
|
||||
- **Scalability**: Adding new sensors requires significant manual effort. **Severity: Minor**
|
||||
|
||||
#### Recommendations:
|
||||
- Use a modular approach for sensor integration.
|
||||
|
||||
---
|
||||
|
||||
## C. Missing / Risky Areas
|
||||
|
||||
### Missing System Requirements
|
||||
- SD card wear leveling.
|
||||
- Power loss recovery mechanisms.
|
||||
|
||||
### Missing System States
|
||||
- Detailed ERROR and DEGRADED state transitions.
|
||||
|
||||
### Missing Failure Handling
|
||||
- Sensor failure fallback mechanisms.
|
||||
|
||||
### Missing Documentation
|
||||
- Secure boot and cryptographic key management.
|
||||
|
||||
---
|
||||
|
||||
## D. Improvement Recommendations
|
||||
|
||||
1. **Architectural Enhancements**:
|
||||
- Enforce strict abstraction boundaries.
|
||||
- Define all state transitions and behaviors.
|
||||
|
||||
2. **Requirement Additions**:
|
||||
- Add requirements for SD card wear leveling and power loss recovery.
|
||||
|
||||
3. **Security Improvements**:
|
||||
- Implement secure boot and cryptographic verification mechanisms.
|
||||
|
||||
4. **Scalability Enhancements**:
|
||||
- Adopt a modular approach for sensor integration.
|
||||
|
||||
---
|
||||
|
||||
## E. Generated Artifacts
|
||||
|
||||
### State Machine Diagram
|
||||
```mermaid
|
||||
graph TD
|
||||
INIT --> IDLE
|
||||
IDLE --> RUNNING
|
||||
RUNNING --> DEGRADED
|
||||
RUNNING --> ERROR
|
||||
DEGRADED --> TEARDOWN
|
||||
ERROR --> TEARDOWN
|
||||
TEARDOWN --> INIT
|
||||
```
|
||||
|
||||
### Cross-Feature Conflict Table
|
||||
| Feature A | Feature B | Conflict Description | Resolution Recommendation |
|
||||
|-----------------|-----------------|-------------------------------|----------------------------------|
|
||||
| OTA | DAQ | Timing conflicts | Define OTA timing constraints |
|
||||
| Persistence | Power Loss | Data corruption risks | Add wear leveling and recovery |
|
||||
|
||||
---
|
||||
252
System Design/Failure_Handling_Model.md
Normal file
252
System Design/Failure_Handling_Model.md
Normal file
@@ -0,0 +1,252 @@
|
||||
# Failure Handling Model Specification
|
||||
|
||||
**Document Type:** Normative System Specification
|
||||
**Scope:** Sensor Hub (Sub-Hub) Fault Detection, Classification, and Recovery
|
||||
**Traceability:** SR-DIAG-001 through SR-DIAG-011, SR-SYS-002, SR-SYS-004
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document defines the fault taxonomy, escalation rules, recovery behaviors, and integration with the system state machine. All components SHALL adhere to this failure handling model.
|
||||
|
||||
## 2. Fault Taxonomy
|
||||
|
||||
### 2.1 Severity Levels
|
||||
|
||||
| Severity | Code | Description | State Impact | Recovery Behavior |
|
||||
|----------|------|-------------|--------------|-------------------|
|
||||
| **INFO** | `DIAG_SEV_INFO` | Informational event, no action required | None | Log only |
|
||||
| **WARNING** | `DIAG_SEV_WARNING` | Non-critical fault, degraded operation | `RUNNING` → `WARNING` | Continue with reduced functionality |
|
||||
| **ERROR** | `DIAG_SEV_ERROR` | Critical fault, feature disabled | Feature-specific | Feature isolation, retry logic |
|
||||
| **FATAL** | `DIAG_SEV_FATAL` | System-critical fault, core functionality disabled | `RUNNING` → `FAULT` | Controlled teardown, recovery attempt |
|
||||
|
||||
### 2.2 Fault Categories
|
||||
|
||||
| Category | Description | Examples | Typical Severity |
|
||||
|----------|-------------|----------|------------------|
|
||||
| **SENSOR** | Sensor hardware or communication failure | Disconnection, out-of-range, non-responsive | WARNING (single), ERROR (multiple), FATAL (all) |
|
||||
| **COMMUNICATION** | Network or protocol failure | Link loss, timeout, authentication failure | WARNING (temporary), ERROR (persistent), FATAL (critical) |
|
||||
| **STORAGE** | Persistence or storage medium failure | SD card failure, NVM corruption, write failure | WARNING (degraded), ERROR (persistent), FATAL (critical) |
|
||||
| **SECURITY** | Security violation or authentication failure | Secure boot failure, key corruption, unauthorized access | FATAL (always) |
|
||||
| **SYSTEM** | System resource or configuration failure | Memory exhaustion, task failure, configuration error | ERROR (recoverable), FATAL (unrecoverable) |
|
||||
| **OTA** | Firmware update failure | Validation failure, transfer error, flash error | ERROR (retry), FATAL (rollback) |
|
||||
| **CALIBRATION** | Calibration or machine constants failure | Invalid MC, calibration error, sensor mismatch | WARNING (single), ERROR (critical) |
|
||||
|
||||
## 3. Diagnostic Code Structure
|
||||
|
||||
### 3.1 Diagnostic Code Format
|
||||
|
||||
```
|
||||
DIAG-<CATEGORY>-<COMPONENT>-<NUMBER>
|
||||
```
|
||||
|
||||
- **CATEGORY:** Two-letter code (SN, CM, ST, SC, SY, OT, CL)
|
||||
- **COMPONENT:** Component identifier (e.g., TEMP, HUM, CO2, NET, SD, OTA)
|
||||
- **NUMBER:** Unique fault number (0001-9999)
|
||||
|
||||
### 3.2 Diagnostic Code Registry
|
||||
|
||||
| Code | Severity | Category | Component | Description |
|
||||
|------|----------|----------|-----------|-------------|
|
||||
| `DIAG-SN-TEMP-0001` | WARNING | SENSOR | Temperature | Temperature sensor disconnected |
|
||||
| `DIAG-SN-TEMP-0002` | ERROR | SENSOR | Temperature | Temperature sensor out of range |
|
||||
| `DIAG-SN-TEMP-0003` | FATAL | SENSOR | Temperature | All temperature sensors failed |
|
||||
| `DIAG-CM-NET-0001` | WARNING | COMMUNICATION | Network | Main Hub link temporarily lost |
|
||||
| `DIAG-CM-NET-0002` | ERROR | COMMUNICATION | Network | Main Hub link persistently lost |
|
||||
| `DIAG-ST-SD-0001` | WARNING | STORAGE | SD Card | SD card write failure (retry successful) |
|
||||
| `DIAG-ST-SD-0002` | ERROR | STORAGE | SD Card | SD card persistent write failure |
|
||||
| `DIAG-ST-SD-0003` | FATAL | STORAGE | SD Card | SD card corruption detected |
|
||||
| `DIAG-SC-BOOT-0001` | FATAL | SECURITY | Secure Boot | Secure boot verification failed |
|
||||
| `DIAG-SY-MEM-0001` | ERROR | SYSTEM | Memory | Memory allocation failure |
|
||||
| `DIAG-OT-FW-0001` | ERROR | OTA | Firmware | Firmware integrity validation failed |
|
||||
| `DIAG-CL-MC-0001` | WARNING | CALIBRATION | Machine Constants | Invalid sensor slot configuration |
|
||||
|
||||
## 4. Fault Detection Rules
|
||||
|
||||
### 4.1 Sensor Fault Detection
|
||||
|
||||
| Condition | Detection Method | Severity Assignment |
|
||||
|-----------|------------------|-------------------|
|
||||
| Sensor disconnected | Hardware presence signal | WARNING (if other sensors available) |
|
||||
| Sensor non-responsive | Communication timeout (3 retries) | ERROR (if critical sensor) |
|
||||
| Sensor out of range | Value validation against limits | WARNING (if single occurrence), ERROR (if persistent) |
|
||||
| All sensors failed | Count of failed sensors = total | FATAL |
|
||||
|
||||
### 4.2 Communication Fault Detection
|
||||
|
||||
| Condition | Detection Method | Severity Assignment |
|
||||
|-----------|------------------|-------------------|
|
||||
| Link temporarily lost | Heartbeat timeout (< 30s) | WARNING |
|
||||
| Link persistently lost | Heartbeat timeout (> 5 minutes) | ERROR |
|
||||
| Authentication failure | Security layer rejection | FATAL |
|
||||
| Protocol error | Message parsing failure (3 consecutive) | ERROR |
|
||||
|
||||
### 4.3 Storage Fault Detection
|
||||
|
||||
| Condition | Detection Method | Severity Assignment |
|
||||
|-----------|------------------|-------------------|
|
||||
| Write failure (retry successful) | Write operation with retry | WARNING |
|
||||
| Write failure (persistent) | Write operation failure (3 retries) | ERROR |
|
||||
| SD card corruption | File system check failure | FATAL |
|
||||
| Storage full | Available space < threshold | WARNING |
|
||||
|
||||
### 4.4 Security Fault Detection
|
||||
|
||||
| Condition | Detection Method | Severity Assignment |
|
||||
|-----------|------------------|-------------------|
|
||||
| Secure boot failure | Boot verification failure | FATAL (always) |
|
||||
| Key corruption | Cryptographic key validation failure | FATAL |
|
||||
| Unauthorized access | Authentication failure (3 attempts) | FATAL |
|
||||
| Message tampering | Integrity check failure | ERROR (if persistent → FATAL) |
|
||||
|
||||
## 5. Escalation Rules
|
||||
|
||||
### 5.1 Severity Escalation
|
||||
|
||||
| Current Severity | Escalation Trigger | New Severity | State Transition |
|
||||
|------------------|-------------------|--------------|-----------------|
|
||||
| INFO | N/A | N/A | None |
|
||||
| WARNING | Same fault persists > 5 minutes | ERROR | `WARNING` → `WARNING` (feature degraded) |
|
||||
| WARNING | Multiple warnings (≥3) | ERROR | `WARNING` → `WARNING` (feature degraded) |
|
||||
| WARNING | Critical feature affected | FATAL | `WARNING` → `FAULT` |
|
||||
| ERROR | Same fault persists > 10 minutes | FATAL | `RUNNING` → `FAULT` |
|
||||
| ERROR | Cascading failures (≥2 features) | FATAL | `RUNNING` → `FAULT` |
|
||||
| FATAL | N/A | N/A | `RUNNING` → `FAULT` |
|
||||
|
||||
### 5.2 Cascading Failure Detection
|
||||
|
||||
A cascading failure is detected when:
|
||||
- Multiple independent features fail simultaneously
|
||||
- Failure in one feature causes failure in another
|
||||
- System resource exhaustion (memory, CPU, storage)
|
||||
|
||||
**Response:** Immediate escalation to FATAL, transition to `FAULT` state.
|
||||
|
||||
## 6. Recovery Behaviors
|
||||
|
||||
### 6.1 Recovery Strategies by Severity
|
||||
|
||||
| Severity | Recovery Strategy | Retry Logic | State Impact |
|
||||
|----------|------------------|-------------|--------------|
|
||||
| **INFO** | None | N/A | None |
|
||||
| **WARNING** | Automatic retry, degraded operation | 3 retries with exponential backoff | Continue in `WARNING` state |
|
||||
| **ERROR** | Feature isolation, automatic retry | 3 retries, then manual intervention | Feature disabled, system continues |
|
||||
| **FATAL** | Controlled teardown, recovery attempt | Single recovery attempt, then manual | `FAULT` → `TEARDOWN` → `INIT` |
|
||||
|
||||
### 6.2 Recovery Time Limits
|
||||
|
||||
| Fault Type | Maximum Recovery Time | Recovery Action |
|
||||
|------------|----------------------|----------------|
|
||||
| Sensor (WARNING) | 5 minutes | Automatic retry, sensor exclusion |
|
||||
| Communication (WARNING) | 30 seconds | Automatic reconnection |
|
||||
| Storage (WARNING) | 10 seconds | Retry write operation |
|
||||
| Sensor (ERROR) | Manual intervention | Sensor marked as failed |
|
||||
| Communication (ERROR) | Manual intervention | Communication feature disabled |
|
||||
| Storage (ERROR) | Manual intervention | Persistence disabled, system continues |
|
||||
| FATAL (any) | 60 seconds | Controlled teardown and recovery attempt |
|
||||
|
||||
### 6.3 Latching Behavior
|
||||
|
||||
| Severity | Latching Rule | Clear Condition |
|
||||
|----------|--------------|----------------|
|
||||
| **INFO** | Not latched | Overwritten by new event |
|
||||
| **WARNING** | Latched until cleared | Fault condition cleared + manual clear OR automatic clear after 1 hour |
|
||||
| **ERROR** | Latched until cleared | Manual clear via diagnostic session OR system reset |
|
||||
| **FATAL** | Latched until cleared | Manual clear via diagnostic session OR system reset |
|
||||
|
||||
## 7. Fault Reporting
|
||||
|
||||
### 7.1 Reporting Channels
|
||||
|
||||
| Severity | Local HMI | Diagnostic Log | Main Hub | Diagnostic Session |
|
||||
|----------|-----------|----------------|----------|-------------------|
|
||||
| **INFO** | Optional | Yes | No | Yes |
|
||||
| **WARNING** | Yes (status indicator) | Yes | Yes (periodic) | Yes |
|
||||
| **ERROR** | Yes (status indicator) | Yes | Yes (immediate) | Yes |
|
||||
| **FATAL** | Yes (status indicator) | Yes | Yes (immediate) | Yes |
|
||||
|
||||
### 7.2 Diagnostic Event Structure
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
uint32_t diagnostic_code; // Unique diagnostic code
|
||||
diag_severity_t severity; // INFO, WARNING, ERROR, FATAL
|
||||
uint64_t timestamp; // System timestamp (microseconds)
|
||||
const char* source_component; // Component identifier
|
||||
uint32_t occurrence_count; // Number of occurrences
|
||||
bool is_latched; // Latching status
|
||||
fault_category_t category; // SENSOR, COMMUNICATION, etc.
|
||||
} diagnostic_event_t;
|
||||
```
|
||||
|
||||
## 8. Integration with State Machine
|
||||
|
||||
### 8.1 Fault-to-State Mapping
|
||||
|
||||
| Fault Severity | Current State | Target State | Transition Trigger |
|
||||
|----------------|---------------|--------------|-------------------|
|
||||
| INFO | Any | Same | None (no state change) |
|
||||
| WARNING | `RUNNING` | `WARNING` | First WARNING fault |
|
||||
| WARNING | `WARNING` | `WARNING` | Additional WARNING (latched) |
|
||||
| ERROR | `RUNNING` | `RUNNING` | Feature isolation, continue |
|
||||
| ERROR | `WARNING` | `WARNING` | Feature isolation, continue |
|
||||
| FATAL | `RUNNING` | `FAULT` | First FATAL fault |
|
||||
| FATAL | `WARNING` | `FAULT` | Escalation to FATAL |
|
||||
| FATAL | `FAULT` | `FAULT` | Additional FATAL (latched) |
|
||||
|
||||
### 8.2 State-Dependent Fault Handling
|
||||
|
||||
| State | Fault Handling Behavior |
|
||||
|-------|------------------------|
|
||||
| `INIT` | Boot-time faults → `BOOT_FAILURE` if security-related |
|
||||
| `RUNNING` | Full fault detection and handling |
|
||||
| `WARNING` | Fault escalation monitoring, recovery attempts |
|
||||
| `FAULT` | Fault logging only, recovery attempt preparation |
|
||||
| `OTA_PREP` | OTA-related faults only, others deferred |
|
||||
| `OTA_UPDATE` | OTA progress faults only |
|
||||
| `TEARDOWN` | Fault logging only, no new fault detection |
|
||||
| `SERVICE` | Fault inspection only, no new fault detection |
|
||||
|
||||
## 9. Error Handler Responsibilities
|
||||
|
||||
The Error Handler component SHALL:
|
||||
1. Receive fault reports from all components
|
||||
2. Classify faults according to taxonomy
|
||||
3. Determine severity and escalation
|
||||
4. Trigger state transitions when required
|
||||
5. Manage fault latching and clearing
|
||||
6. Coordinate recovery attempts
|
||||
7. Report faults to diagnostics and Main Hub
|
||||
|
||||
## 10. Traceability
|
||||
|
||||
- **SR-DIAG-001:** Implemented via diagnostic code framework
|
||||
- **SR-DIAG-002:** Implemented via unique diagnostic code assignment
|
||||
- **SR-DIAG-003:** Implemented via severity classification
|
||||
- **SR-DIAG-004:** Implemented via timestamp and source association
|
||||
- **SR-SYS-002:** Implemented via fault-to-state mapping
|
||||
- **SR-SYS-004:** Implemented via FATAL fault → TEARDOWN transition
|
||||
|
||||
## 11. Mermaid Fault Escalation Diagram
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
FaultDetected[Fault Detected] --> ClassifySeverity{Classify Severity}
|
||||
ClassifySeverity -->|INFO| LogOnly[Log Only]
|
||||
ClassifySeverity -->|WARNING| CheckState1{Current State?}
|
||||
ClassifySeverity -->|ERROR| IsolateFeature[Isolate Feature]
|
||||
ClassifySeverity -->|FATAL| TriggerFaultState[Trigger FAULT State]
|
||||
|
||||
CheckState1 -->|RUNNING| TransitionWarning[Transition to WARNING]
|
||||
CheckState1 -->|WARNING| LatchWarning[Latch Warning]
|
||||
|
||||
IsolateFeature --> RetryLogic{Retry Logic}
|
||||
RetryLogic -->|Success| ClearError[Clear Error]
|
||||
RetryLogic -->|Failure| EscalateToFatal{Escalate?}
|
||||
EscalateToFatal -->|Yes| TriggerFaultState
|
||||
EscalateToFatal -->|No| ManualIntervention[Manual Intervention]
|
||||
|
||||
TriggerFaultState --> TeardownSequence[Initiate Teardown]
|
||||
TeardownSequence --> RecoveryAttempt{Recovery Attempt}
|
||||
RecoveryAttempt -->|Success| ResetToInit[Reset to INIT]
|
||||
RecoveryAttempt -->|Failure| ManualIntervention
|
||||
```
|
||||
120
System Design/Features/Cross-Feature Constraints.md
Normal file
120
System Design/Features/Cross-Feature Constraints.md
Normal file
@@ -0,0 +1,120 @@
|
||||
## 1\. Purpose
|
||||
|
||||
This document defines **cross-feature constraints** that apply across multiple system features and components. These constraints ensure consistent behavior, prevent architectural violations, and reduce integration risk.
|
||||
|
||||
Cross-feature constraints are **mandatory rules** that all future software design and implementation must comply with.
|
||||
|
||||
## 2\. Architectural Constraints
|
||||
|
||||
### CFC-ARCH-01: Layered Architecture Enforcement
|
||||
|
||||
* Application logic shall not access hardware directly.
|
||||
|
||||
* All hardware access shall be performed via Drivers and OSAL layers.
|
||||
|
||||
* Persistence access shall only be performed through the DP component.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
DAQ, DQC, DATA, DIAG, SYS, OTA, SEC
|
||||
|
||||
### CFC-ARCH-02: State-Aware Feature Execution
|
||||
|
||||
* All features shall be aware of the current system state.
|
||||
|
||||
* Features shall not execute actions that are invalid for the current state.
|
||||
|
||||
|
||||
**Examples:**
|
||||
|
||||
* DAQ shall not start sampling during OTA\_UPDATE.
|
||||
|
||||
* Communication shall be limited during TEARDOWN.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
SYS, DAQ, COM, OTA, DATA
|
||||
|
||||
## 3\. Concurrency & Timing Constraints
|
||||
|
||||
### CFC-TIME-01: Non-Blocking Operation
|
||||
|
||||
* Sensor acquisition, communication, and UI updates shall be non-blocking.
|
||||
|
||||
* Blocking operations shall be isolated in controlled system services (e.g., persistence task).
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
DAQ, COM, SYS
|
||||
|
||||
### CFC-TIME-02: Deterministic Task Behavior
|
||||
|
||||
* Time-critical tasks (sensor acquisition, watchdog servicing) shall have deterministic execution time.
|
||||
|
||||
* Dynamic memory allocation during runtime shall be minimized or prohibited in critical paths.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
DAQ, SYS, DIAG
|
||||
|
||||
## 4\. Data & Persistence Constraints
|
||||
|
||||
### CFC-DATA-01: Single Source of Truth
|
||||
|
||||
* Runtime and persistent data shall be owned and managed by the DP component.
|
||||
|
||||
* No feature shall maintain private persistent copies of shared system data.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
DATA, DAQ, DIAG, SYS, OTA
|
||||
|
||||
### CFC-DATA-02: Data Consistency During Transitions
|
||||
|
||||
* No data write operations shall occur during teardown unless explicitly authorized by the System Manager.
|
||||
|
||||
* Persistence completion shall be confirmed before state transitions.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
SYS, DATA, OTA
|
||||
|
||||
## 5\. Security Constraints
|
||||
|
||||
### CFC-SEC-01: Security First Initialization
|
||||
|
||||
* Secure boot and flash protection shall be enabled before any application-level logic executes.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
SEC, SYS
|
||||
|
||||
### CFC-SEC-02: Encrypted Channels Only
|
||||
|
||||
* OTA, diagnostics, and data transmission shall only occur over encrypted and authenticated channels.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
COM, OTA, DIAG, SEC
|
||||
|
||||
## 6\. HMI & Debug Constraints
|
||||
|
||||
### CFC-HMI-01: Read-Only Local UI
|
||||
|
||||
* The OLED HMI shall not allow configuration changes that affect system safety or security.
|
||||
|
||||
* Configuration updates shall only be accepted via authenticated communication channels.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
SYS, SEC
|
||||
|
||||
### CFC-DBG-01: Debug Isolation
|
||||
|
||||
* Debug and engineering sessions shall not interfere with normal system operation.
|
||||
|
||||
* Debug commands shall respect system state restrictions.
|
||||
|
||||
|
||||
**Impacted Features:**
|
||||
SYS, DIAG, SEC
|
||||
359
System Design/Features/Features.md
Normal file
359
System Design/Features/Features.md
Normal file
@@ -0,0 +1,359 @@
|
||||
# **ASF Sensor Hub – Feature Definition Document**
|
||||
|
||||
*(Global, Feature-Based, Architecture-Neutral)*
|
||||
|
||||
This document defines the **system features** of the ASF Sensor Hub subsystem, organized by functional categories.
|
||||
It is intended to be used as:
|
||||
|
||||
* A **feature baseline** in ALM
|
||||
* Input to **system requirements derivation**
|
||||
* Reference for **architecture and software design**
|
||||
* Traceability anchor to IEC 61508 / IEC 61499 style decomposition later
|
||||
|
||||
> ⚠️ **Important Scope Note**
|
||||
> This document covers **ONLY the Sensor Hub (Sub-Hub)** based on **ESP32-S3**.
|
||||
> Main Hub, Cloud, Farm Control Logic are **explicitly out of scope**.
|
||||
|
||||
---
|
||||
|
||||
## **1. System Context Overview**
|
||||
|
||||
The ASF Sensor Hub is a **distributed sensing node** deployed inside a poultry house.
|
||||
Its primary responsibilities are:
|
||||
|
||||
* Acquisition of multiple environmental sensors
|
||||
* 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
|
||||
|
||||
The Sensor Hub operates as an **autonomous embedded system** with defined lifecycle states.
|
||||
|
||||
---
|
||||
|
||||
## **2. Feature Categorization Overview**
|
||||
|
||||
The system features are grouped into the following categories:
|
||||
|
||||
1. **Sensor Data Acquisition Features**
|
||||
2. **Data Quality & Calibration Features**
|
||||
3. **Communication Features**
|
||||
4. **Diagnostics & Health Monitoring Features**
|
||||
5. **Persistence & Data Management Features**
|
||||
6. **Firmware Update (OTA) Features**
|
||||
7. **Security & Safety Features**
|
||||
8. **System Management Features**
|
||||
|
||||
Each feature is described at a **functional level** (WHAT the system does, not HOW).
|
||||
|
||||
---
|
||||
|
||||
## **3. Sensor Data Acquisition Features**
|
||||
|
||||
### **F-DAQ-01: Multi-Sensor Data Acquisition**
|
||||
|
||||
The system provides the capability to acquire data from multiple environmental sensors connected to the Sensor Hub hardware.
|
||||
|
||||
Supported sensor types include:
|
||||
|
||||
* Temperature
|
||||
* Humidity
|
||||
* Carbon Dioxide (CO₂)
|
||||
* Ammonia (NH₃)
|
||||
* Volatile Organic Compounds (VOC)
|
||||
* Particulate Matter (PM)
|
||||
* Light Intensity
|
||||
|
||||
---
|
||||
|
||||
### **F-DAQ-02: High-Frequency Sampling and Local Filtering**
|
||||
|
||||
The system provides local preprocessing of sensor data by:
|
||||
|
||||
* Sampling each sensor multiple times per acquisition cycle
|
||||
* Applying a fast local filtering mechanism
|
||||
* Producing a single validated value per sensor per cycle
|
||||
|
||||
Filtering algorithms are **pluggable and configurable**.
|
||||
|
||||
---
|
||||
|
||||
### **F-DAQ-03: Timestamped Sensor Data Generation**
|
||||
|
||||
The system provides timestamped sensor data using a synchronized local time source.
|
||||
|
||||
Each sensor record includes:
|
||||
|
||||
* Sensor identifier
|
||||
* Measured value
|
||||
* Timestamp
|
||||
* Data validity status
|
||||
|
||||
---
|
||||
|
||||
## **4. Data Quality & Calibration Features**
|
||||
|
||||
### **F-DQC-01: Automatic Sensor Detection**
|
||||
|
||||
The system provides automatic detection of sensor presence based on dedicated hardware detection signals.
|
||||
|
||||
Key characteristics:
|
||||
|
||||
* Each sensor slot is type-specific
|
||||
* Sensor presence is detected during initialization and runtime
|
||||
* Only detected sensors are initialized and sampled
|
||||
|
||||
---
|
||||
|
||||
### **F-DQC-02: Sensor Type Enforcement**
|
||||
|
||||
The system enforces sensor-slot compatibility to prevent incorrect sensor usage.
|
||||
|
||||
Each physical slot:
|
||||
|
||||
* Accepts only one sensor type
|
||||
* Is mapped to a predefined sensor class in software
|
||||
|
||||
---
|
||||
|
||||
### **F-DQC-03: Sensor Failure Detection**
|
||||
|
||||
The system provides detection of sensor failures, including:
|
||||
|
||||
* Communication errors
|
||||
* Out-of-range values
|
||||
* Non-responsive sensors
|
||||
|
||||
Detected failures are classified and reported.
|
||||
|
||||
---
|
||||
|
||||
### **F-DQC-04: Machine Constants & Calibration Management**
|
||||
|
||||
The system provides a Machine Constants (MC) mechanism responsible for:
|
||||
|
||||
* Defining installed sensor types
|
||||
* Holding sensor calibration parameters
|
||||
* Defining communication parameters
|
||||
* Defining system identity parameters
|
||||
|
||||
MC data is persistent and reloadable.
|
||||
|
||||
---
|
||||
|
||||
## **5. Communication Features**
|
||||
|
||||
### **F-COM-01: Main Hub Communication**
|
||||
|
||||
The system provides bidirectional communication with a Main Hub to:
|
||||
|
||||
* Send sensor data
|
||||
* Send diagnostics information
|
||||
* Receive configuration updates
|
||||
* Receive firmware updates
|
||||
|
||||
---
|
||||
|
||||
### **F-COM-02: On-Demand Data Broadcasting**
|
||||
|
||||
The system provides on-demand transmission of the most recent sensor dataset upon request from the Main Hub.
|
||||
|
||||
---
|
||||
|
||||
### **F-COM-03: Peer Sensor Hub Communication**
|
||||
|
||||
The system provides limited peer-to-peer communication between Sensor Hubs for:
|
||||
|
||||
* Connectivity checks
|
||||
* Time synchronization support
|
||||
* Basic status exchange
|
||||
|
||||
This feature is **on-demand and optional**.
|
||||
|
||||
---
|
||||
|
||||
## **6. Diagnostics & Health Monitoring Features**
|
||||
|
||||
### **F-DIAG-01: Diagnostic Code Management**
|
||||
|
||||
The system provides structured diagnostics with:
|
||||
|
||||
* Diagnostic codes
|
||||
* Severity levels
|
||||
* Root cause hierarchy
|
||||
* Timestamping
|
||||
|
||||
---
|
||||
|
||||
### **F-DIAG-02: Diagnostic Data Storage**
|
||||
|
||||
The system provides persistent storage of diagnostic events for post-analysis.
|
||||
|
||||
---
|
||||
|
||||
### **F-DIAG-03: Diagnostic Session**
|
||||
|
||||
The system provides a diagnostic session allowing engineers to:
|
||||
|
||||
* Retrieve diagnostic data
|
||||
* Inspect system health
|
||||
* Clear diagnostic records
|
||||
|
||||
---
|
||||
|
||||
## **7. Persistence & Data Management Features**
|
||||
|
||||
### **F-DATA-01: Persistent Sensor Data Storage**
|
||||
|
||||
The system provides persistent storage of sensor data in non-volatile memory (SD Card).
|
||||
|
||||
---
|
||||
|
||||
### **F-DATA-02: Data Persistence Abstraction (DP Component)**
|
||||
|
||||
The system provides a Data Persistence (DP) component responsible for:
|
||||
|
||||
* Abstracting storage media (SD / NVM)
|
||||
* Managing write/read operations
|
||||
* Ensuring data integrity
|
||||
|
||||
---
|
||||
|
||||
### **F-DATA-03: Safe Data Handling During State Transitions**
|
||||
|
||||
The system ensures that all critical data is safely stored before:
|
||||
|
||||
* Firmware update
|
||||
* Configuration update
|
||||
* System teardown
|
||||
* Reset or restart
|
||||
|
||||
---
|
||||
|
||||
## **8. Firmware Update (OTA) Features**
|
||||
|
||||
### **F-OTA-01: OTA Update Negotiation**
|
||||
|
||||
The system provides an OTA handshake mechanism with the Main Hub to:
|
||||
|
||||
* Acknowledge update availability
|
||||
* Signal readiness for update
|
||||
|
||||
---
|
||||
|
||||
### **F-OTA-02: Firmware Reception and Storage**
|
||||
|
||||
The system provides secure reception of firmware images and temporary storage on SD Card.
|
||||
|
||||
---
|
||||
|
||||
### **F-OTA-03: Firmware Integrity Validation**
|
||||
|
||||
The system validates firmware integrity using checksum or CRC before activation.
|
||||
|
||||
---
|
||||
|
||||
### **F-OTA-04: Safe Firmware Activation**
|
||||
|
||||
The system provides controlled firmware flashing and rollback-safe activation.
|
||||
|
||||
---
|
||||
|
||||
## **9. Security & Safety Features**
|
||||
|
||||
### **F-SEC-01: Secure Boot**
|
||||
|
||||
The system provides secure boot functionality to ensure only authenticated firmware is executed.
|
||||
|
||||
---
|
||||
|
||||
### **F-SEC-02: Secure Flash Storage**
|
||||
|
||||
The system provides encrypted flash storage for sensitive assets.
|
||||
|
||||
---
|
||||
|
||||
### **F-SEC-03: Encrypted Communication**
|
||||
|
||||
The system provides encrypted communication channels for all external data exchange.
|
||||
|
||||
---
|
||||
|
||||
## **10. System Management Features**
|
||||
|
||||
### **F-SYS-01: System State Management**
|
||||
|
||||
The system provides explicit lifecycle states including:
|
||||
|
||||
* Initialization
|
||||
* Normal Operation
|
||||
* Degraded Operation
|
||||
* Update Mode
|
||||
* Fault Mode
|
||||
* Teardown Mode
|
||||
|
||||
---
|
||||
|
||||
### **F-SYS-02: Controlled Teardown Mechanism**
|
||||
|
||||
The system provides a controlled teardown mechanism that:
|
||||
|
||||
* Stops sensor acquisition
|
||||
* Flushes all critical data
|
||||
* Ensures persistent storage consistency
|
||||
* Prepares the system for update or shutdown
|
||||
|
||||
---
|
||||
|
||||
### **F-SYS-03: Status Indication**
|
||||
|
||||
The system provides visual status indicators:
|
||||
|
||||
* Green: Normal operation
|
||||
* Yellow: Warning state
|
||||
* Red: Fatal error state
|
||||
|
||||
---
|
||||
|
||||
### **F-SYS-04: Debug & Engineering Sessions**
|
||||
|
||||
The system provides engineering access sessions allowing:
|
||||
|
||||
* Log inspection
|
||||
* MC file inspection and update
|
||||
* Command execution
|
||||
* Controlled debugging
|
||||
|
||||
---
|
||||
|
||||
## **11. Feature Relationship Overview (High-Level)**
|
||||
|
||||
```
|
||||
Sensor Acquisition
|
||||
↓
|
||||
Data Quality & Calibration
|
||||
↓
|
||||
Data Persistence
|
||||
↓
|
||||
Communication
|
||||
↓
|
||||
Diagnostics & System Management
|
||||
↓
|
||||
OTA / Security / Safety
|
||||
```
|
||||
|
||||
* **Machine Constants** affect:
|
||||
|
||||
* Sensor initialization
|
||||
* Calibration
|
||||
* Communication
|
||||
* **Diagnostics** span all features
|
||||
* **Teardown** is a cross-cutting mechanism triggered by:
|
||||
|
||||
* OTA
|
||||
* MC update
|
||||
* Fatal faults
|
||||
|
||||
---
|
||||
|
||||
83
System Design/Features/System Assumptions & Limitations.md
Normal file
83
System Design/Features/System Assumptions & Limitations.md
Normal file
@@ -0,0 +1,83 @@
|
||||
## 1\. System Assumptions
|
||||
|
||||
### SA-01: Deployment Environment
|
||||
|
||||
* The Sensor Hub operates in an indoor poultry farm environment.
|
||||
|
||||
* Environmental conditions may include high humidity, dust, and ammonia presence.
|
||||
|
||||
|
||||
### SA-02: Power Availability
|
||||
|
||||
* The Sensor Hub is assumed to have continuous power.
|
||||
|
||||
* Short power interruptions may occur; system shall recover gracefully.
|
||||
|
||||
|
||||
### SA-03: Network Connectivity
|
||||
|
||||
* Wireless connectivity to the Main Hub may be intermittent.
|
||||
|
||||
* The Sensor Hub shall operate autonomously when disconnected.
|
||||
|
||||
|
||||
### SA-04: Trusted Provisioning
|
||||
|
||||
* Devices are assumed to be provisioned securely during manufacturing or installation.
|
||||
|
||||
* Cryptographic keys are assumed to be injected via a secure process.
|
||||
|
||||
|
||||
### SA-05: Time Synchronization
|
||||
|
||||
* System time is assumed to be synchronized periodically by the Main Hub.
|
||||
|
||||
* Temporary time drift is acceptable.
|
||||
|
||||
|
||||
## 2\. System Limitations
|
||||
|
||||
### SL-01: Local Processing Limits
|
||||
|
||||
* The Sensor Hub performs lightweight preprocessing only.
|
||||
|
||||
* Complex analytics and AI models are out of scope.
|
||||
|
||||
|
||||
### SL-02: User Interface Constraints
|
||||
|
||||
* The OLED display is intended for monitoring and diagnostics only.
|
||||
|
||||
* It is not a full configuration or management interface.
|
||||
|
||||
|
||||
### SL-03: Physical Security
|
||||
|
||||
* The Sensor Hub does not include physical tamper detection.
|
||||
|
||||
* Physical access is assumed to be restricted.
|
||||
|
||||
|
||||
### SL-04: Storage Constraints
|
||||
|
||||
* SD card storage capacity is finite.
|
||||
|
||||
* Data retention policies may result in data overwrite.
|
||||
|
||||
|
||||
### SL-05: Safety Classification
|
||||
|
||||
* The system is not classified as a safety-critical life-support system.
|
||||
|
||||
* Failures may impact farm performance but not human safety directly.
|
||||
|
||||
|
||||
## 3\. External Dependencies
|
||||
|
||||
* ESP32-S3 hardware platform
|
||||
|
||||
* ESP-IDF framework
|
||||
|
||||
* Supported sensors and communication modules
|
||||
|
||||
* Main Hub availability for OTA and configuration updates
|
||||
151
System Design/Features/[COM] Communication Features.md
Normal file
151
System Design/Features/[COM] Communication Features.md
Normal file
@@ -0,0 +1,151 @@
|
||||
<macro class="toc op-uc-placeholder op-uc-toc">
|
||||
</macro>
|
||||
|
||||
# Feature Engineering Specification
|
||||
|
||||
## Communication Features
|
||||
|
||||
**Feature Group ID:** FG-COM
|
||||
**Scope:** Sensor Hub (Sub-Hub only)
|
||||
**Target Platform:** ESP32-S3–based Sensor Hub
|
||||
**Applies To:** Indoor poultry farm sensor hubs
|
||||
**Dependencies:**
|
||||
|
||||
* Sensor Data Acquisition (FG-DAQ)
|
||||
|
||||
* Data Quality & Calibration (FG-DQC)
|
||||
|
||||
* Diagnostics & Health Monitoring (FG-DIAG)
|
||||
|
||||
* Security & Safety Features (FG-SEC)
|
||||
|
||||
|
||||
## 1\. Purpose and Objectives
|
||||
|
||||
The **Communication Features** define how the Sensor Hub exchanges data and control information with external entities. These features ensure that sensor data, diagnostics, configuration updates, and control requests are transferred in a **reliable, secure, and deterministic manner**.
|
||||
|
||||
The communication layer is designed to:
|
||||
|
||||
* Support hierarchical farm architecture (Sensor Hub → Main Hub)
|
||||
|
||||
* Enable on-demand and event-driven data transfer
|
||||
|
||||
* Allow limited peer-to-peer communication between Sensor Hubs
|
||||
|
||||
* Maintain robustness under intermittent connectivity
|
||||
|
||||
|
||||
## 2\. Feature Overview and Relationships
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature Name</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Primary Objective</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Related Features</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-COM-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Main Hub Communication</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Primary uplink/downlink with Main Hub</p></td><td class="op-uc-table--cell"><p class="op-uc-p">OTA, Diagnostics, MC Management</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-COM-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">On-Demand Data Broadcasting</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Provide latest data upon request</p></td><td class="op-uc-table--cell"><p class="op-uc-p">DAQ, DP Stack</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-COM-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Peer Sensor Hub Communication</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Limited hub-to-hub coordination</p></td><td class="op-uc-table--cell"><p class="op-uc-p">System Management</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 3\. Functional Feature Descriptions
|
||||
|
||||
### 3.1 F-COM-01: Main Hub Communication
|
||||
|
||||
**Description**
|
||||
The Sensor Hub shall establish and maintain a bidirectional communication channel with the Main Hub. This channel is used for transmitting sensor data, diagnostics, alarms, and status information, as well as receiving commands, firmware updates, and Machine Constants updates.
|
||||
|
||||
The communication mechanism shall support reliable delivery, message integrity verification, and connection state monitoring.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Bidirectional communication
|
||||
|
||||
* Command and response handling
|
||||
|
||||
* Diagnostics and status reporting
|
||||
|
||||
* Integration with OTA and MC updates
|
||||
|
||||
|
||||
### 3.2 F-COM-02: On-Demand Data Broadcasting
|
||||
|
||||
**Description**
|
||||
The Sensor Hub shall support on-demand transmission of the most recent sensor data upon request from the Main Hub. This allows the Main Hub to query real-time conditions without waiting for periodic reporting cycles.
|
||||
|
||||
Data broadcasts include timestamped sensor values and associated validity status.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Request/response data exchange
|
||||
|
||||
* Latest-value data delivery
|
||||
|
||||
* Timestamp and validity inclusion
|
||||
|
||||
* Low-latency response
|
||||
|
||||
|
||||
### 3.3 F-COM-03: Peer Sensor Hub Communication
|
||||
|
||||
**Description**
|
||||
Sensor Hubs shall be capable of limited peer-to-peer communication for coordination purposes such as connectivity checks, time synchronization assistance, or basic status exchange.
|
||||
|
||||
Peer communication is optional, demand-driven, and does not replace the primary communication path through the Main Hub.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Hub-to-hub message exchange
|
||||
|
||||
* Minimal command set
|
||||
|
||||
* No dependency on centralized infrastructure
|
||||
|
||||
* Isolation from control logic
|
||||
|
||||
|
||||
## 4\. System Requirements (Formal SHALL Statements)
|
||||
|
||||
### 4.1 Main Hub Communication
|
||||
|
||||
**SR-COM-001**
|
||||
The system shall support bidirectional communication between the Sensor Hub and the Main Hub.
|
||||
|
||||
**SR-COM-002**
|
||||
The system shall transmit sensor data, diagnostics, and system status information to the Main Hub.
|
||||
|
||||
**SR-COM-003**
|
||||
The system shall receive commands, configuration updates, and firmware update requests from the Main Hub.
|
||||
|
||||
**SR-COM-004**
|
||||
The system shall monitor and report the communication link status with the Main Hub.
|
||||
|
||||
### 4.2 On-Demand Data Broadcasting
|
||||
|
||||
**SR-COM-005**
|
||||
The system shall support on-demand requests from the Main Hub for sensor data.
|
||||
|
||||
**SR-COM-006**
|
||||
The system shall respond to on-demand data requests with the most recent timestamped sensor data.
|
||||
|
||||
**SR-COM-007**
|
||||
The system shall include data validity and sensor status information in on-demand responses.
|
||||
|
||||
### 4.3 Peer Sensor Hub Communication
|
||||
|
||||
**SR-COM-008**
|
||||
The system shall support limited peer-to-peer communication between Sensor Hubs.
|
||||
|
||||
**SR-COM-009**
|
||||
The system shall allow peer communication for basic coordination functions such as connectivity checks or time synchronization.
|
||||
|
||||
**SR-COM-010**
|
||||
The system shall ensure that peer Sensor Hub communication does not interfere with Main Hub communication or control operations.
|
||||
|
||||
## 5\. Traceability Mapping
|
||||
|
||||
### 5.1 Feature → System Requirement Mapping
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">System Requirements</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-COM-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-COM-001, SR-COM-002, SR-COM-003, SR-COM-004</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-COM-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-COM-005, SR-COM-006, SR-COM-007</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-COM-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-COM-008, SR-COM-009, SR-COM-010</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 6\. Engineering Notes and Constraints
|
||||
|
||||
* Communication protocol selection (Wi-Fi, ESP-NOW, proprietary RF, etc.) is deferred to the Software Requirements phase.
|
||||
|
||||
* Security (authentication, encryption) is defined under **Security & Safety Features**.
|
||||
|
||||
* Communication failures shall trigger diagnostics events but shall not block sensor acquisition.
|
||||
|
||||
|
||||
##
|
||||
299
System Design/Features/[DAQ] Sensor Data Acquisition Features.md
Normal file
299
System Design/Features/[DAQ] Sensor Data Acquisition Features.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# **ASF Sensor Hub**
|
||||
|
||||
## **Feature Engineering Specification**
|
||||
|
||||
## **Sensor Data Acquisition Features**
|
||||
|
||||
## **1\. Feature Overview**
|
||||
|
||||
### **Feature Name**
|
||||
|
||||
Sensor Data Acquisition Features
|
||||
|
||||
### **Feature ID**
|
||||
|
||||
FEAT-DAQ
|
||||
|
||||
### **Subsystem**
|
||||
|
||||
ASF Sensor Hub (Sub-Hub)
|
||||
|
||||
### **Target Platform**
|
||||
|
||||
ESP32-S3–based embedded system
|
||||
|
||||
### **Scope**
|
||||
|
||||
This feature defines the capabilities of the Sensor Hub related to:
|
||||
|
||||
* Environmental sensor data acquisition
|
||||
|
||||
* Local preprocessing and filtering
|
||||
|
||||
* Timestamping and preparation of sensor data for persistence and communication
|
||||
|
||||
|
||||
This feature **does NOT include**:
|
||||
|
||||
* Main Hub processing
|
||||
|
||||
* Cloud analytics
|
||||
|
||||
* Control logic
|
||||
|
||||
* OTA, diagnostics, or persistence mechanisms (referenced only as dependencies)
|
||||
|
||||
|
||||
## **2\. Purpose and Engineering Rationale**
|
||||
|
||||
Modern poultry farm automation systems require **high-resolution, reliable, and time-correlated environmental data** to enable:
|
||||
|
||||
* Accurate environmental control
|
||||
|
||||
* Early fault detection
|
||||
|
||||
* Advanced analytics and machine learning
|
||||
|
||||
|
||||
The Sensor Data Acquisition feature ensures:
|
||||
|
||||
* Deterministic sensor sampling
|
||||
|
||||
* Noise-resilient measurements
|
||||
|
||||
* Temporal traceability of data
|
||||
|
||||
* Decoupling of acquisition from communication and control
|
||||
|
||||
|
||||
This aligns with **distributed intelligence principles** used in leading international poultry automation systems.
|
||||
|
||||
## **3\. Feature Decomposition**
|
||||
|
||||
The Sensor Data Acquisition feature is decomposed into the following sub-features:
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Sub-Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Name</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DAQ-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Multi-Sensor Data Acquisition</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DAQ-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">High-Frequency Sampling and Local Filtering</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DAQ-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Timestamped Sensor Data Generation</p></td></tr></tbody></table></figure>
|
||||
|
||||
## **4\. Functional Description**
|
||||
|
||||
### **4.1 F-DAQ-01: Multi-Sensor Data Acquisition**
|
||||
|
||||
#### **Description**
|
||||
|
||||
The Sensor Hub acquires environmental data from multiple heterogeneous sensors connected to dedicated hardware interfaces.
|
||||
|
||||
#### **Supported Sensor Types**
|
||||
|
||||
* Temperature
|
||||
|
||||
* Relative Humidity
|
||||
|
||||
* Carbon Dioxide (CO₂)
|
||||
|
||||
* Ammonia (NH₃)
|
||||
|
||||
* Volatile Organic Compounds (VOC)
|
||||
|
||||
* Particulate Matter (PM)
|
||||
|
||||
* Light Intensity
|
||||
|
||||
|
||||
Each sensor:
|
||||
|
||||
* Is mapped to a predefined hardware slot
|
||||
|
||||
* Has a dedicated driver abstraction
|
||||
|
||||
* Can be independently enabled or disabled
|
||||
|
||||
|
||||
#### **Key Characteristics**
|
||||
|
||||
* Concurrent sensor handling
|
||||
|
||||
* Modular sensor driver architecture
|
||||
|
||||
* Runtime awareness of sensor presence
|
||||
|
||||
|
||||
### **4.2 F-DAQ-02: High-Frequency Sampling and Local Filtering**
|
||||
|
||||
#### **Description**
|
||||
|
||||
For each enabled sensor, the system performs multiple raw readings per acquisition cycle and applies a local filtering mechanism to produce a single representative value.
|
||||
|
||||
#### **Sampling Behavior**
|
||||
|
||||
* Each sensor is sampled **N times per cycle** (default: 10)
|
||||
|
||||
* Sampling occurs within a bounded time window
|
||||
|
||||
* Sampling frequency is configurable via Machine Constants
|
||||
|
||||
|
||||
#### **Filtering Behavior**
|
||||
|
||||
* Filtering is executed locally on the Sensor Hub
|
||||
|
||||
* Filtering algorithms are abstracted and replaceable
|
||||
|
||||
* Examples (non-exhaustive):
|
||||
|
||||
* Moving average
|
||||
|
||||
* Median filter
|
||||
|
||||
* Outlier rejection
|
||||
|
||||
|
||||
#### **Objective**
|
||||
|
||||
* Reduce sensor noise
|
||||
|
||||
* Improve data stability
|
||||
|
||||
* Avoid propagating raw sensor jitter upstream
|
||||
|
||||
|
||||
### **4.3 F-DAQ-03: Timestamped Sensor Data Generation**
|
||||
|
||||
#### **Description**
|
||||
|
||||
Each processed sensor value is associated with a timestamp generated by the Sensor Hub.
|
||||
|
||||
#### **Timestamp Characteristics**
|
||||
|
||||
* Generated after filtering completion
|
||||
|
||||
* Represents the effective measurement time
|
||||
|
||||
* Based on system time (RTC or synchronized clock)
|
||||
|
||||
|
||||
#### **Sensor Data Record**
|
||||
|
||||
Each record includes:
|
||||
|
||||
* Sensor ID
|
||||
|
||||
* Sensor type
|
||||
|
||||
* Filtered value
|
||||
|
||||
* Unit of measurement
|
||||
|
||||
* Timestamp
|
||||
|
||||
* Data validity status
|
||||
|
||||
|
||||
## **5\. Operational Flow**
|
||||
|
||||
### **Normal Acquisition Cycle**
|
||||
|
||||
1. Detect enabled sensors
|
||||
|
||||
2. Initialize sensor drivers (if not already active)
|
||||
|
||||
3. Perform high-frequency sampling per sensor
|
||||
|
||||
4. Apply local filtering
|
||||
|
||||
5. Generate timestamp
|
||||
|
||||
6. Create sensor data record
|
||||
|
||||
7. Forward data to:
|
||||
|
||||
* Data Persistence component
|
||||
|
||||
* Communication component (on request)
|
||||
|
||||
|
||||
## **6\. Constraints and Assumptions**
|
||||
|
||||
### **Constraints**
|
||||
|
||||
* Sensor acquisition must not block system-critical tasks
|
||||
|
||||
* Sampling and filtering must complete within a bounded cycle time
|
||||
|
||||
* Memory usage must be deterministic
|
||||
|
||||
|
||||
### **Assumptions**
|
||||
|
||||
* Sensor presence detection is handled by a separate feature
|
||||
|
||||
* Time synchronization is provided by another system component
|
||||
|
||||
* Storage and communication are decoupled from acquisition
|
||||
|
||||
|
||||
## **7\. Architecture Diagram (PlantUML)**
|
||||
|
||||
### **7.1 Sensor Data Acquisition – Logical View**
|
||||
|
||||
<br>
|
||||
|
||||
`@startuml package "Sensor Hub" { component "Sensor Drivers" as SD component "Sampling Engine" as SE component "Filtering Engine" as FE component "Timestamp Service" as TS component "Sensor Data Buffer" as DB SD --> SE : raw samples SE --> FE : sampled data FE --> TS : filtered value TS --> DB : timestamped record } @enduml`
|
||||
|
||||
### **7.2 Acquisition Cycle Sequence Diagram**
|
||||
|
||||
<br>
|
||||
|
||||
`@startuml participant "Sensor Driver" as S participant "Sampling Engine" as SE participant "Filtering Engine" as FE participant "Timestamp Service" as TS S -> SE : read() loop N samples SE -> S : sample() end SE -> FE : raw sample set FE -> TS : filtered value TS -> FE : timestamp @enduml`
|
||||
|
||||
## **8\. Formal System SHALL Requirements**
|
||||
|
||||
### **8.1 Requirement Style**
|
||||
|
||||
* Each requirement uses **“The system shall …”**
|
||||
|
||||
* Each requirement has a unique ID
|
||||
|
||||
* Requirements are atomic and testable
|
||||
|
||||
|
||||
### **8.2 Requirements List**
|
||||
|
||||
#### **Multi-Sensor Acquisition**
|
||||
|
||||
* **REQ-DAQ-001**
|
||||
The system shall support acquisition of data from multiple environmental sensor types simultaneously.
|
||||
|
||||
* **REQ-DAQ-002**
|
||||
The system shall provide a dedicated software driver abstraction for each supported sensor type.
|
||||
|
||||
* **REQ-DAQ-003**
|
||||
The system shall acquire sensor data only from sensors detected as present and enabled.
|
||||
|
||||
|
||||
#### **High-Frequency Sampling & Filtering**
|
||||
|
||||
* **REQ-DAQ-004**
|
||||
The system shall sample each enabled sensor multiple times within a single acquisition cycle.
|
||||
|
||||
* **REQ-DAQ-005**
|
||||
The system shall apply a local filtering mechanism to raw sensor samples to produce a single representative value.
|
||||
|
||||
* **REQ-DAQ-006**
|
||||
The system shall allow configuration of sampling count and filtering parameters via system configuration data.
|
||||
|
||||
|
||||
#### **Timestamped Data Generation**
|
||||
|
||||
* **REQ-DAQ-007**
|
||||
The system shall associate each processed sensor value with a timestamp.
|
||||
|
||||
* **REQ-DAQ-008**
|
||||
The system shall generate timestamps after completion of filtering.
|
||||
|
||||
* **REQ-DAQ-009**
|
||||
The system shall include sensor identifier, sensor type, value, unit, timestamp, and validity status in each sensor data record.
|
||||
|
||||
|
||||
## **9\. Feature-to-Requirement Traceability**
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Requirement IDs</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DAQ-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">REQ-DAQ-001, REQ-DAQ-002, REQ-DAQ-003</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DAQ-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">REQ-DAQ-004, REQ-DAQ-005, REQ-DAQ-006</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DAQ-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">REQ-DAQ-007, REQ-DAQ-008, REQ-DAQ-009</p></td></tr></tbody></table></figure>
|
||||
@@ -0,0 +1,173 @@
|
||||
<macro class="toc op-uc-placeholder op-uc-toc">
|
||||
</macro>
|
||||
|
||||
# Feature Engineering Specification
|
||||
|
||||
## Persistence & Data Management Features
|
||||
|
||||
**Feature Group ID:** FG-DATA
|
||||
**Scope:** Sensor Hub (Sub-Hub only)
|
||||
**Target Platform:** ESP32-S3–based Sensor Hub
|
||||
**Applies To:** Indoor poultry farm sensor hubs
|
||||
**Dependencies:**
|
||||
|
||||
* Sensor Data Acquisition (FG-DAQ)
|
||||
|
||||
* Data Quality & Calibration (FG-DQC)
|
||||
|
||||
* Diagnostics & Health Monitoring (FG-DIAG)
|
||||
|
||||
* System State Management / Teardown Mechanism
|
||||
|
||||
|
||||
## 1\. Purpose and Objectives
|
||||
|
||||
The **Persistence & Data Management Features** define how the Sensor Hub stores, protects, and manages critical runtime and historical data. These features ensure that:
|
||||
|
||||
* Sensor data and system state are not lost during resets or failures
|
||||
|
||||
* Data storage is abstracted from application logic
|
||||
|
||||
* Critical data is safely handled during firmware updates, configuration changes, or fatal faults
|
||||
|
||||
|
||||
The persistence layer is a **foundational system service**, supporting diagnostics, calibration, OTA, and recovery operations.
|
||||
|
||||
## 2\. Feature Overview and Relationships
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature Name</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Primary Objective</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Related Features</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DATA-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Persistent Sensor Data Storage</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Store timestamped sensor data</p></td><td class="op-uc-table--cell"><p class="op-uc-p">DAQ, COM</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DATA-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Data Persistence Abstraction (DP)</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Abstract storage access</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Application Layer</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DATA-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Safe Data Handling During State Transitions</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Protect data during teardown</p></td><td class="op-uc-table--cell"><p class="op-uc-p">OTA, System Mgmt</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 3\. Functional Feature Descriptions
|
||||
|
||||
### 3.1 F-DATA-01: Persistent Sensor Data Storage
|
||||
|
||||
**Description**
|
||||
The system shall persist timestamped sensor data to non-volatile storage to support historical analysis, diagnostics correlation, and recovery scenarios.
|
||||
|
||||
Persistence may include:
|
||||
|
||||
* Filtered sensor values
|
||||
|
||||
* Timestamps
|
||||
|
||||
* Sensor validity and status metadata
|
||||
|
||||
|
||||
The persistence policy (frequency, retention window, overwrite behavior) is configurable and optimized for storage longevity and performance.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Non-volatile storage (SD card / NVM)
|
||||
|
||||
* Timestamped records
|
||||
|
||||
* Configurable retention policy
|
||||
|
||||
* Integration with DAQ and COM
|
||||
|
||||
|
||||
### 3.2 F-DATA-02: Data Persistence Abstraction (DP Component)
|
||||
|
||||
**Description**
|
||||
The system shall provide a **Data Persistence (DP) component** that abstracts storage access for all upper layers. Application and feature modules interact with the DP component rather than directly accessing storage hardware.
|
||||
|
||||
The DP component manages:
|
||||
|
||||
* Data model definitions
|
||||
|
||||
* Serialization and deserialization
|
||||
|
||||
* Storage backend selection
|
||||
|
||||
* Consistency and integrity guarantees
|
||||
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Unified persistence API
|
||||
|
||||
* Storage backend abstraction
|
||||
|
||||
* Centralized data ownership
|
||||
|
||||
* Reduced coupling between layers
|
||||
|
||||
|
||||
### 3.3 F-DATA-03: Safe Data Handling During State Transitions
|
||||
|
||||
**Description**
|
||||
The system shall ensure safe and deterministic handling of data during critical state transitions, including:
|
||||
|
||||
* Firmware updates (OTA)
|
||||
|
||||
* Machine Constants updates
|
||||
|
||||
* System resets
|
||||
|
||||
* Fatal error handling
|
||||
|
||||
|
||||
Before entering such transitions, the system executes a controlled data finalization process to flush buffers, persist critical state, and verify data integrity.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Controlled data flush
|
||||
|
||||
* Atomic write operations
|
||||
|
||||
* Data integrity checks
|
||||
|
||||
* Coordination with teardown mechanism
|
||||
|
||||
|
||||
## 4\. System Requirements (Formal SHALL Statements)
|
||||
|
||||
### 4.1 Persistent Sensor Data Storage
|
||||
|
||||
**SR-DATA-001**
|
||||
The system shall persist timestamped sensor data in non-volatile storage.
|
||||
|
||||
**SR-DATA-002**
|
||||
The system shall store sensor data together with sensor identifiers, timestamps, and validity status.
|
||||
|
||||
**SR-DATA-003**
|
||||
The system shall support configurable data retention and overwrite policies.
|
||||
|
||||
### 4.2 Data Persistence Abstraction (DP Component)
|
||||
|
||||
**SR-DATA-004**
|
||||
The system shall provide a Data Persistence (DP) component as the sole interface for persistent data access.
|
||||
|
||||
**SR-DATA-005**
|
||||
The system shall prevent application and feature modules from directly accessing storage hardware.
|
||||
|
||||
**SR-DATA-006**
|
||||
The DP component shall support serialization and deserialization of structured system data.
|
||||
|
||||
### 4.3 Safe Data Handling During State Transitions
|
||||
|
||||
**SR-DATA-007**
|
||||
The system shall ensure that all critical runtime data is flushed to non-volatile storage before entering a controlled teardown or reset.
|
||||
|
||||
**SR-DATA-008**
|
||||
The system shall protect data integrity during firmware updates and configuration changes.
|
||||
|
||||
**SR-DATA-009**
|
||||
The system shall verify successful data persistence before completing a state transition.
|
||||
|
||||
## 5\. Feature ↔ System Requirement Mapping
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">System Requirements</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DATA-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DATA-001, SR-DATA-002, SR-DATA-003</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DATA-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DATA-004, SR-DATA-005, SR-DATA-006</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DATA-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DATA-007, SR-DATA-008, SR-DATA-009</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 6\. Engineering Notes
|
||||
|
||||
* The DP component aligns with your **DP Stack** already defined in the architecture.
|
||||
|
||||
* Atomic write strategies (e.g., temp file + rename) are recommended.
|
||||
|
||||
* Diagnostic events should be generated on persistence failures.
|
||||
|
||||
* Storage wear-leveling considerations apply for SD/NVM.
|
||||
|
||||
|
||||
##
|
||||
@@ -0,0 +1,167 @@
|
||||
<macro class="toc op-uc-placeholder op-uc-toc">
|
||||
</macro>
|
||||
|
||||
# Feature Engineering Specification
|
||||
|
||||
## Diagnostics & Health Monitoring Features
|
||||
|
||||
**Feature Group ID:** FG-DIAG
|
||||
**Scope:** Sensor Hub (Sub-Hub only)
|
||||
**Target Platform:** ESP32-S3–based Sensor Hub
|
||||
**Applies To:** Indoor poultry farm sensor hubs
|
||||
**Dependencies:**
|
||||
|
||||
* Sensor Data Acquisition (FG-DAQ)
|
||||
|
||||
* Data Quality & Calibration (FG-DQC)
|
||||
|
||||
* Communication Features (FG-COM)
|
||||
|
||||
* Persistence / DP Stack
|
||||
|
||||
|
||||
## 1\. Purpose and Objectives
|
||||
|
||||
The **Diagnostics & Health Monitoring Features** provide a structured and persistent mechanism to detect, classify, record, and expose system faults, warnings, and health states.
|
||||
|
||||
These features ensure that:
|
||||
|
||||
* Failures are detectable and explainable
|
||||
|
||||
* Root causes are traceable
|
||||
|
||||
* Diagnostic data survives resets and power loss
|
||||
|
||||
* Engineers can access diagnostic information locally or remotely
|
||||
|
||||
|
||||
The diagnostics subsystem is **non-intrusive**, meaning it shall not block core sensing or communication functions unless the system enters a fatal state.
|
||||
|
||||
## 2\. Feature Overview and Relationships
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature Name</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Primary Objective</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Related Features</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DIAG-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Diagnostic Code Management</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Standardize fault and warning identification</p></td><td class="op-uc-table--cell"><p class="op-uc-p">DQC, COM</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DIAG-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Diagnostic Data Storage</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Persist diagnostic events</p></td><td class="op-uc-table--cell"><p class="op-uc-p">DP Stack</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DIAG-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Diagnostic Session</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Engineer access to diagnostics</p></td><td class="op-uc-table--cell"><p class="op-uc-p">COM, System Mgmt</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 3\. Functional Feature Descriptions
|
||||
|
||||
### 3.1 F-DIAG-01: Diagnostic Code Management
|
||||
|
||||
**Description**
|
||||
The system shall implement a structured diagnostic code framework to represent system health conditions, warnings, errors, and fatal faults.
|
||||
|
||||
Each diagnostic event is associated with:
|
||||
|
||||
* A unique diagnostic code
|
||||
|
||||
* Severity level (info, warning, error, fatal)
|
||||
|
||||
* A hierarchical root-cause classification
|
||||
|
||||
* Timestamp and source component
|
||||
|
||||
|
||||
This framework enables consistent fault handling across all system components.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Unique diagnostic code registry
|
||||
|
||||
* Severity classification
|
||||
|
||||
* Root-cause hierarchy
|
||||
|
||||
* Event-based reporting
|
||||
|
||||
|
||||
### 3.2 F-DIAG-02: Diagnostic Data Storage
|
||||
|
||||
**Description**
|
||||
The system shall persist diagnostic events in non-volatile storage to allow post-failure analysis and long-term health monitoring.
|
||||
|
||||
Stored diagnostics remain available across system resets and power cycles until explicitly cleared by an authorized diagnostic session or command.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Persistent storage of diagnostic events
|
||||
|
||||
* Timestamped records
|
||||
|
||||
* Bounded storage with overwrite policy
|
||||
|
||||
* Integration with DP / Persistence layer
|
||||
|
||||
|
||||
### 3.3 F-DIAG-03: Diagnostic Session
|
||||
|
||||
**Description**
|
||||
The system shall provide a diagnostic session that allows authorized engineers or tools to access diagnostic data, inspect system health, and perform maintenance operations.
|
||||
|
||||
The diagnostic session may be accessed locally or remotely via the communication interface and supports read and limited control operations.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Session-based access
|
||||
|
||||
* Read diagnostics and health data
|
||||
|
||||
* Clear diagnostic records
|
||||
|
||||
* Controlled command execution
|
||||
|
||||
|
||||
## 4\. System Requirements (Formal SHALL Statements)
|
||||
|
||||
### 4.1 Diagnostic Code Management
|
||||
|
||||
**SR-DIAG-001**
|
||||
The system shall implement a diagnostic code framework for reporting system health, warnings, errors, and fatal faults.
|
||||
|
||||
**SR-DIAG-002**
|
||||
The system shall assign a unique diagnostic code to each detected fault or abnormal condition.
|
||||
|
||||
**SR-DIAG-003**
|
||||
The system shall classify diagnostic codes by severity level.
|
||||
|
||||
**SR-DIAG-004**
|
||||
The system shall associate each diagnostic event with a timestamp and source component.
|
||||
|
||||
### 4.2 Diagnostic Data Storage
|
||||
|
||||
**SR-DIAG-005**
|
||||
The system shall persist diagnostic events in non-volatile storage.
|
||||
|
||||
**SR-DIAG-006**
|
||||
The system shall retain diagnostic data across system resets and power cycles.
|
||||
|
||||
**SR-DIAG-007**
|
||||
The system shall implement a bounded diagnostic storage mechanism with a defined overwrite or rollover policy.
|
||||
|
||||
### 4.3 Diagnostic Session
|
||||
|
||||
**SR-DIAG-008**
|
||||
The system shall provide a diagnostic session interface for accessing diagnostic data.
|
||||
|
||||
**SR-DIAG-009**
|
||||
The system shall allow authorized diagnostic sessions to retrieve stored diagnostic events.
|
||||
|
||||
**SR-DIAG-010**
|
||||
The system shall allow authorized diagnostic sessions to clear diagnostic records.
|
||||
|
||||
**SR-DIAG-011**
|
||||
The system shall ensure that diagnostic sessions do not interfere with normal sensor acquisition or communication operations.
|
||||
|
||||
## 5\. Feature ↔ System Requirement Mapping
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">System Requirements</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DIAG-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DIAG-001, SR-DIAG-002, SR-DIAG-003, SR-DIAG-004</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DIAG-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DIAG-005, SR-DIAG-006, SR-DIAG-007</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DIAG-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DIAG-008, SR-DIAG-009, SR-DIAG-010, SR-DIAG-011</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 6\. Engineering Notes
|
||||
|
||||
* Diagnostic codes should be versioned to support firmware evolution.
|
||||
|
||||
* Diagnostic severity may be linked to LED indicators (green/yellow/red).
|
||||
|
||||
* Fatal diagnostics may trigger the teardown mechanism defined elsewhere.
|
||||
|
||||
* Security and access control for diagnostic sessions are handled under **Security & Safety Features**.
|
||||
|
||||
|
||||
##
|
||||
@@ -0,0 +1,180 @@
|
||||
<macro class="toc op-uc-placeholder op-uc-toc">
|
||||
</macro>
|
||||
|
||||
# Feature Engineering Specification
|
||||
|
||||
## Data Quality & Calibration Features
|
||||
|
||||
**Feature Group ID:** FG-DQC
|
||||
**Scope:** Sensor Hub (Sub-Hub only)
|
||||
**Target Platform:** ESP32-S3–based Sensor Hub
|
||||
**Applies To:** Indoor poultry farm sensor hubs
|
||||
**Dependencies:** Sensor Data Acquisition Features (FG-DAQ), Diagnostics Features (FG-DIAG), Persistence / DP Stack
|
||||
|
||||
## 1\. Purpose and Objectives
|
||||
|
||||
The **Data Quality & Calibration Features** ensure that all sensor data generated by the Sensor Hub is **valid, trustworthy, correctly classified, and calibrated** throughout the system lifecycle. These features provide mechanisms for:
|
||||
|
||||
* Automatic identification of connected sensors
|
||||
|
||||
* Enforcing correct sensor–slot compatibility
|
||||
|
||||
* Early detection and isolation of faulty sensors
|
||||
|
||||
* Centralized management of machine constants and calibration parameters
|
||||
|
||||
|
||||
The goal is to maintain **high data integrity**, reduce commissioning errors, support **remote reconfiguration**, and ensure safe operation during updates or failures.
|
||||
|
||||
<br>
|
||||
|
||||
<macro class="embedded-table op-uc-placeholder op-uc-embedded-table" data-query-props="{"columns[]":["id","subject","type","status","assignee","priority"],"showSums":false,"timelineVisible":false,"highlightingMode":"none","includeSubprojects":true,"showHierarchies":true,"groupBy":"","filters":"[{\"search\":{\"operator\":\"**\",\"values\":[\"DQC\"]}}]","sortBy":"[[\"id\",\"asc\"]]","timestamps":"PT0S"}">
|
||||
</macro>
|
||||
|
||||
## 2\. Feature Overview and Relationships
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature Name</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Primary Objective</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Related Features</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Automatic Sensor Detection</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Detect connected sensors dynamically</p></td><td class="op-uc-table--cell"><p class="op-uc-p">F-DAQ-01, F-DIAG-01</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Sensor Type Enforcement</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Prevent incorrect sensor-slot usage</p></td><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-01</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Sensor Failure Detection</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Identify and isolate faulty sensors</p></td><td class="op-uc-table--cell"><p class="op-uc-p">F-DIAG-02</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-04</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Machine Constants & Calibration Management</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Manage static configuration and calibration</p></td><td class="op-uc-table--cell"><p class="op-uc-p">OTA, Persistence, Teardown</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 3\. Functional Feature Descriptions
|
||||
|
||||
### 3.1 F-DQC-01: Automatic Sensor Detection
|
||||
|
||||
**Description**
|
||||
The Sensor Hub shall automatically detect which sensors are physically connected at runtime. Each sensor slot provides a dedicated detection mechanism (e.g., GPIO presence pin or ID signal) that allows the system to determine whether a sensor is installed.
|
||||
|
||||
Detected sensors are dynamically initialized and incorporated into the data acquisition workflow without requiring firmware changes.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Hardware-based presence detection
|
||||
|
||||
* Runtime sensor enumeration
|
||||
|
||||
* Dynamic initialization during boot or reconfiguration
|
||||
|
||||
* Integration with diagnostics and data acquisition
|
||||
|
||||
|
||||
### 3.2 F-DQC-02: Sensor Type Enforcement
|
||||
|
||||
**Description**
|
||||
Each physical sensor slot on the Sensor Hub is dedicated to a specific sensor type. The system enforces sensor-slot compatibility to prevent incorrect sensor insertion (e.g., humidity sensor in temperature slot).
|
||||
|
||||
This enforcement is achieved via electrical identification, pin mapping, or firmware configuration defined in Machine Constants.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Fixed sensor-to-slot mapping
|
||||
|
||||
* Sensor identity verification
|
||||
|
||||
* Rejection of invalid sensor configurations
|
||||
|
||||
* Diagnostic reporting of configuration violations
|
||||
|
||||
|
||||
### 3.3 F-DQC-03: Sensor Failure Detection
|
||||
|
||||
**Description**
|
||||
The Sensor Hub continuously monitors sensor behavior to detect failures such as disconnection, out-of-range values, non-responsive sensors, or abnormal signal patterns.
|
||||
|
||||
Detected sensor failures are classified, logged, timestamped, and reported to the Main Hub. Failed sensors are excluded from control and analytics workflows to prevent propagation of invalid data.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Runtime health monitoring
|
||||
|
||||
* Failure classification
|
||||
|
||||
* Fault isolation
|
||||
|
||||
* Diagnostic event generation
|
||||
|
||||
|
||||
### 3.4 F-DQC-04: Machine Constants & Calibration Management
|
||||
|
||||
**Description**
|
||||
The system maintains a **Machine Constants (MC)** dataset that defines static and semi-static configuration parameters for the Sensor Hub, including:
|
||||
|
||||
* Installed sensor types and slots
|
||||
|
||||
* Communication identifiers and addressing
|
||||
|
||||
* Calibration coefficients and offsets
|
||||
|
||||
* Sensor-specific limits and scaling
|
||||
|
||||
|
||||
Machine Constants are persisted in non-volatile storage (SD card) and loaded during system initialization. Updates may be received from the Main Hub and applied via a controlled teardown and reinitialization process.
|
||||
|
||||
**Key Capabilities**
|
||||
|
||||
* Persistent configuration storage
|
||||
|
||||
* Runtime loading and validation
|
||||
|
||||
* Remote update support
|
||||
|
||||
* Controlled reinitialization sequence
|
||||
|
||||
|
||||
## 4\. System Requirements (Formal SHALL Statements)
|
||||
|
||||
### 4.1 Automatic Sensor Detection
|
||||
|
||||
**SR-DQC-001**
|
||||
The system shall detect the presence of each sensor using a dedicated hardware detection mechanism.
|
||||
|
||||
**SR-DQC-002**
|
||||
The system shall perform sensor presence detection during system startup and after any reinitialization event.
|
||||
|
||||
**SR-DQC-003**
|
||||
The system shall initialize only those sensors that are detected as present.
|
||||
|
||||
### 4.2 Sensor Type Enforcement
|
||||
|
||||
**SR-DQC-004**
|
||||
The system shall assign each sensor slot to a predefined sensor type.
|
||||
|
||||
**SR-DQC-005**
|
||||
The system shall verify that the detected sensor matches the expected sensor type for the slot.
|
||||
|
||||
**SR-DQC-006**
|
||||
The system shall reject and report any sensor-slot mismatch as a diagnostic event.
|
||||
|
||||
### 4.3 Sensor Failure Detection
|
||||
|
||||
**SR-DQC-007**
|
||||
The system shall continuously monitor sensor responsiveness and signal validity during operation.
|
||||
|
||||
**SR-DQC-008**
|
||||
The system shall detect sensor failures including disconnection, non-responsiveness, and invalid measurement ranges.
|
||||
|
||||
**SR-DQC-009**
|
||||
The system shall mark a failed sensor as defective and exclude it from data reporting.
|
||||
|
||||
**SR-DQC-010**
|
||||
The system shall report detected sensor failures to the Main Hub with timestamps and failure classification.
|
||||
|
||||
### 4.4 Machine Constants & Calibration Management
|
||||
|
||||
**SR-DQC-011**
|
||||
The system shall maintain a Machine Constants dataset defining sensor configuration, calibration parameters, and communication identifiers.
|
||||
|
||||
**SR-DQC-012**
|
||||
The system shall persist the Machine Constants dataset in non-volatile storage.
|
||||
|
||||
**SR-DQC-013**
|
||||
The system shall load and apply Machine Constants during system initialization.
|
||||
|
||||
**SR-DQC-014**
|
||||
The system shall support remote updates of the Machine Constants dataset initiated by the Main Hub.
|
||||
|
||||
**SR-DQC-015**
|
||||
The system shall apply updated Machine Constants only after executing a controlled teardown and reinitialization sequence.
|
||||
|
||||
## 5\. Traceability Summary
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">System Requirements</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DQC-001 → SR-DQC-003</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DQC-004 → SR-DQC-006</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DQC-007 → SR-DQC-010</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-DQC-04</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-DQC-011 → SR-DQC-015</p></td></tr></tbody></table></figure>
|
||||
|
||||
##
|
||||
185
System Design/Features/[OTA] Firmware Update (OTA) Features.md
Normal file
185
System Design/Features/[OTA] Firmware Update (OTA) Features.md
Normal file
@@ -0,0 +1,185 @@
|
||||
<macro class="toc op-uc-placeholder op-uc-toc">
|
||||
</macro>
|
||||
|
||||
# 8\. Firmware Update (OTA) Features
|
||||
|
||||
## 8.1 Feature Overview
|
||||
|
||||
The **Firmware Update (OTA) Features** enable the Sensor Hub (Sub-Hub) to safely receive, validate, and activate new firmware images provided by the Main Hub.
|
||||
These features ensure **controlled firmware lifecycle management**, **data integrity**, **system availability**, and **fault containment** during firmware update operations.
|
||||
|
||||
The OTA process is designed to:
|
||||
|
||||
* Prevent unauthorized or corrupted firmware installation
|
||||
|
||||
* Preserve critical system data and calibration information
|
||||
|
||||
* Ensure recoverability in case of update failure
|
||||
|
||||
* Minimize operational disruption
|
||||
|
||||
|
||||
This feature set applies **only to the Sensor Hub (ESP32-S3 based)** and does not include cloud-side or Main Hub OTA logic.
|
||||
|
||||
## 8.2 Scope and Assumptions
|
||||
|
||||
### In Scope
|
||||
|
||||
* OTA negotiation and readiness handshake with Main Hub
|
||||
|
||||
* Firmware image reception over secure communication
|
||||
|
||||
* Temporary firmware storage on SD card
|
||||
|
||||
* Firmware integrity verification (e.g., CRC, hash)
|
||||
|
||||
* Controlled firmware activation and reboot
|
||||
|
||||
|
||||
### Out of Scope
|
||||
|
||||
* Firmware generation and signing
|
||||
|
||||
* Cloud-side firmware distribution
|
||||
|
||||
* Rollback policy definition (may be extended later)
|
||||
|
||||
|
||||
## 8.3 Sub-Features
|
||||
|
||||
### 8.3.1 F-OTA-01: OTA Update Negotiation
|
||||
|
||||
**Description**
|
||||
This sub-feature governs the initial negotiation phase between the Sensor Hub and the Main Hub prior to any firmware transfer.
|
||||
The Sensor Hub validates its current operational state and explicitly signals readiness before accepting an OTA update.
|
||||
|
||||
**Responsibilities**
|
||||
|
||||
* Receive OTA availability notification
|
||||
|
||||
* Validate system readiness (power, storage, state)
|
||||
|
||||
* Acknowledge or reject OTA request
|
||||
|
||||
* Transition system into OTA-preparation mode
|
||||
|
||||
|
||||
### 8.3.2 F-OTA-02: Firmware Reception and Storage
|
||||
|
||||
**Description**
|
||||
This sub-feature handles the controlled reception of the firmware image from the Main Hub and its storage in non-volatile memory (SD card) without overwriting the currently running firmware.
|
||||
|
||||
**Responsibilities**
|
||||
|
||||
* Receive firmware in chunks
|
||||
|
||||
* Store firmware image on SD card
|
||||
|
||||
* Monitor transfer completeness
|
||||
|
||||
* Prevent execution during download
|
||||
|
||||
|
||||
### 8.3.3 F-OTA-03: Firmware Integrity Validation
|
||||
|
||||
**Description**
|
||||
This sub-feature validates the integrity and correctness of the received firmware image prior to activation, ensuring that corrupted or incomplete firmware is never flashed.
|
||||
|
||||
**Responsibilities**
|
||||
|
||||
* Perform integrity checks (CRC, checksum, hash)
|
||||
|
||||
* Validate firmware size and metadata
|
||||
|
||||
* Reject invalid firmware images
|
||||
|
||||
* Report validation status to Main Hub
|
||||
|
||||
|
||||
### 8.3.4 F-OTA-04: Safe Firmware Activation
|
||||
|
||||
**Description**
|
||||
This sub-feature manages the safe transition from the current firmware to the new firmware, ensuring all critical data is preserved and the system is left in a known safe state.
|
||||
|
||||
**Responsibilities**
|
||||
|
||||
* Trigger teardown procedure
|
||||
|
||||
* Persist runtime and calibration data
|
||||
|
||||
* Flash validated firmware image
|
||||
|
||||
* Reboot system into updated firmware
|
||||
|
||||
|
||||
## 8.4 System Requirements (Formal SHALL Statements)
|
||||
|
||||
### OTA Negotiation Requirements
|
||||
|
||||
* **SR-OTA-001**: The system shall support OTA update negotiation initiated by the Main Hub.
|
||||
|
||||
* **SR-OTA-002**: The system shall verify internal readiness before accepting an OTA update request.
|
||||
|
||||
* **SR-OTA-003**: The system shall explicitly acknowledge or reject OTA requests.
|
||||
|
||||
|
||||
### Firmware Reception & Storage Requirements
|
||||
|
||||
* **SR-OTA-004**: The system shall receive firmware images over the established communication channel.
|
||||
|
||||
* **SR-OTA-005**: The system shall store received firmware images in non-volatile storage prior to validation.
|
||||
|
||||
* **SR-OTA-006**: The system shall prevent overwriting the active firmware during firmware reception.
|
||||
|
||||
|
||||
### Firmware Integrity Requirements
|
||||
|
||||
* **SR-OTA-007**: The system shall validate the integrity of the received firmware image before activation.
|
||||
|
||||
* **SR-OTA-008**: The system shall reject firmware images that fail integrity validation.
|
||||
|
||||
* **SR-OTA-009**: The system shall report firmware validation results to the Main Hub.
|
||||
|
||||
|
||||
### Safe Activation Requirements
|
||||
|
||||
* **SR-OTA-010**: The system shall execute a controlled teardown before firmware activation.
|
||||
|
||||
* **SR-OTA-011**: The system shall persist critical runtime data prior to firmware flashing.
|
||||
|
||||
* **SR-OTA-012**: The system shall activate new firmware only after successful validation.
|
||||
|
||||
* **SR-OTA-013**: The system shall reboot into the new firmware following successful activation.
|
||||
|
||||
|
||||
## 8.5 Feature-to-Requirement Traceability
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Related System Requirements</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-OTA-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-OTA-001, SR-OTA-002, SR-OTA-003</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-OTA-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-OTA-004, SR-OTA-005, SR-OTA-006</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-OTA-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-OTA-007, SR-OTA-008, SR-OTA-009</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-OTA-04</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-OTA-010, SR-OTA-011, SR-OTA-012, SR-OTA-013</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 8.6 Architectural Considerations (Informative)
|
||||
|
||||
* OTA logic shall be implemented as a **dedicated OTA Manager component**
|
||||
|
||||
* Firmware storage shall be accessed via the **DP (Data Persistence) component**
|
||||
|
||||
* OTA state transitions shall interact with:
|
||||
|
||||
* Diagnostics subsystem
|
||||
|
||||
* Machine Constants management
|
||||
|
||||
* Teardown mechanism
|
||||
|
||||
* OTA execution shall not block critical system diagnostics reporting
|
||||
|
||||
|
||||
## 8.7 Related Features
|
||||
|
||||
* **Persistence & Data Management Features (F-DATA-03)**
|
||||
|
||||
* **Diagnostics & Health Monitoring Features**
|
||||
|
||||
* **Security & Safety Features (Secure Boot, Secure Flash)**
|
||||
|
||||
|
||||
###
|
||||
228
System Design/Features/[SEC] Security & Safety Features.md
Normal file
228
System Design/Features/[SEC] Security & Safety Features.md
Normal file
@@ -0,0 +1,228 @@
|
||||
<macro class="toc op-uc-placeholder op-uc-toc">
|
||||
</macro>
|
||||
|
||||
#
|
||||
Security & Safety Features
|
||||
|
||||
## Sensor Hub (Sub-Hub) Scope Only
|
||||
|
||||
## 1 Feature Overview
|
||||
|
||||
The **Security & Safety Features** ensure that the Sensor Hub operates only with trusted firmware, protects sensitive data at rest, and guarantees confidentiality and integrity of all communications. These features are foundational and cross-cutting, supporting all other functional features (DAQ, DQC, COM, DIAG, DATA, OTA).
|
||||
|
||||
This feature set is designed to:
|
||||
|
||||
* Prevent execution of unauthorized or malicious firmware
|
||||
|
||||
* Protect firmware, configuration, and machine constants stored in memory
|
||||
|
||||
* Secure all communications with cryptographic mechanisms
|
||||
|
||||
* Provide deterministic and auditable behavior in case of security violations
|
||||
|
||||
|
||||
## 2 Scope and Assumptions
|
||||
|
||||
**In Scope**
|
||||
|
||||
* Sensor Hub (ESP32-S3–based)
|
||||
|
||||
* Boot process security
|
||||
|
||||
* Flash and external storage protection
|
||||
|
||||
* Communication security with Main Hub and peer Sensor Hubs
|
||||
|
||||
|
||||
**Out of Scope**
|
||||
|
||||
* Cloud server security policies
|
||||
|
||||
* User identity management
|
||||
|
||||
* Physical tamper detection hardware (optional future feature)
|
||||
|
||||
|
||||
## 3 Sub-Feature Breakdown
|
||||
|
||||
### 3.1 F-SEC-01: Secure Boot
|
||||
|
||||
#### Description
|
||||
|
||||
Secure Boot ensures that only authenticated and authorized firmware images are executed on the Sensor Hub. During system startup, the bootloader verifies the cryptographic signature of the firmware image before handing over execution.
|
||||
|
||||
If verification fails, the system enters a defined **security fault state** and prevents normal operation.
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
* Firmware authenticity verification
|
||||
|
||||
* Root-of-trust enforcement
|
||||
|
||||
* Prevention of downgrade or rollback attacks (if enabled)
|
||||
|
||||
|
||||
#### Constraints
|
||||
|
||||
* Must complete before any application code execution
|
||||
|
||||
* Must be enforced on every boot (cold or warm)
|
||||
|
||||
|
||||
### 3.2 F-SEC-02: Secure Flash Storage
|
||||
|
||||
#### Description
|
||||
|
||||
Secure Flash Storage protects sensitive data stored in internal flash and external storage (e.g., SD card) from unauthorized access or modification.
|
||||
|
||||
Sensitive data includes:
|
||||
|
||||
* Firmware images
|
||||
|
||||
* Machine constants
|
||||
|
||||
* Calibration data
|
||||
|
||||
* Cryptographic material
|
||||
|
||||
* Persistent diagnostics and logs
|
||||
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
* Encrypted storage of sensitive regions
|
||||
|
||||
* Access control enforcement
|
||||
|
||||
* Prevention of unauthorized read/write operations
|
||||
|
||||
|
||||
#### Constraints
|
||||
|
||||
* Encryption must not compromise system boot reliability
|
||||
|
||||
* Storage access must be mediated through controlled software components (e.g., DP component)
|
||||
|
||||
|
||||
### 3.3 F-SEC-03: Encrypted Communication
|
||||
|
||||
#### Description
|
||||
|
||||
Encrypted Communication ensures that all data exchanged between the Sensor Hub and other entities (Main Hub, peer Sensor Hubs) is protected against eavesdropping, tampering, and impersonation.
|
||||
|
||||
This includes:
|
||||
|
||||
* Sensor data transmission
|
||||
|
||||
* Diagnostics reporting
|
||||
|
||||
* OTA negotiation and data transfer
|
||||
|
||||
* Configuration and machine constant updates
|
||||
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
* Confidentiality of transmitted data
|
||||
|
||||
* Integrity and authenticity verification
|
||||
|
||||
* Secure session establishment
|
||||
|
||||
|
||||
#### Constraints
|
||||
|
||||
* Must be compatible with ESP32-S3 cryptographic capabilities
|
||||
|
||||
* Must support reconnection and key renewal mechanisms
|
||||
|
||||
|
||||
## 4 Functional Flow Overview
|
||||
|
||||
### Secure Boot Flow (Simplified)
|
||||
|
||||
```text
|
||||
Power On
|
||||
↓
|
||||
ROM Bootloader
|
||||
↓
|
||||
Verify Firmware Signature
|
||||
↓
|
||||
[Valid] → Jump to Application
|
||||
[Invalid] → Enter Security Fault State
|
||||
```
|
||||
|
||||
### Secure Communication Flow (Simplified)
|
||||
|
||||
```text
|
||||
Session Request
|
||||
↓
|
||||
Mutual Authentication
|
||||
↓
|
||||
Key Exchange
|
||||
↓
|
||||
Encrypted Data Exchange
|
||||
```
|
||||
|
||||
## 5 System SHALL Requirements (Formal)
|
||||
|
||||
### Secure Boot Requirements
|
||||
|
||||
* **SR-SEC-001**: The system shall verify the authenticity of the firmware image before execution during every boot cycle.
|
||||
|
||||
* **SR-SEC-002**: The system shall prevent execution of firmware images that fail cryptographic verification.
|
||||
|
||||
* **SR-SEC-003**: The system shall enter a defined security fault state upon secure boot failure.
|
||||
|
||||
* **SR-SEC-004**: The system shall protect the root-of-trust against modification.
|
||||
|
||||
|
||||
### Secure Flash Storage Requirements
|
||||
|
||||
* **SR-SEC-005**: The system shall protect sensitive data stored in internal flash memory from unauthorized access.
|
||||
|
||||
* **SR-SEC-006**: The system shall support encryption of sensitive data stored in external storage.
|
||||
|
||||
* **SR-SEC-007**: The system shall restrict access to cryptographic keys to authorized system components only.
|
||||
|
||||
* **SR-SEC-008**: The system shall ensure data integrity for stored configuration and machine constant files.
|
||||
|
||||
|
||||
### Encrypted Communication Requirements
|
||||
|
||||
* **SR-SEC-009**: The system shall encrypt all communication with the Main Hub.
|
||||
|
||||
* **SR-SEC-010**: The system shall ensure integrity and authenticity of all received and transmitted messages.
|
||||
|
||||
* **SR-SEC-011**: The system shall use secure communication channels for OTA firmware updates.
|
||||
|
||||
* **SR-SEC-012**: The system shall detect and report communication security violations.
|
||||
|
||||
|
||||
## 6 Traceability Matrix (Feature → System Requirements)
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Related System Requirements</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-SEC-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-SEC-001, SR-SEC-002, SR-SEC-003, SR-SEC-004</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-SEC-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-SEC-005, SR-SEC-006, SR-SEC-007, SR-SEC-008</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-SEC-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-SEC-009, SR-SEC-010, SR-SEC-011, SR-SEC-012</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 7 Design & Implementation Notes (Non-Normative)
|
||||
|
||||
* ESP32-S3 secure boot and flash encryption features should be leveraged where possible.
|
||||
|
||||
* Key provisioning should occur during manufacturing or secure onboarding.
|
||||
|
||||
* Security failures should integrate with the Diagnostics & Health Monitoring feature set.
|
||||
|
||||
* Security features must be active before any sensor data acquisition or communication begins.
|
||||
|
||||
|
||||
## 8 Dependencies
|
||||
|
||||
* **OTA Features** (for secure firmware updates)
|
||||
|
||||
* **Communication Features** (transport layer)
|
||||
|
||||
* **Diagnostics Features** (security fault reporting)
|
||||
|
||||
* **Persistence & DP Component** (secure storage abstraction)
|
||||
|
||||
|
||||
###
|
||||
314
System Design/Features/[SYS] System Management Features.md
Normal file
314
System Design/Features/[SYS] System Management Features.md
Normal file
@@ -0,0 +1,314 @@
|
||||
<macro class="toc op-uc-placeholder op-uc-toc">
|
||||
</macro>
|
||||
|
||||
#
|
||||
System Management Features
|
||||
|
||||
## Sensor Hub (Sub-Hub) Scope
|
||||
|
||||
## 1 Feature Overview
|
||||
|
||||
The **System Management Features** provide deterministic control over the Sensor Hub’s operational lifecycle, runtime state visibility, controlled shutdown behavior, and engineering interaction capabilities.
|
||||
|
||||
This feature group is responsible for:
|
||||
|
||||
* Managing system operational states and transitions
|
||||
|
||||
* Ensuring safe teardown during updates or failures
|
||||
|
||||
* Providing local human–machine interaction via OLED display and buttons
|
||||
|
||||
* Supporting engineering/debug sessions for diagnostics and maintenance
|
||||
|
||||
|
||||
These features act as the **supervisory layer** governing all other functional domains (DAQ, DQC, COM, DIAG, DATA, OTA, SEC).
|
||||
|
||||
## 2 Scope and Assumptions
|
||||
|
||||
**In Scope**
|
||||
|
||||
* ESP32-S3 Sensor Hub
|
||||
|
||||
* OLED-based local UI (I2C)
|
||||
|
||||
* Physical input buttons
|
||||
|
||||
* Controlled state transitions and teardown
|
||||
|
||||
* Debug and engineering access
|
||||
|
||||
|
||||
**Out of Scope**
|
||||
|
||||
* Main Hub UI
|
||||
|
||||
* Cloud dashboards
|
||||
|
||||
* User authentication / role management
|
||||
|
||||
|
||||
## 3 Sub-Feature Breakdown
|
||||
|
||||
### 3.1 F-SYS-01: System State Management
|
||||
|
||||
#### Description
|
||||
|
||||
System State Management defines and controls the operational states of the Sensor Hub and governs all valid transitions between them.
|
||||
|
||||
The system operates as a **finite state machine (FSM)** with deterministic behavior.
|
||||
|
||||
#### Typical System States
|
||||
|
||||
* **INIT** – Hardware and software initialization
|
||||
|
||||
* **RUNNING** – Normal sensor acquisition and communication
|
||||
|
||||
* **WARNING** – Non-fatal fault detected, degraded operation
|
||||
|
||||
* **FAULT** – Fatal error, core functionality disabled
|
||||
|
||||
* **OTA\_UPDATE** – Firmware update in progress
|
||||
|
||||
* **MC\_UPDATE** – Machine constants update in progress
|
||||
|
||||
* **TEARDOWN** – Controlled shutdown sequence
|
||||
|
||||
* **IDLE / SERVICE** – Engineering or diagnostic interaction
|
||||
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
* Enforce valid state transitions
|
||||
|
||||
* Notify dependent components of state changes
|
||||
|
||||
* Prevent unsafe operations during restricted states
|
||||
|
||||
|
||||
### 3.2 F-SYS-02: Controlled Teardown Mechanism
|
||||
|
||||
#### Description
|
||||
|
||||
The Controlled Teardown Mechanism ensures that the Sensor Hub transitions safely from an active state into reset, update, or shutdown without data loss or corruption.
|
||||
|
||||
Teardown is triggered by:
|
||||
|
||||
* Firmware update
|
||||
|
||||
* Machine constant update
|
||||
|
||||
* Fatal system fault
|
||||
|
||||
* Manual engineering command
|
||||
|
||||
|
||||
#### Teardown Sequence (Mandatory)
|
||||
|
||||
1. Stop sensor acquisition tasks
|
||||
|
||||
2. Flush pending data via DP component
|
||||
|
||||
3. Persist calibration, diagnostics, and runtime state
|
||||
|
||||
4. Close communication sessions
|
||||
|
||||
5. Release hardware resources
|
||||
|
||||
6. Enter target state (reset, OTA, idle)
|
||||
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
* Guarantee data consistency
|
||||
|
||||
* Ensure deterministic shutdown behavior
|
||||
|
||||
* Prevent flash or SD corruption
|
||||
|
||||
|
||||
### 3.3 F-SYS-03: Status Indication (OLED-Based HMI)
|
||||
|
||||
#### Description
|
||||
|
||||
The Sensor Hub provides local system visibility using an **OLED display connected via I2C**, replacing LED indicators.
|
||||
|
||||
The display, together with **three physical buttons (Up / Down / Select)**, forms a minimal local Human–Machine Interface (HMI).
|
||||
|
||||
#### Default Information Displayed (Main Screen)
|
||||
|
||||
1. **Connectivity status**
|
||||
|
||||
* Connected / Disconnected
|
||||
|
||||
* Signal strength (RSSI) if available
|
||||
|
||||
2. **System status**
|
||||
|
||||
* Current system state (RUNNING, WARNING, FAULT, OTA, etc.)
|
||||
|
||||
3. **Connected sensors**
|
||||
|
||||
* Count and/or summary status
|
||||
|
||||
4. **Time and date**
|
||||
|
||||
* Synchronized system time
|
||||
|
||||
|
||||
#### Menu Navigation Behavior
|
||||
|
||||
* **Select button**
|
||||
|
||||
* From main screen → opens menu
|
||||
|
||||
* From submenu → returns to main screen
|
||||
|
||||
* **Up / Down buttons**
|
||||
|
||||
* Navigate menu entries
|
||||
|
||||
* Scroll within pages if applicable
|
||||
|
||||
|
||||
#### Menu Structure
|
||||
|
||||
**Main Menu**
|
||||
|
||||
* **Diagnostics**
|
||||
|
||||
* Lists active and stored diagnostic codes
|
||||
|
||||
* Displays occurrence count per diagnostic
|
||||
|
||||
* **Sensors**
|
||||
|
||||
* Lists all detected sensors
|
||||
|
||||
* Displays sensor type and configuration status
|
||||
|
||||
* **Health**
|
||||
|
||||
* Displays SD card usage
|
||||
|
||||
* Displays overall system health indicators
|
||||
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
* Provide real-time system visibility
|
||||
|
||||
* Support local inspection without external tools
|
||||
|
||||
* Reflect system state and diagnostics accurately
|
||||
|
||||
|
||||
### 3.4 F-SYS-04: Debug & Engineering Sessions
|
||||
|
||||
#### Description
|
||||
|
||||
Debug & Engineering Sessions allow authorized engineers to interact with the Sensor Hub for diagnostics, inspection, and controlled operations.
|
||||
|
||||
Sessions may be established via:
|
||||
|
||||
* Wired interface (e.g., USB/UART)
|
||||
|
||||
* Secure communication channel (logical session)
|
||||
|
||||
|
||||
#### Supported Capabilities
|
||||
|
||||
* Retrieve diagnostic logs
|
||||
|
||||
* Read machine constant files
|
||||
|
||||
* Inspect system state and health
|
||||
|
||||
* Trigger controlled actions (e.g., reboot, teardown)
|
||||
|
||||
* Monitor runtime logs
|
||||
|
||||
|
||||
#### Session Types
|
||||
|
||||
* **Diagnostic Session** – Read-only access for inspection
|
||||
|
||||
* **Debug Session** – Command execution and deeper inspection
|
||||
|
||||
|
||||
## 4 Functional Interaction Overview
|
||||
|
||||
### System State & Teardown Relationship
|
||||
|
||||
```text
|
||||
RUNNING
|
||||
↓ (Update / Fault)
|
||||
TEARDOWN
|
||||
↓
|
||||
OTA_UPDATE / MC_UPDATE / RESET
|
||||
```
|
||||
|
||||
### Local HMI Interaction
|
||||
|
||||
```text
|
||||
OLED Display ← System State Manager
|
||||
Buttons → UI Controller → State/Menu Logic
|
||||
```
|
||||
|
||||
## 5 System SHALL Requirements (Formal)
|
||||
|
||||
### System State Management
|
||||
|
||||
* **SR-SYS-001**: The system shall implement a defined finite state machine for operational control.
|
||||
|
||||
* **SR-SYS-002**: The system shall restrict operations based on the current system state.
|
||||
|
||||
* **SR-SYS-003**: The system shall notify system components of state transitions.
|
||||
|
||||
|
||||
### Controlled Teardown
|
||||
|
||||
* **SR-SYS-004**: The system shall execute a controlled teardown sequence before firmware or machine constant updates.
|
||||
|
||||
* **SR-SYS-005**: The system shall persist all critical runtime data before completing teardown.
|
||||
|
||||
* **SR-SYS-006**: The system shall prevent data corruption during teardown and reset operations.
|
||||
|
||||
|
||||
### Status Indication & HMI
|
||||
|
||||
* **SR-SYS-007**: The system shall provide a local OLED display using I2C communication.
|
||||
|
||||
* **SR-SYS-008**: The system shall display connectivity status, system state, sensor summary, and time/date.
|
||||
|
||||
* **SR-SYS-009**: The system shall provide menu navigation using Up, Down, and Select buttons.
|
||||
|
||||
* **SR-SYS-010**: The system shall provide diagnostic, sensor, and health information via the local menu.
|
||||
|
||||
|
||||
### Debug & Engineering Sessions
|
||||
|
||||
* **SR-SYS-011**: The system shall support diagnostic sessions for retrieving logs and system status.
|
||||
|
||||
* **SR-SYS-012**: The system shall support debug sessions for controlled engineering operations.
|
||||
|
||||
* **SR-SYS-013**: The system shall restrict debug actions to authorized sessions only.
|
||||
|
||||
|
||||
## 6 Traceability Matrix
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Feature ID</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">System Requirements</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-SYS-01</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-SYS-001, SR-SYS-002, SR-SYS-003</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-SYS-02</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-SYS-004, SR-SYS-005, SR-SYS-006</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-SYS-03</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-SYS-007, SR-SYS-008, SR-SYS-009, SR-SYS-010</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">F-SYS-04</p></td><td class="op-uc-table--cell"><p class="op-uc-p">SR-SYS-011, SR-SYS-012, SR-SYS-013</p></td></tr></tbody></table></figure>
|
||||
|
||||
## 7 Dependencies
|
||||
|
||||
* Diagnostics & Health Monitoring Features
|
||||
|
||||
* Persistence & DP Component
|
||||
|
||||
* Communication Features
|
||||
|
||||
* Security & Safety Features
|
||||
|
||||
* OTA Features
|
||||
|
||||
|
||||
##
|
||||
132
System Design/SRS/Annex_A_Traceability.md
Normal file
132
System Design/SRS/Annex_A_Traceability.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Annex A: Software Requirements Traceability Matrix
|
||||
|
||||
**Document:** SRS Annex A
|
||||
**Version:** 1.0
|
||||
**Date:** 2025-01-19
|
||||
|
||||
## Purpose
|
||||
|
||||
This annex provides complete traceability between:
|
||||
- Features → System Requirements (SR) → Software Requirements (SWR) → Components → Tests
|
||||
|
||||
## Traceability Matrix Structure
|
||||
|
||||
| Feature ID | System Requirement ID | Software Requirement ID | Component | Test ID |
|
||||
|------------|----------------------|------------------------|-----------|---------|
|
||||
| F-SYS-01 | SR-SYS-001 | SWR-SYS-001 | STM (State Manager) | T-SYS-001 |
|
||||
| F-SYS-01 | SR-SYS-001 | SWR-SYS-002 | STM | T-SYS-002 |
|
||||
| F-SYS-01 | SR-SYS-002 | SWR-SYS-003 | STM | T-SYS-003 |
|
||||
| F-SYS-01 | SR-SYS-003 | SWR-SYS-004 | STM, Event System | T-SYS-004 |
|
||||
| F-SYS-02 | SR-SYS-004 | SWR-SYS-005 | STM | T-SYS-005 |
|
||||
| F-SYS-02 | SR-SYS-005 | SWR-SYS-006 | STM, Persistence | T-SYS-006 |
|
||||
| F-SYS-02 | SR-SYS-006 | SWR-SYS-007 | STM, Persistence | T-SYS-007 |
|
||||
| F-SYS-03 | SR-SYS-007 | SWR-SYS-008 | HMI (OLED Driver) | T-SYS-008 |
|
||||
| F-SYS-03 | SR-SYS-008 | SWR-SYS-009 | HMI | T-SYS-009 |
|
||||
| F-SYS-03 | SR-SYS-009 | SWR-SYS-010 | HMI | T-SYS-010 |
|
||||
| F-SYS-03 | SR-SYS-010 | SWR-SYS-011 | HMI, Diagnostics | T-SYS-011 |
|
||||
| F-SYS-04 | SR-SYS-011 | SWR-SYS-012 | Debug Session Manager | T-SYS-012 |
|
||||
| F-SYS-04 | SR-SYS-012 | SWR-SYS-013 | Debug Session Manager | T-SYS-013 |
|
||||
| F-SYS-04 | SR-SYS-013 | SWR-SYS-014 | Debug Session Manager, Security | T-SYS-014 |
|
||||
| F-SYS-04 | SR-SYS-013 | SWR-SYS-015 | Debug Session Manager | T-SYS-015 |
|
||||
| F-DAQ-01 | SR-DAQ-001 | SWR-DAQ-001 | Sensor Manager | T-DAQ-001 |
|
||||
| F-DAQ-01 | SR-DAQ-002 | SWR-DAQ-002 | Sensor Manager | T-DAQ-002 |
|
||||
| F-DAQ-01 | SR-DAQ-003 | SWR-DAQ-003 | Sensor Manager, Sensor Drivers | T-DAQ-003 |
|
||||
| F-DAQ-01 | SR-DAQ-004 | SWR-DAQ-004 | Sensor Manager | T-DAQ-004 |
|
||||
| F-DAQ-02 | SR-DAQ-005 | SWR-DAQ-005 | Sensor Manager | T-DAQ-005 |
|
||||
| F-DAQ-02 | SR-DAQ-006 | SWR-DAQ-006 | Sensor Manager | T-DAQ-006 |
|
||||
| F-DAQ-02 | SR-DAQ-007 | SWR-DAQ-007 | Sensor Manager | T-DAQ-007 |
|
||||
| F-DAQ-03 | SR-DAQ-008 | SWR-DAQ-008 | Sensor Manager, Time Utils | T-DAQ-008 |
|
||||
| F-DAQ-03 | SR-DAQ-009 | SWR-DAQ-009 | Sensor Manager | T-DAQ-009 |
|
||||
| F-DAQ-03 | SR-DAQ-010 | SWR-DAQ-010 | Sensor Manager, Data Pool | T-DAQ-010 |
|
||||
| F-DQC-01 | SR-DQC-001 | SWR-DQC-001 | Sensor Manager, Sensor Drivers | T-DQC-001 |
|
||||
| F-DQC-01 | SR-DQC-002 | SWR-DQC-002 | Sensor Manager | T-DQC-002 |
|
||||
| F-DQC-01 | SR-DQC-003 | SWR-DQC-003 | Sensor Manager | T-DQC-003 |
|
||||
| F-DQC-02 | SR-DQC-004 | SWR-DQC-004 | Sensor Manager | T-DQC-004 |
|
||||
| F-DQC-02 | SR-DQC-005 | SWR-DQC-005 | Sensor Manager | T-DQC-005 |
|
||||
| F-DQC-02 | SR-DQC-006 | SWR-DQC-006 | Sensor Manager, Diagnostics | T-DQC-006 |
|
||||
| F-DQC-03 | SR-DQC-007 | SWR-DQC-007 | Sensor Manager | T-DQC-007 |
|
||||
| F-DQC-03 | SR-DQC-008 | SWR-DQC-008 | Sensor Manager | T-DQC-008 |
|
||||
| F-DQC-03 | SR-DQC-009 | SWR-DQC-009 | Sensor Manager | T-DQC-009 |
|
||||
| F-DQC-03 | SR-DQC-010 | SWR-DQC-010 | Sensor Manager, Communication | T-DQC-010 |
|
||||
| F-DQC-04 | SR-DQC-011 | SWR-DQC-011 | Machine Constant Manager | T-DQC-011 |
|
||||
| F-DQC-04 | SR-DQC-012 | SWR-DQC-012 | Machine Constant Manager, Persistence | T-DQC-012 |
|
||||
| F-DQC-04 | SR-DQC-013 | SWR-DQC-013 | Machine Constant Manager | T-DQC-013 |
|
||||
| F-DQC-04 | SR-DQC-014 | SWR-DQC-014 | Machine Constant Manager, Communication | T-DQC-014 |
|
||||
| F-DQC-04 | SR-DQC-015 | SWR-DQC-015 | Machine Constant Manager, STM | T-DQC-015 |
|
||||
| F-COM-01 | SR-COM-001 | SWR-COM-001 | Main Hub APIs, Network Stack | T-COM-001 |
|
||||
| F-COM-01 | SR-COM-002 | SWR-COM-002 | Main Hub APIs | T-COM-002 |
|
||||
| F-COM-01 | SR-COM-003 | SWR-COM-003 | Main Hub APIs | T-COM-003 |
|
||||
| F-COM-01 | SR-COM-004 | SWR-COM-004 | Network Stack | T-COM-004 |
|
||||
| F-COM-02 | SR-COM-005 | SWR-COM-005 | Main Hub APIs | T-COM-005 |
|
||||
| F-COM-02 | SR-COM-006 | SWR-COM-006 | Main Hub APIs, Data Pool | T-COM-006 |
|
||||
| F-COM-02 | SR-COM-007 | SWR-COM-007 | Main Hub APIs | T-COM-007 |
|
||||
| F-COM-03 | SR-COM-008 | SWR-COM-008 | Network Stack | T-COM-008 |
|
||||
| F-COM-03 | SR-COM-009 | SWR-COM-009 | Network Stack | T-COM-009 |
|
||||
| F-COM-03 | SR-COM-010 | SWR-COM-009 | Network Stack | T-COM-010 |
|
||||
| F-DIAG-01 | SR-DIAG-001 | SWR-DIAG-001 | Diagnostics Task | T-DIAG-001 |
|
||||
| F-DIAG-01 | SR-DIAG-002 | SWR-DIAG-002 | Diagnostics Task | T-DIAG-002 |
|
||||
| F-DIAG-01 | SR-DIAG-003 | SWR-DIAG-003 | Diagnostics Task | T-DIAG-003 |
|
||||
| F-DIAG-01 | SR-DIAG-004 | SWR-DIAG-004 | Diagnostics Task | T-DIAG-004 |
|
||||
| F-DIAG-02 | SR-DIAG-005 | SWR-DIAG-005 | Diagnostics Task, Persistence | T-DIAG-005 |
|
||||
| F-DIAG-02 | SR-DIAG-006 | SWR-DIAG-006 | Diagnostics Task, Persistence | T-DIAG-006 |
|
||||
| F-DIAG-02 | SR-DIAG-007 | SWR-DIAG-007 | Diagnostics Task, Persistence | T-DIAG-007 |
|
||||
| F-DIAG-03 | SR-DIAG-008 | SWR-DIAG-008 | Diagnostics Task | T-DIAG-008 |
|
||||
| F-DIAG-03 | SR-DIAG-009 | SWR-DIAG-009 | Diagnostics Task | T-DIAG-009 |
|
||||
| F-DIAG-03 | SR-DIAG-010 | SWR-DIAG-010 | Diagnostics Task | T-DIAG-010 |
|
||||
| F-DIAG-03 | SR-DIAG-011 | SWR-DIAG-011 | Diagnostics Task | T-DIAG-011 |
|
||||
| F-DATA-01 | SR-DATA-001 | SWR-DATA-001 | Persistence | T-DATA-001 |
|
||||
| F-DATA-01 | SR-DATA-002 | SWR-DATA-002 | Persistence | T-DATA-002 |
|
||||
| F-DATA-01 | SR-DATA-003 | SWR-DATA-003 | Persistence | T-DATA-003 |
|
||||
| F-DATA-02 | SR-DATA-004 | SWR-DATA-004 | Persistence | T-DATA-004 |
|
||||
| F-DATA-02 | SR-DATA-005 | SWR-DATA-005 | Persistence | T-DATA-005 |
|
||||
| F-DATA-02 | SR-DATA-006 | SWR-DATA-006 | Persistence | T-DATA-006 |
|
||||
| F-DATA-03 | SR-DATA-007 | SWR-DATA-007 | Persistence, STM | T-DATA-007 |
|
||||
| F-DATA-03 | SR-DATA-008 | SWR-DATA-008 | Persistence, OTA Manager | T-DATA-008 |
|
||||
| F-DATA-03 | SR-DATA-009 | SWR-DATA-009 | Persistence, STM | T-DATA-009 |
|
||||
| F-OTA-01 | SR-OTA-001 | SWR-OTA-001 | OTA Manager | T-OTA-001 |
|
||||
| F-OTA-01 | SR-OTA-002 | SWR-OTA-002 | OTA Manager | T-OTA-002 |
|
||||
| F-OTA-01 | SR-OTA-003 | SWR-OTA-003 | OTA Manager | T-OTA-003 |
|
||||
| F-OTA-02 | SR-OTA-004 | SWR-OTA-004 | OTA Manager, Network Stack | T-OTA-004 |
|
||||
| F-OTA-02 | SR-OTA-005 | SWR-OTA-005 | OTA Manager, Persistence | T-OTA-005 |
|
||||
| F-OTA-02 | SR-OTA-006 | SWR-OTA-006 | OTA Manager | T-OTA-006 |
|
||||
| F-OTA-03 | SR-OTA-007 | SWR-OTA-007 | OTA Manager, Security | T-OTA-007 |
|
||||
| F-OTA-03 | SR-OTA-008 | SWR-OTA-008 | OTA Manager | T-OTA-008 |
|
||||
| F-OTA-03 | SR-OTA-009 | SWR-OTA-009 | OTA Manager, Communication | T-OTA-009 |
|
||||
| F-OTA-04 | SR-OTA-010 | SWR-OTA-010 | OTA Manager, STM | T-OTA-010 |
|
||||
| F-OTA-04 | SR-OTA-011 | SWR-OTA-011 | OTA Manager, Persistence | T-OTA-011 |
|
||||
| F-OTA-04 | SR-OTA-012 | SWR-OTA-012 | OTA Manager | T-OTA-012 |
|
||||
| F-OTA-04 | SR-OTA-013 | SWR-OTA-013 | OTA Manager | T-OTA-013 |
|
||||
| F-SEC-01 | SR-SEC-001 | SWR-SEC-001 | Security (Secure Boot) | T-SEC-001 |
|
||||
| F-SEC-01 | SR-SEC-002 | SWR-SEC-002 | Security (Secure Boot) | T-SEC-002 |
|
||||
| F-SEC-01 | SR-SEC-003 | SWR-SEC-003 | Security (Secure Boot), STM | T-SEC-003 |
|
||||
| F-SEC-01 | SR-SEC-004 | SWR-SEC-004 | Security (Secure Boot) | T-SEC-004 |
|
||||
| F-SEC-02 | SR-SEC-005 | SWR-SEC-005 | Security (Flash Encryption) | T-SEC-005 |
|
||||
| F-SEC-02 | SR-SEC-006 | SWR-SEC-006 | Security (Flash Encryption), Persistence | T-SEC-006 |
|
||||
| F-SEC-02 | SR-SEC-007 | SWR-SEC-007 | Security (Key Management) | T-SEC-007 |
|
||||
| F-SEC-02 | SR-SEC-008 | SWR-SEC-008 | Security (Data Integrity) | T-SEC-008 |
|
||||
| F-SEC-03 | SR-SEC-009 | SWR-SEC-009 | Security (Communication Encryption) | T-SEC-009 |
|
||||
| F-SEC-03 | SR-SEC-010 | SWR-SEC-010 | Security (Message Integrity) | T-SEC-010 |
|
||||
| F-SEC-03 | SR-SEC-011 | SWR-SEC-011 | Security (OTA Encryption) | T-SEC-011 |
|
||||
| F-SEC-03 | SR-SEC-012 | SWR-SEC-012 | Security, Diagnostics | T-SEC-012 |
|
||||
|
||||
## Component Abbreviations
|
||||
|
||||
- **STM:** State Manager (System Management)
|
||||
- **HMI:** Human-Machine Interface (OLED + Buttons)
|
||||
- **Sensor Manager:** Sensor acquisition and management
|
||||
- **Machine Constant Manager:** Machine constants management
|
||||
- **Main Hub APIs:** Main Hub communication interface
|
||||
- **Network Stack:** Low-level network communication
|
||||
- **Diagnostics Task:** Diagnostics and health monitoring
|
||||
- **Error Handler:** Fault classification and escalation
|
||||
- **Persistence:** Data Persistence component
|
||||
- **OTA Manager:** Firmware update management
|
||||
- **Security:** Security and safety features
|
||||
- **Event System:** Cross-component event communication
|
||||
- **Data Pool:** Runtime data storage
|
||||
|
||||
## Notes
|
||||
|
||||
- Test IDs (T-*) are placeholders for future test specification
|
||||
- Component assignments are preliminary and may be refined during detailed design
|
||||
- Some SWRs may map to multiple components (e.g., SWR-SYS-004 requires STM and Event System)
|
||||
236
System Design/SRS/Annex_B_Interfaces.md
Normal file
236
System Design/SRS/Annex_B_Interfaces.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# Annex B: External Interface Specifications
|
||||
|
||||
**Document:** SRS Annex B
|
||||
**Version:** 1.0
|
||||
**Date:** 2025-01-19
|
||||
|
||||
## Purpose
|
||||
|
||||
This annex defines the external interfaces between the Sensor Hub and external entities (Main Hub, sensors, storage, HMI).
|
||||
|
||||
## 1. Main Hub Communication Interface
|
||||
|
||||
### 1.1 Protocol Stack
|
||||
|
||||
```
|
||||
Application Layer (Sensor Hub APIs)
|
||||
↓
|
||||
Transport Security Layer (TLS/DTLS)
|
||||
↓
|
||||
Network Layer (Wi-Fi / Zigbee / LoRa)
|
||||
↓
|
||||
Physical Layer
|
||||
```
|
||||
|
||||
### 1.2 Message Format
|
||||
|
||||
**Request Message Structure:**
|
||||
```c
|
||||
typedef struct {
|
||||
uint8_t message_type; // REQ_DATA, REQ_STATUS, REQ_DIAG, CMD_CONFIG, CMD_OTA
|
||||
uint16_t message_id; // Unique request ID
|
||||
uint32_t timestamp; // Request timestamp
|
||||
uint16_t payload_length; // Payload length in bytes
|
||||
uint8_t payload[]; // Message-specific payload
|
||||
uint32_t checksum; // Message integrity checksum
|
||||
} main_hub_request_t;
|
||||
```
|
||||
|
||||
**Response Message Structure:**
|
||||
```c
|
||||
typedef struct {
|
||||
uint8_t message_type; // RESP_DATA, RESP_STATUS, RESP_DIAG, ACK, NACK
|
||||
uint16_t message_id; // Matching request ID
|
||||
uint8_t status_code; // SUCCESS, ERROR, TIMEOUT
|
||||
uint32_t timestamp; // Response timestamp
|
||||
uint16_t payload_length; // Payload length in bytes
|
||||
uint8_t payload[]; // Message-specific payload
|
||||
uint32_t checksum; // Message integrity checksum
|
||||
} main_hub_response_t;
|
||||
```
|
||||
|
||||
### 1.3 Message Types
|
||||
|
||||
| Message Type | Direction | Purpose | Payload |
|
||||
|--------------|-----------|---------|---------|
|
||||
| `REQ_DATA` | Main Hub → Sensor Hub | Request latest sensor data | None |
|
||||
| `RESP_DATA` | Sensor Hub → Main Hub | Sensor data response | Sensor data records |
|
||||
| `REQ_STATUS` | Main Hub → Sensor Hub | Request system status | None |
|
||||
| `RESP_STATUS` | Sensor Hub → Main Hub | System status response | Status information |
|
||||
| `REQ_DIAG` | Main Hub → Sensor Hub | Request diagnostic data | Diagnostic filter |
|
||||
| `RESP_DIAG` | Sensor Hub → Main Hub | Diagnostic data response | Diagnostic events |
|
||||
| `CMD_CONFIG` | Main Hub → Sensor Hub | Configuration update | Configuration data |
|
||||
| `CMD_OTA` | Main Hub → Sensor Hub | OTA update request | OTA metadata |
|
||||
| `ACK` | Sensor Hub → Main Hub | Acknowledgment | None or status |
|
||||
| `NACK` | Sensor Hub → Main Hub | Negative acknowledgment | Error code |
|
||||
|
||||
### 1.4 Communication Requirements
|
||||
|
||||
- **Encryption:** All messages SHALL be encrypted using TLS/DTLS
|
||||
- **Authentication:** All messages SHALL be authenticated
|
||||
- **Integrity:** All messages SHALL include integrity checksums
|
||||
- **Timeout:** Request timeout: 5 seconds
|
||||
- **Retry:** Maximum 3 retries with exponential backoff
|
||||
|
||||
## 2. Sensor Interfaces
|
||||
|
||||
### 2.1 Supported Protocols
|
||||
|
||||
| Protocol | Sensor Types | Interface |
|
||||
|----------|--------------|-----------|
|
||||
| I2C | Temperature, Humidity, CO2, NH3, VOC, Light | I2C bus (configurable pins) |
|
||||
| SPI | Particulate matter sensors | SPI bus (configurable pins) |
|
||||
| UART | Some sensor modules | UART (configurable pins) |
|
||||
| Analog | Analog sensors | ADC channels |
|
||||
|
||||
### 2.2 Sensor Detection Signal
|
||||
|
||||
Each sensor slot SHALL provide a dedicated GPIO pin for presence detection:
|
||||
- **High (3.3V):** Sensor present
|
||||
- **Low (0V):** Sensor absent
|
||||
|
||||
### 2.3 Sensor Data Format
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
uint8_t sensor_id; // Unique sensor identifier
|
||||
uint8_t sensor_type; // TEMP, HUM, CO2, NH3, VOC, PM, LIGHT
|
||||
float value; // Filtered sensor value
|
||||
uint8_t unit; // Unit code (C, RH, PPM, LUX, etc.)
|
||||
uint64_t timestamp_us; // Timestamp in microseconds
|
||||
uint8_t validity_status; // VALID, INVALID, DEGRADED, FAILED
|
||||
uint8_t sample_count; // Number of samples used for filtering
|
||||
} sensor_data_record_t;
|
||||
```
|
||||
|
||||
## 3. Storage Interfaces
|
||||
|
||||
### 3.1 SD Card Interface
|
||||
|
||||
**File System:** FAT32
|
||||
**Mount Point:** `/sdcard`
|
||||
|
||||
**Directory Structure:**
|
||||
```
|
||||
/sdcard/
|
||||
├── sensor_data/
|
||||
│ └── YYYYMMDD_HHMMSS.dat
|
||||
├── diagnostics/
|
||||
│ └── diag_log.dat
|
||||
├── machine_constants/
|
||||
│ └── mc.dat
|
||||
└── ota/
|
||||
└── firmware.bin
|
||||
```
|
||||
|
||||
**File Naming Convention:**
|
||||
- Sensor data: `YYYYMMDD_HHMMSS.dat` (timestamp-based)
|
||||
- Diagnostics: `diag_log.dat` (circular log)
|
||||
- Machine constants: `mc.dat` (single file)
|
||||
- OTA firmware: `firmware.bin` (temporary)
|
||||
|
||||
### 3.2 NVM (Non-Volatile Memory) Interface
|
||||
|
||||
**Storage Areas:**
|
||||
- **Machine Constants:** 4KB
|
||||
- **System Configuration:** 2KB
|
||||
- **Diagnostic Log (circular):** 8KB
|
||||
- **OTA Metadata:** 1KB
|
||||
|
||||
**Access Method:** ESP-IDF NVS (Non-Volatile Storage) API
|
||||
|
||||
## 4. HMI Interfaces
|
||||
|
||||
### 4.1 OLED Display Interface
|
||||
|
||||
**Protocol:** I2C
|
||||
**Address:** Configurable (default: 0x3C)
|
||||
**Display:** 128x64 pixels, monochrome
|
||||
|
||||
**Display Content:**
|
||||
- **Main Screen:** Connectivity, System State, Sensor Count, Time/Date
|
||||
- **Menu Screens:** Diagnostics, Sensors, Health
|
||||
|
||||
### 4.2 Button Interface
|
||||
|
||||
**Buttons:** 3 GPIO inputs (Up, Down, Select)
|
||||
|
||||
**Button Behavior:**
|
||||
- **Up:** Navigate menu up / Scroll up
|
||||
- **Down:** Navigate menu down / Scroll down
|
||||
- **Select:** Enter menu / Select item / Return to main screen
|
||||
|
||||
**Debouncing:** Hardware debouncing (10ms) + software debouncing (50ms)
|
||||
|
||||
## 5. Debug Interface
|
||||
|
||||
### 5.1 Physical Interface
|
||||
|
||||
**Protocol:** UART
|
||||
**Baud Rate:** 115200
|
||||
**Data Bits:** 8
|
||||
**Parity:** None
|
||||
**Stop Bits:** 1
|
||||
**Flow Control:** None
|
||||
|
||||
### 5.2 Debug Protocol
|
||||
|
||||
**Session Establishment:**
|
||||
1. Client sends authentication challenge
|
||||
2. Sensor Hub responds with challenge response
|
||||
3. Client sends session key (encrypted)
|
||||
4. Sensor Hub validates and establishes session
|
||||
|
||||
**Debug Commands:**
|
||||
- `READ_DIAG <filter>` - Read diagnostic events
|
||||
- `READ_STATUS` - Read system status
|
||||
- `READ_MC` - Read machine constants
|
||||
- `CLEAR_DIAG` - Clear diagnostic log
|
||||
- `REBOOT` - Reboot system
|
||||
- `TEARDOWN` - Initiate controlled teardown
|
||||
|
||||
**Security:** All debug sessions SHALL be authenticated. Unauthorized access SHALL be rejected and logged as a security violation.
|
||||
|
||||
## 6. Peer Sensor Hub Communication
|
||||
|
||||
### 6.1 Protocol
|
||||
|
||||
**Protocol:** Same as Main Hub communication (Wi-Fi / Zigbee / LoRa)
|
||||
**Message Types:** Limited to connectivity checks and time synchronization
|
||||
|
||||
### 6.2 Message Types
|
||||
|
||||
| Message Type | Purpose |
|
||||
|--------------|---------|
|
||||
| `PEER_PING` | Connectivity check |
|
||||
| `PEER_PONG` | Connectivity response |
|
||||
| `PEER_TIME_SYNC` | Time synchronization request |
|
||||
| `PEER_TIME_RESP` | Time synchronization response |
|
||||
|
||||
### 6.3 Requirements
|
||||
|
||||
- Peer communication SHALL NOT interfere with Main Hub communication
|
||||
- Peer communication SHALL be encrypted and authenticated
|
||||
- Peer communication SHALL be limited to coordination functions only
|
||||
|
||||
## 7. Interface Requirements Summary
|
||||
|
||||
| Interface | Protocol | Encryption | Authentication | Integrity |
|
||||
|-----------|----------|------------|----------------|-----------|
|
||||
| Main Hub | TLS/DTLS over Wi-Fi/Zigbee/LoRa | Yes | Yes | Yes |
|
||||
| Sensors | I2C/SPI/UART/Analog | No | No | No (hardware-level) |
|
||||
| SD Card | SPI (SD protocol) | Optional (SWR-SEC-006) | No | Yes (file system) |
|
||||
| NVM | ESP-IDF NVS | Optional (SWR-SEC-005) | No | Yes (NVS) |
|
||||
| OLED Display | I2C | No | No | No |
|
||||
| Buttons | GPIO | No | No | No |
|
||||
| Debug | UART | Yes | Yes | Yes |
|
||||
| Peer Sensor Hub | Same as Main Hub | Yes | Yes | Yes |
|
||||
|
||||
## 8. Traceability
|
||||
|
||||
- **SWR-IF-001:** Main Hub communication interface
|
||||
- **SWR-IF-002:** Sensor interfaces
|
||||
- **SWR-IF-003:** OLED display interface
|
||||
- **SWR-IF-004:** Button input interfaces
|
||||
- **SWR-IF-005:** Storage interfaces
|
||||
- **SWR-IF-006:** Debug interface
|
||||
230
System Design/SRS/Annex_C_Budgets.md
Normal file
230
System Design/SRS/Annex_C_Budgets.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# Annex C: Timing and Resource Budgets
|
||||
|
||||
**Document:** SRS Annex C
|
||||
**Version:** 1.0
|
||||
**Date:** 2025-01-19
|
||||
|
||||
## Purpose
|
||||
|
||||
This annex defines timing budgets, resource allocation limits, and performance constraints for the Sensor Hub software.
|
||||
|
||||
## 1. Timing Budgets
|
||||
|
||||
### 1.1 Sensor Acquisition Timing
|
||||
|
||||
| Operation | Maximum Duration | Justification |
|
||||
|-----------|------------------|---------------|
|
||||
| Single sensor sample (I2C) | 10ms | I2C transaction time |
|
||||
| Single sensor sample (SPI) | 5ms | SPI transaction time |
|
||||
| Single sensor sample (UART) | 20ms | UART transaction time |
|
||||
| Single sensor sample (Analog/ADC) | 1ms | ADC conversion time |
|
||||
| Filtering (10 samples) | 5ms | Local filtering computation |
|
||||
| Timestamp generation | 1ms | System time access |
|
||||
| Complete acquisition cycle (per sensor) | 100ms | Total per sensor (worst case) |
|
||||
| Complete acquisition cycle (all sensors) | 500ms | 5 sensors × 100ms (with overlap) |
|
||||
|
||||
### 1.2 State Transition Timing
|
||||
|
||||
| Transition | Maximum Duration | Justification |
|
||||
|------------|------------------|---------------|
|
||||
| `[*]` → `INIT` | 100ms | Power-on initialization |
|
||||
| `INIT` → `RUNNING` | 5s | Hardware init, secure boot, MC load |
|
||||
| `INIT` → `BOOT_FAILURE` | 2s | Secure boot verification |
|
||||
| `RUNNING` → `WARNING` | 50ms | Fault detection and state change |
|
||||
| `RUNNING` → `FAULT` | 50ms | Critical fault detection |
|
||||
| `RUNNING` → `OTA_PREP` | 100ms | OTA request processing |
|
||||
| `OTA_PREP` → `TEARDOWN` | 2s | Readiness validation |
|
||||
| `TEARDOWN` → `OTA_UPDATE` | 500ms | Data flush and resource release |
|
||||
| `TEARDOWN` → `INIT` | 500ms | Data flush and reset |
|
||||
| `OTA_UPDATE` → `RUNNING` | 10 minutes | Firmware transfer and flashing |
|
||||
| `RUNNING` → `SERVICE` | 100ms | Debug session establishment |
|
||||
| `SERVICE` → `RUNNING` | 50ms | Debug session closure |
|
||||
| `RUNNING` → `SD_DEGRADED` | 200ms | SD failure detection |
|
||||
|
||||
### 1.3 Communication Timing
|
||||
|
||||
| Operation | Maximum Duration | Justification |
|
||||
|------------|------------------|---------------|
|
||||
| Main Hub request processing | 100ms | Data retrieval and response |
|
||||
| Main Hub message transmission | 50ms | Network transmission (local) |
|
||||
| Main Hub message reception | 50ms | Network reception (local) |
|
||||
| Communication link failure detection | 30s | Heartbeat timeout |
|
||||
| OTA firmware chunk reception | 1s | Network transfer per chunk |
|
||||
| Peer Sensor Hub ping | 100ms | Connectivity check |
|
||||
|
||||
### 1.4 Persistence Timing
|
||||
|
||||
| Operation | Maximum Duration | Justification |
|
||||
|------------|------------------|---------------|
|
||||
| Sensor data write (SD card) | 50ms | File write operation |
|
||||
| Diagnostic event write (SD card) | 20ms | Log append operation |
|
||||
| Machine constants write (NVM) | 10ms | NVS write operation |
|
||||
| Data flush (all pending) | 200ms | Complete flush operation |
|
||||
| SD card failure detection | 500ms | File system check |
|
||||
|
||||
### 1.5 OTA Timing
|
||||
|
||||
| Operation | Maximum Duration | Justification |
|
||||
|------------|------------------|---------------|
|
||||
| OTA readiness validation | 2s | System state and resource check |
|
||||
| Firmware chunk reception | 1s | Network transfer per chunk |
|
||||
| Firmware integrity validation | 5s | Cryptographic verification |
|
||||
| Firmware flashing | 2 minutes | Flash write operation |
|
||||
| Complete OTA operation | 10 minutes | End-to-end OTA process |
|
||||
|
||||
### 1.6 Diagnostic Timing
|
||||
|
||||
| Operation | Maximum Duration | Justification |
|
||||
|------------|------------------|---------------|
|
||||
| Diagnostic event generation | 1ms | Event creation and classification |
|
||||
| Diagnostic event persistence | 20ms | Log write operation |
|
||||
| Diagnostic query processing | 50ms | Log read and filtering |
|
||||
| Fault escalation | 50ms | Severity check and state transition |
|
||||
|
||||
## 2. Resource Budgets
|
||||
|
||||
### 2.1 Memory (RAM) Budget
|
||||
|
||||
| Component | Allocation | Peak Usage | Monitoring Required |
|
||||
|-----------|------------|------------|---------------------|
|
||||
| System (RTOS, ESP-IDF) | 80KB | 100KB | Yes |
|
||||
| Sensor Manager | 20KB | 25KB | Yes |
|
||||
| Event System | 10KB | 15KB | Yes |
|
||||
| Data Pool | 15KB | 20KB | Yes |
|
||||
| Communication Stack | 30KB | 40KB | Yes |
|
||||
| Diagnostics | 10KB | 15KB | Yes |
|
||||
| Persistence | 15KB | 20KB | Yes |
|
||||
| OTA Manager | 20KB | 30KB | Yes |
|
||||
| Security | 10KB | 15KB | Yes |
|
||||
| System Management | 10KB | 15KB | Yes |
|
||||
| HMI | 5KB | 8KB | Yes |
|
||||
| **Total Allocated** | **225KB** | **283KB** | |
|
||||
| **Available (ESP32-S3)** | **512KB** | **512KB** | |
|
||||
| **Utilization** | **44%** | **55%** | |
|
||||
| **Safety Margin** | **56%** | **45%** | |
|
||||
|
||||
**Note:** Peak usage includes worst-case stack usage and temporary buffers. Actual runtime usage SHALL be monitored and maintained below 60% (307KB).
|
||||
|
||||
### 2.2 Flash (Program Memory) Budget
|
||||
|
||||
| Component | Allocation | Notes |
|
||||
|-----------|------------|-------|
|
||||
| Bootloader | 32KB | ESP-IDF bootloader |
|
||||
| Application Code | 1.5MB | Main application firmware |
|
||||
| OTA Partition 0 | 1.5MB | Primary firmware partition |
|
||||
| OTA Partition 1 | 1.5MB | Secondary firmware partition (for updates) |
|
||||
| NVS (Non-Volatile Storage) | 20KB | Configuration and MC storage |
|
||||
| SPIFFS/LittleFS | 500KB | File system (if used) |
|
||||
| **Total Used** | **5.052MB** | |
|
||||
| **Available (8MB Flash)** | **8MB** | |
|
||||
| **Utilization** | **63%** | |
|
||||
| **Safety Margin** | **37%** | |
|
||||
|
||||
### 2.3 CPU Utilization Budget
|
||||
|
||||
| Task | Priority | CPU Usage (Normal) | CPU Usage (Peak) | Notes |
|
||||
|------|----------|-------------------|------------------|-------|
|
||||
| Sensor Acquisition | High | 15% | 25% | Time-critical |
|
||||
| Communication | Medium | 10% | 20% | Network I/O |
|
||||
| Diagnostics | Low | 5% | 10% | Background |
|
||||
| Persistence | Medium | 5% | 15% | Storage I/O |
|
||||
| System Management | High | 5% | 10% | State management |
|
||||
| HMI | Low | 2% | 5% | Display updates |
|
||||
| Idle | - | 58% | 15% | System idle |
|
||||
| **Total** | - | **100%** | **100%** | |
|
||||
|
||||
**Requirement:** CPU utilization SHALL NOT exceed 80% during normal operation (SWR-PERF-005).
|
||||
|
||||
### 2.4 Storage (SD Card) Budget
|
||||
|
||||
| Data Type | Daily Write Volume | Retention Policy | Notes |
|
||||
|-----------|-------------------|------------------|-------|
|
||||
| Sensor Data | 50MB | 7 days (rolling) | 5 sensors × 1 sample/min × 24h |
|
||||
| Diagnostic Log | 5MB | 30 days (circular) | Bounded log with overwrite |
|
||||
| Machine Constants | 1KB | Permanent | Updated only on configuration change |
|
||||
| OTA Firmware | 2MB | Temporary | Deleted after successful update |
|
||||
| **Total Daily Writes** | **57MB** | | |
|
||||
| **SD Card Capacity** | **32GB** (typical) | | |
|
||||
| **Wear Level** | **Low** | | With wear-leveling |
|
||||
|
||||
**Requirement:** SD card writes SHALL be wear-aware to prevent premature failure (SWR-DATA-013).
|
||||
|
||||
### 2.5 Network Bandwidth Budget
|
||||
|
||||
| Operation | Bandwidth | Frequency | Daily Volume |
|
||||
|-----------|-----------|-----------|--------------|
|
||||
| Sensor Data Transmission | 1KB/packet | 1 packet/min | 1.44MB/day |
|
||||
| Diagnostic Reporting | 500B/packet | On-demand | Variable |
|
||||
| Status Updates | 200B/packet | 1 packet/5min | 57.6KB/day |
|
||||
| OTA Firmware Transfer | 2MB | On-demand | Variable |
|
||||
| **Total (Normal Operation)** | - | - | **~1.5MB/day** | |
|
||||
|
||||
**Note:** OTA transfers are infrequent and excluded from daily normal operation budget.
|
||||
|
||||
## 3. Performance Constraints
|
||||
|
||||
### 3.1 Real-Time Constraints
|
||||
|
||||
| Constraint | Requirement | Verification Method |
|
||||
|------------|-------------|---------------------|
|
||||
| Sensor acquisition determinism | ≤ 100ms per sensor | Timing measurement |
|
||||
| State transition determinism | ≤ 50ms (except INIT, TEARDOWN) | Timing measurement |
|
||||
| Communication response time | ≤ 100ms | End-to-end timing |
|
||||
| Data persistence latency | ≤ 200ms | Write operation timing |
|
||||
|
||||
### 3.2 Resource Constraints
|
||||
|
||||
| Resource | Limit | Monitoring | Action on Exceed |
|
||||
|----------|-------|------------|------------------|
|
||||
| RAM Usage | 60% (307KB) | Runtime monitoring | Enter WARNING state, reduce buffers |
|
||||
| CPU Usage | 80% | Runtime monitoring | Reduce task priorities, throttle operations |
|
||||
| SD Card Space | 10% free | File system check | Trigger data retention policy |
|
||||
| Flash Usage | 70% (5.6MB) | Build-time check | Optimize code size |
|
||||
|
||||
### 3.3 Quality Constraints
|
||||
|
||||
| Constraint | Requirement | Verification Method |
|
||||
|------------|-------------|---------------------|
|
||||
| Power loss recovery | < 1 second | Power interruption test |
|
||||
| SD card failure handling | Graceful degradation | SD card removal test |
|
||||
| OTA failure recovery | Rollback capability | OTA failure injection test |
|
||||
| Secure boot failure | BOOT_FAILURE state | Secure boot verification test |
|
||||
|
||||
## 4. Worst-Case Execution Time (WCET) Analysis
|
||||
|
||||
### 4.1 Critical Paths
|
||||
|
||||
**Sensor Acquisition Path:**
|
||||
```
|
||||
Sensor Read (10ms) × 10 samples = 100ms
|
||||
+ Filtering (5ms) = 105ms
|
||||
+ Timestamp (1ms) = 106ms
|
||||
WCET = 110ms (with 4ms margin)
|
||||
```
|
||||
|
||||
**State Transition Path:**
|
||||
```
|
||||
State validation (5ms)
|
||||
+ Component notification (10ms)
|
||||
+ State update (1ms)
|
||||
WCET = 20ms (with 30ms margin for 50ms requirement)
|
||||
```
|
||||
|
||||
**Data Persistence Path:**
|
||||
```
|
||||
Data serialization (10ms)
|
||||
+ File write (50ms)
|
||||
+ Verification (10ms)
|
||||
WCET = 80ms (with 120ms margin for 200ms requirement)
|
||||
```
|
||||
|
||||
## 5. Traceability
|
||||
|
||||
- **SWR-PERF-001:** Sensor acquisition cycle timing
|
||||
- **SWR-PERF-002:** State transition timing
|
||||
- **SWR-PERF-003:** Data persistence timing
|
||||
- **SWR-PERF-004:** OTA operation duration
|
||||
- **SWR-PERF-005:** CPU utilization limit
|
||||
- **SWR-PERF-006:** RAM usage limit
|
||||
- **SWR-PERF-007:** Main Hub response time
|
||||
- **SWR-PERF-008:** Communication link failure detection
|
||||
844
System Design/SRS/SRS.md
Normal file
844
System Design/SRS/SRS.md
Normal file
@@ -0,0 +1,844 @@
|
||||
# Software Requirements Specification (SRS)
|
||||
|
||||
**Document ID:** SRS-ASF-SensorHub-001
|
||||
**Version:** 1.0
|
||||
**Date:** 2025-01-19
|
||||
**Standard:** ISO/IEC/IEEE 29148:2018
|
||||
**Scope:** Sensor Hub (Sub-Hub) Software Requirements
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
### 1.1 Purpose
|
||||
|
||||
This Software Requirements Specification (SRS) defines the software requirements for the ASF Sensor Hub (Sub-Hub) embedded system. This document provides a complete description of all software requirements, derived from system requirements and features, to enable implementation and verification.
|
||||
|
||||
### 1.2 Scope
|
||||
|
||||
This SRS covers:
|
||||
- Sensor Hub firmware running on ESP32-S3
|
||||
- All application-layer components and drivers
|
||||
- Interfaces to Main Hub, sensors, and storage
|
||||
- System state management, diagnostics, and security
|
||||
|
||||
This SRS explicitly excludes:
|
||||
- Main Hub firmware
|
||||
- Cloud services
|
||||
- Hardware design specifications
|
||||
- Manufacturing and deployment procedures
|
||||
|
||||
### 1.3 Definitions, Acronyms, and Abbreviations
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| **DAQ** | Data Acquisition |
|
||||
| **DQC** | Data Quality & Calibration |
|
||||
| **DIAG** | Diagnostics & Health Monitoring |
|
||||
| **DP** | Data Persistence component |
|
||||
| **FSM** | Finite State Machine |
|
||||
| **MC** | Machine Constants |
|
||||
| **NVM** | Non-Volatile Memory |
|
||||
| **OTA** | Over-The-Air (firmware update) |
|
||||
| **SRS** | Software Requirements Specification |
|
||||
| **SR** | System Requirement |
|
||||
| **SWR** | Software Requirement |
|
||||
| **SWRS** | Software Requirements |
|
||||
|
||||
### 1.4 References
|
||||
|
||||
- ISO/IEC/IEEE 29148:2018 - Systems and software engineering - Life cycle processes - Requirements engineering
|
||||
- System Requirements: `System Design/system_requirementsand_and_traceability.csv`
|
||||
- Features: `System Design/Features/`
|
||||
- System State Machine: `System Design/System_State_Machine_Specification.md`
|
||||
- Failure Handling Model: `System Design/Failure_Handling_Model.md`
|
||||
- Cross-Feature Constraints: `System Design/Features/Cross-Feature Constraints.md`
|
||||
|
||||
### 1.5 Overview
|
||||
|
||||
This SRS is organized as follows:
|
||||
- **Section 2:** Overall Description (product perspective, functions, user characteristics, constraints)
|
||||
- **Section 3:** Specific Requirements (functional, interface, performance, design constraints, quality attributes)
|
||||
- **Annex A:** Software Requirements Traceability Matrix
|
||||
- **Annex B:** External Interface Specifications
|
||||
- **Annex C:** Timing and Resource Budgets
|
||||
|
||||
## 2. Overall Description
|
||||
|
||||
### 2.1 Product Perspective
|
||||
|
||||
The Sensor Hub is an embedded system component within the Distributed Intelligent Poultry Farm Environmental Control System (DIPFECS). It operates autonomously but communicates with a Main Hub for data transmission and configuration updates.
|
||||
|
||||
**System Context:**
|
||||
```
|
||||
[Sensors] → [Sensor Hub] ↔ [Main Hub] ↔ [Central Server]
|
||||
↓
|
||||
[SD Card / NVM]
|
||||
```
|
||||
|
||||
### 2.2 Product Functions
|
||||
|
||||
The Sensor Hub software provides the following major functions:
|
||||
|
||||
1. **Sensor Data Acquisition (DAQ)** - Multi-sensor sampling, filtering, timestamping
|
||||
2. **Data Quality & Calibration (DQC)** - Sensor detection, validation, calibration management
|
||||
3. **Communication (COM)** - Bidirectional communication with Main Hub and peer Sensor Hubs
|
||||
4. **Diagnostics & Health Monitoring (DIAG)** - Fault detection, classification, persistent logging
|
||||
5. **Persistence & Data Management (DATA)** - Non-volatile storage of sensor data and system state
|
||||
6. **Firmware Update (OTA)** - Secure over-the-air firmware updates
|
||||
7. **Security & Safety (SEC)** - Secure boot, encrypted storage, encrypted communication
|
||||
8. **System Management (SYS)** - State machine, teardown, HMI, debug sessions
|
||||
|
||||
### 2.3 User Characteristics
|
||||
|
||||
**Primary Users:**
|
||||
- **Farm Operators:** Monitor system status via OLED display
|
||||
- **Engineers:** Access diagnostic and debug sessions
|
||||
- **Main Hub:** Automated data collection and control
|
||||
|
||||
**User Assumptions:**
|
||||
- Farm operators have basic technical knowledge
|
||||
- Engineers have embedded systems expertise
|
||||
- Main Hub communication is automated
|
||||
|
||||
### 2.4 Constraints
|
||||
|
||||
#### 2.4.1 Hardware Constraints
|
||||
- ESP32-S3 microcontroller (dual-core, 512KB SRAM, 8MB flash)
|
||||
- Limited I/O pins for sensors and peripherals
|
||||
- SD card for external storage (subject to wear and failure)
|
||||
- Power: Continuous AC power (with brief interruptions)
|
||||
|
||||
#### 2.4.2 Software Constraints
|
||||
- ESP-IDF v5.4 framework
|
||||
- FreeRTOS for task scheduling
|
||||
- C/C++ programming languages
|
||||
- No dynamic memory allocation in critical paths
|
||||
|
||||
#### 2.4.3 Regulatory Constraints
|
||||
- Animal welfare regulations compliance
|
||||
- Environmental monitoring standards
|
||||
- Security requirements (encryption, authentication)
|
||||
|
||||
#### 2.4.4 Operational Constraints
|
||||
- Harsh environment (humidity, dust, ammonia)
|
||||
- Unattended operation (24/7)
|
||||
- Remote deployment (limited physical access)
|
||||
|
||||
### 2.5 Assumptions and Dependencies
|
||||
|
||||
**Assumptions:**
|
||||
- Sensors are pre-configured and compatible
|
||||
- Main Hub provides time synchronization
|
||||
- Cryptographic keys are securely provisioned
|
||||
- Power interruptions are brief (< 1 second)
|
||||
|
||||
**Dependencies:**
|
||||
- ESP-IDF framework availability and stability
|
||||
- Sensor driver availability
|
||||
- Main Hub communication protocol compatibility
|
||||
|
||||
## 3. Specific Requirements
|
||||
|
||||
### 3.1 Functional Requirements
|
||||
|
||||
#### 3.1.1 System State Management (SWR-SYS-001 through SWR-SYS-015)
|
||||
|
||||
**SWR-SYS-001:** The software SHALL implement a finite state machine (FSM) with the following states: INIT, BOOT_FAILURE, RUNNING, WARNING, FAULT, OTA_PREP, OTA_UPDATE, MC_UPDATE, TEARDOWN, SERVICE, SD_DEGRADED.
|
||||
|
||||
**Traceability:** SR-SYS-001
|
||||
|
||||
**SWR-SYS-002:** The software SHALL enforce valid state transitions as defined in the System State Machine Specification.
|
||||
|
||||
**Traceability:** SR-SYS-001
|
||||
|
||||
**SWR-SYS-003:** The software SHALL restrict feature operations based on the current system state according to per-state execution rules.
|
||||
|
||||
**Traceability:** SR-SYS-002
|
||||
|
||||
**SWR-SYS-004:** The software SHALL notify all registered components when a state transition occurs via the Event System.
|
||||
|
||||
**Traceability:** SR-SYS-003
|
||||
|
||||
**SWR-SYS-005:** The software SHALL execute a controlled teardown sequence before firmware updates, machine constant updates, or system resets.
|
||||
|
||||
**Traceability:** SR-SYS-004
|
||||
|
||||
**SWR-SYS-006:** The software SHALL persist all critical runtime data before completing a teardown sequence.
|
||||
|
||||
**Traceability:** SR-SYS-005
|
||||
|
||||
**SWR-SYS-007:** The software SHALL prevent data corruption during teardown and reset operations.
|
||||
|
||||
**Traceability:** SR-SYS-006
|
||||
|
||||
**SWR-SYS-008:** The software SHALL provide a local OLED display interface using I2C communication protocol.
|
||||
|
||||
**Traceability:** SR-SYS-007
|
||||
|
||||
**SWR-SYS-009:** The software SHALL display connectivity status, system state, connected sensor summary, and time/date on the OLED display.
|
||||
|
||||
**Traceability:** SR-SYS-008
|
||||
|
||||
**SWR-SYS-010:** The software SHALL provide menu navigation using Up, Down, and Select buttons.
|
||||
|
||||
**Traceability:** SR-SYS-009
|
||||
|
||||
**SWR-SYS-011:** The software SHALL provide diagnostic, sensor, and health information through the local OLED menu interface.
|
||||
|
||||
**Traceability:** SR-SYS-010
|
||||
|
||||
**SWR-SYS-012:** The software SHALL support diagnostic sessions for retrieving system status and diagnostic data.
|
||||
|
||||
**Traceability:** SR-SYS-011
|
||||
|
||||
**SWR-SYS-013:** The software SHALL support debug sessions allowing controlled engineering commands.
|
||||
|
||||
**Traceability:** SR-SYS-012
|
||||
|
||||
**SWR-SYS-014:** The software SHALL restrict debug session actions to authorized engineering access only.
|
||||
|
||||
**Traceability:** SR-SYS-013
|
||||
|
||||
**SWR-SYS-015:** The software SHALL ensure debug sessions do not interfere with normal sensor acquisition or communication operations.
|
||||
|
||||
**Traceability:** SR-SYS-013, CFC-DBG-01
|
||||
|
||||
#### 3.1.2 Sensor Data Acquisition (SWR-DAQ-001 through SWR-DAQ-015)
|
||||
|
||||
**SWR-DAQ-001:** The software SHALL support simultaneous acquisition of environmental data from multiple sensor types (temperature, humidity, CO2, NH3, VOC, particulate matter, light).
|
||||
|
||||
**Traceability:** SR-DAQ-001
|
||||
|
||||
**SWR-DAQ-002:** The software SHALL assign each supported sensor type to a predefined and unique hardware slot.
|
||||
|
||||
**Traceability:** SR-DAQ-002
|
||||
|
||||
**SWR-DAQ-003:** The software SHALL detect the physical presence of each sensor via a dedicated hardware detection signal prior to sensor initialization.
|
||||
|
||||
**Traceability:** SR-DAQ-003
|
||||
|
||||
**SWR-DAQ-004:** The software SHALL initialize and activate only sensors that are detected as present and enabled.
|
||||
|
||||
**Traceability:** SR-DAQ-004
|
||||
|
||||
**SWR-DAQ-005:** The software SHALL sample each enabled sensor multiple times within a single acquisition cycle (default: 10 samples per sensor per cycle).
|
||||
|
||||
**Traceability:** SR-DAQ-005
|
||||
|
||||
**SWR-DAQ-006:** The software SHALL apply a local filtering mechanism to raw sensor samples to produce a single filtered sensor value per acquisition cycle.
|
||||
|
||||
**Traceability:** SR-DAQ-006
|
||||
|
||||
**SWR-DAQ-007:** The software SHALL complete each sensor's sampling and filtering process within a bounded and deterministic time window (maximum 100ms per sensor).
|
||||
|
||||
**Traceability:** SR-DAQ-007, CFC-TIME-02
|
||||
|
||||
**SWR-DAQ-008:** The software SHALL generate a timestamp for each filtered sensor value upon completion of the acquisition and filtering process.
|
||||
|
||||
**Traceability:** SR-DAQ-008
|
||||
|
||||
**SWR-DAQ-009:** The software SHALL generate a timestamped sensor data record containing at minimum: sensor identifier, sensor type, filtered value, unit of measurement, timestamp, and data validity status.
|
||||
|
||||
**Traceability:** SR-DAQ-009
|
||||
|
||||
**SWR-DAQ-010:** The software SHALL maintain the most recent timestamped sensor data record in memory and make it available for persistence and on-demand communication requests.
|
||||
|
||||
**Traceability:** SR-DAQ-010
|
||||
|
||||
**SWR-DAQ-011:** The software SHALL NOT perform sensor acquisition during OTA_UPDATE, MC_UPDATE, or TEARDOWN states.
|
||||
|
||||
**Traceability:** CFC-ARCH-02
|
||||
|
||||
**SWR-DAQ-012:** The software SHALL perform sensor acquisition in a non-blocking manner.
|
||||
|
||||
**Traceability:** CFC-TIME-01
|
||||
|
||||
**SWR-DAQ-013:** The software SHALL use deterministic memory allocation for sensor acquisition buffers (no dynamic allocation in acquisition path).
|
||||
|
||||
**Traceability:** CFC-TIME-02
|
||||
|
||||
**SWR-DAQ-014:** The software SHALL publish sensor data updates via the Event System upon completion of each acquisition cycle.
|
||||
|
||||
**Traceability:** Architecture requirement
|
||||
|
||||
**SWR-DAQ-015:** The software SHALL exclude failed sensors from acquisition cycles as defined by the failure handling model.
|
||||
|
||||
**Traceability:** SR-DQC-009
|
||||
|
||||
#### 3.1.3 Data Quality & Calibration (SWR-DQC-001 through SWR-DQC-018)
|
||||
|
||||
**SWR-DQC-001:** The software SHALL detect the physical presence of each sensor using a dedicated hardware-based detection mechanism.
|
||||
|
||||
**Traceability:** SR-DQC-001
|
||||
|
||||
**SWR-DQC-002:** The software SHALL perform sensor presence detection during system startup and after any reinitialization or reconfiguration event.
|
||||
|
||||
**Traceability:** SR-DQC-002
|
||||
|
||||
**SWR-DQC-003:** The software SHALL initialize and activate only sensors that are detected as present.
|
||||
|
||||
**Traceability:** SR-DQC-003
|
||||
|
||||
**SWR-DQC-004:** The software SHALL assign each physical sensor slot to a predefined sensor type.
|
||||
|
||||
**Traceability:** SR-DQC-004
|
||||
|
||||
**SWR-DQC-005:** The software SHALL verify that a detected sensor matches the expected sensor type for its assigned slot.
|
||||
|
||||
**Traceability:** SR-DQC-005
|
||||
|
||||
**SWR-DQC-006:** The software SHALL reject and report any sensor-slot mismatch as a diagnostic event.
|
||||
|
||||
**Traceability:** SR-DQC-006
|
||||
|
||||
**SWR-DQC-007:** The software SHALL continuously monitor sensor responsiveness and signal validity during normal operation.
|
||||
|
||||
**Traceability:** SR-DQC-007
|
||||
|
||||
**SWR-DQC-008:** The software SHALL detect sensor failures including disconnection, non-responsiveness, and out-of-range measurement values.
|
||||
|
||||
**Traceability:** SR-DQC-008
|
||||
|
||||
**SWR-DQC-009:** The software SHALL mark detected faulty sensors as defective and exclude them from data acquisition and reporting.
|
||||
|
||||
**Traceability:** SR-DQC-009
|
||||
|
||||
**SWR-DQC-010:** The software SHALL report detected sensor failures to the Main Hub with timestamps and failure classification.
|
||||
|
||||
**Traceability:** SR-DQC-010
|
||||
|
||||
**SWR-DQC-011:** The software SHALL maintain a Machine Constants dataset defining sensor configuration, calibration parameters, and communication identifiers.
|
||||
|
||||
**Traceability:** SR-DQC-011
|
||||
|
||||
**SWR-DQC-012:** The software SHALL store the Machine Constants dataset in non-volatile storage.
|
||||
|
||||
**Traceability:** SR-DQC-012
|
||||
|
||||
**SWR-DQC-013:** The software SHALL load and apply the Machine Constants dataset during system initialization.
|
||||
|
||||
**Traceability:** SR-DQC-013
|
||||
|
||||
**SWR-DQC-014:** The software SHALL support remote updates of the Machine Constants dataset initiated by the Main Hub.
|
||||
|
||||
**Traceability:** SR-DQC-014
|
||||
|
||||
**SWR-DQC-015:** The software SHALL apply updated Machine Constants only after executing a controlled teardown and reinitialization procedure.
|
||||
|
||||
**Traceability:** SR-DQC-015
|
||||
|
||||
**SWR-DQC-016:** The software SHALL validate Machine Constants integrity before applying updates.
|
||||
|
||||
**Traceability:** SR-SEC-008
|
||||
|
||||
**SWR-DQC-017:** The software SHALL NOT perform sensor calibration during OTA_UPDATE, MC_UPDATE, or TEARDOWN states.
|
||||
|
||||
**Traceability:** CFC-ARCH-02
|
||||
|
||||
**SWR-DQC-018:** The software SHALL access Machine Constants only through the DP component.
|
||||
|
||||
**Traceability:** CFC-ARCH-01, CFC-DATA-01
|
||||
|
||||
#### 3.1.4 Communication (SWR-COM-001 through SWR-COM-015)
|
||||
|
||||
**SWR-COM-001:** The software SHALL support bidirectional communication between the Sensor Hub and the Main Hub.
|
||||
|
||||
**Traceability:** SR-COM-001
|
||||
|
||||
**SWR-COM-002:** The software SHALL transmit sensor data, diagnostics information, and system status to the Main Hub.
|
||||
|
||||
**Traceability:** SR-COM-002
|
||||
|
||||
**SWR-COM-003:** The software SHALL receive commands, configuration updates, and firmware update requests from the Main Hub.
|
||||
|
||||
**Traceability:** SR-COM-003
|
||||
|
||||
**SWR-COM-004:** The software SHALL monitor the status of the communication link with the Main Hub and report link availability and failure conditions.
|
||||
|
||||
**Traceability:** SR-COM-004
|
||||
|
||||
**SWR-COM-005:** The software SHALL support on-demand requests from the Main Hub for sensor data.
|
||||
|
||||
**Traceability:** SR-COM-005
|
||||
|
||||
**SWR-COM-006:** The software SHALL respond to on-demand data requests with the most recent timestamped sensor data.
|
||||
|
||||
**Traceability:** SR-COM-006
|
||||
|
||||
**SWR-COM-007:** The software SHALL include sensor status and data validity information in on-demand data responses.
|
||||
|
||||
**Traceability:** SR-COM-007
|
||||
|
||||
**SWR-COM-008:** The software SHALL support limited peer-to-peer communication between Sensor Hubs for connectivity checks and time synchronization.
|
||||
|
||||
**Traceability:** SR-COM-008, SR-COM-009
|
||||
|
||||
**SWR-COM-009:** The software SHALL ensure that peer Sensor Hub communication does not interfere with Main Hub communication or control operations.
|
||||
|
||||
**Traceability:** SR-COM-010
|
||||
|
||||
**SWR-COM-010:** The software SHALL encrypt all communication with the Main Hub using authenticated encryption.
|
||||
|
||||
**Traceability:** SR-SEC-009, CFC-SEC-02
|
||||
|
||||
**SWR-COM-011:** The software SHALL ensure integrity and authenticity of all transmitted and received messages.
|
||||
|
||||
**Traceability:** SR-SEC-010
|
||||
|
||||
**SWR-COM-012:** The software SHALL limit communication operations during TEARDOWN state to session closure only.
|
||||
|
||||
**Traceability:** CFC-ARCH-02
|
||||
|
||||
**SWR-COM-013:** The software SHALL perform communication operations in a non-blocking manner.
|
||||
|
||||
**Traceability:** CFC-TIME-01
|
||||
|
||||
**SWR-COM-014:** The software SHALL report communication link failures as diagnostic events according to the failure handling model.
|
||||
|
||||
**Traceability:** SR-COM-004, Failure Handling Model
|
||||
|
||||
**SWR-COM-015:** The software SHALL detect and report communication security violations to the Main Hub.
|
||||
|
||||
**Traceability:** SR-SEC-012
|
||||
|
||||
#### 3.1.5 Diagnostics & Health Monitoring (SWR-DIAG-001 through SWR-DIAG-018)
|
||||
|
||||
**SWR-DIAG-001:** The software SHALL implement a diagnostic code framework for reporting system health conditions, warnings, errors, and fatal faults.
|
||||
|
||||
**Traceability:** SR-DIAG-001
|
||||
|
||||
**SWR-DIAG-002:** The software SHALL assign a unique diagnostic code to each detected fault or abnormal condition.
|
||||
|
||||
**Traceability:** SR-DIAG-002
|
||||
|
||||
**SWR-DIAG-003:** The software SHALL classify diagnostic codes by severity level (INFO, WARNING, ERROR, FATAL).
|
||||
|
||||
**Traceability:** SR-DIAG-003
|
||||
|
||||
**SWR-DIAG-004:** The software SHALL associate each diagnostic event with a timestamp and the originating system component.
|
||||
|
||||
**Traceability:** SR-DIAG-004
|
||||
|
||||
**SWR-DIAG-005:** The software SHALL persist diagnostic events in non-volatile storage.
|
||||
|
||||
**Traceability:** SR-DIAG-005
|
||||
|
||||
**SWR-DIAG-006:** The software SHALL retain diagnostic data across system resets and power cycles.
|
||||
|
||||
**Traceability:** SR-DIAG-006
|
||||
|
||||
**SWR-DIAG-007:** The software SHALL implement a bounded diagnostic storage mechanism with a defined overwrite or rollover policy.
|
||||
|
||||
**Traceability:** SR-DIAG-007
|
||||
|
||||
**SWR-DIAG-008:** The software SHALL provide a diagnostic session interface for accessing diagnostic and system health data.
|
||||
|
||||
**Traceability:** SR-DIAG-008
|
||||
|
||||
**SWR-DIAG-009:** The software SHALL allow authorized diagnostic sessions to retrieve stored diagnostic events.
|
||||
|
||||
**Traceability:** SR-DIAG-009
|
||||
|
||||
**SWR-DIAG-010:** The software SHALL allow authorized diagnostic sessions to clear stored diagnostic records.
|
||||
|
||||
**Traceability:** SR-DIAG-010
|
||||
|
||||
**SWR-DIAG-011:** The software SHALL ensure that diagnostic sessions do not interfere with normal sensor acquisition or communication operations.
|
||||
|
||||
**Traceability:** SR-DIAG-011, CFC-DBG-01
|
||||
|
||||
**SWR-DIAG-012:** The software SHALL trigger state transitions based on diagnostic severity according to the failure handling model.
|
||||
|
||||
**Traceability:** Failure Handling Model, SR-SYS-002
|
||||
|
||||
**SWR-DIAG-013:** The software SHALL implement fault latching behavior as defined in the failure handling model.
|
||||
|
||||
**Traceability:** Failure Handling Model
|
||||
|
||||
**SWR-DIAG-014:** The software SHALL implement fault escalation rules as defined in the failure handling model.
|
||||
|
||||
**Traceability:** Failure Handling Model
|
||||
|
||||
**SWR-DIAG-015:** The software SHALL report WARNING, ERROR, and FATAL diagnostic events to the Main Hub.
|
||||
|
||||
**Traceability:** SR-COM-002
|
||||
|
||||
**SWR-DIAG-016:** The software SHALL provide diagnostic information through the local OLED menu interface.
|
||||
|
||||
**Traceability:** SR-SYS-010
|
||||
|
||||
**SWR-DIAG-017:** The software SHALL access diagnostic storage only through the DP component.
|
||||
|
||||
**Traceability:** CFC-ARCH-01, CFC-DATA-01
|
||||
|
||||
**SWR-DIAG-018:** The software SHALL NOT generate new diagnostic events during TEARDOWN state (except teardown-specific diagnostics).
|
||||
|
||||
**Traceability:** CFC-ARCH-02
|
||||
|
||||
#### 3.1.6 Persistence & Data Management (SWR-DATA-001 through SWR-DATA-015)
|
||||
|
||||
**SWR-DATA-001:** The software SHALL persist timestamped sensor data in non-volatile storage.
|
||||
|
||||
**Traceability:** SR-DATA-001
|
||||
|
||||
**SWR-DATA-002:** The software SHALL store sensor data together with sensor identifiers, timestamps, and validity status.
|
||||
|
||||
**Traceability:** SR-DATA-002
|
||||
|
||||
**SWR-DATA-003:** The software SHALL support configurable data retention and overwrite policies for persisted sensor data.
|
||||
|
||||
**Traceability:** SR-DATA-003
|
||||
|
||||
**SWR-DATA-004:** The software SHALL provide a Data Persistence (DP) component as the sole interface for persistent data access.
|
||||
|
||||
**Traceability:** SR-DATA-004, CFC-ARCH-01
|
||||
|
||||
**SWR-DATA-005:** The software SHALL prevent application and feature modules from directly accessing storage hardware.
|
||||
|
||||
**Traceability:** SR-DATA-005, CFC-ARCH-01
|
||||
|
||||
**SWR-DATA-006:** The DP component SHALL support serialization and deserialization of structured system data.
|
||||
|
||||
**Traceability:** SR-DATA-006
|
||||
|
||||
**SWR-DATA-007:** The software SHALL flush all critical runtime data to non-volatile storage before entering a controlled teardown or reset state.
|
||||
|
||||
**Traceability:** SR-DATA-007, SR-SYS-005
|
||||
|
||||
**SWR-DATA-008:** The software SHALL protect data integrity during firmware updates and machine constant updates.
|
||||
|
||||
**Traceability:** SR-DATA-008
|
||||
|
||||
**SWR-DATA-009:** The software SHALL verify successful data persistence before completing a system state transition.
|
||||
|
||||
**Traceability:** SR-DATA-009, CFC-DATA-02
|
||||
|
||||
**SWR-DATA-010:** The software SHALL NOT perform data write operations during TEARDOWN state unless explicitly authorized by the System Manager.
|
||||
|
||||
**Traceability:** CFC-DATA-02
|
||||
|
||||
**SWR-DATA-011:** The software SHALL ensure persistence completion is confirmed before state transitions.
|
||||
|
||||
**Traceability:** CFC-DATA-02
|
||||
|
||||
**SWR-DATA-012:** The software SHALL handle SD card failures gracefully by entering SD_DEGRADED state and disabling persistence writes.
|
||||
|
||||
**Traceability:** System State Machine Specification
|
||||
|
||||
**SWR-DATA-013:** The software SHALL implement wear-aware storage management to prevent premature SD card failure.
|
||||
|
||||
**Traceability:** Quality requirement
|
||||
|
||||
**SWR-DATA-014:** The software SHALL maintain a single source of truth for runtime and persistent data through the DP component.
|
||||
|
||||
**Traceability:** CFC-DATA-01
|
||||
|
||||
**SWR-DATA-015:** The software SHALL NOT allow features to maintain private persistent copies of shared system data.
|
||||
|
||||
**Traceability:** CFC-DATA-01
|
||||
|
||||
#### 3.1.7 Firmware Update (OTA) (SWR-OTA-001 through SWR-OTA-020)
|
||||
|
||||
**SWR-OTA-001:** The software SHALL support OTA update negotiation initiated by the Main Hub.
|
||||
|
||||
**Traceability:** SR-OTA-001
|
||||
|
||||
**SWR-OTA-002:** The software SHALL verify internal readiness conditions before accepting an OTA update request.
|
||||
|
||||
**Traceability:** SR-OTA-002
|
||||
|
||||
**SWR-OTA-003:** The software SHALL explicitly acknowledge or reject OTA update requests.
|
||||
|
||||
**Traceability:** SR-OTA-003
|
||||
|
||||
**SWR-OTA-004:** The software SHALL receive firmware images over the established communication interface.
|
||||
|
||||
**Traceability:** SR-OTA-004
|
||||
|
||||
**SWR-OTA-005:** The software SHALL store received firmware images in non-volatile storage prior to validation.
|
||||
|
||||
**Traceability:** SR-OTA-005
|
||||
|
||||
**SWR-OTA-006:** The software SHALL prevent overwriting the active firmware during firmware reception.
|
||||
|
||||
**Traceability:** SR-OTA-006
|
||||
|
||||
**SWR-OTA-007:** The software SHALL validate the integrity of received firmware images before activation.
|
||||
|
||||
**Traceability:** SR-OTA-007
|
||||
|
||||
**SWR-OTA-008:** The software SHALL reject firmware images that fail integrity validation.
|
||||
|
||||
**Traceability:** SR-OTA-008
|
||||
|
||||
**SWR-OTA-009:** The software SHALL report firmware validation and OTA status to the Main Hub.
|
||||
|
||||
**Traceability:** SR-OTA-009
|
||||
|
||||
**SWR-OTA-010:** The software SHALL execute a controlled teardown procedure prior to firmware activation.
|
||||
|
||||
**Traceability:** SR-OTA-010, SR-SYS-004
|
||||
|
||||
**SWR-OTA-011:** The software SHALL persist critical runtime data and calibration data before flashing new firmware.
|
||||
|
||||
**Traceability:** SR-OTA-011, SR-SYS-005
|
||||
|
||||
**SWR-OTA-012:** The software SHALL activate new firmware only after successful integrity validation.
|
||||
|
||||
**Traceability:** SR-OTA-012
|
||||
|
||||
**SWR-OTA-013:** The software SHALL reboot into the new firmware after successful activation.
|
||||
|
||||
**Traceability:** SR-OTA-013
|
||||
|
||||
**SWR-OTA-014:** The software SHALL use encrypted and authenticated communication channels for OTA firmware updates.
|
||||
|
||||
**Traceability:** SR-SEC-011, CFC-SEC-02
|
||||
|
||||
**SWR-OTA-015:** The software SHALL transition to OTA_PREP state upon accepting an OTA request.
|
||||
|
||||
**Traceability:** System State Machine Specification
|
||||
|
||||
**SWR-OTA-016:** The software SHALL NOT allow OTA operations during WARNING, FAULT, SERVICE, or SD_DEGRADED states.
|
||||
|
||||
**Traceability:** System State Machine Specification, CFC-ARCH-02
|
||||
|
||||
**SWR-OTA-017:** The software SHALL complete OTA operations within a maximum duration of 10 minutes.
|
||||
|
||||
**Traceability:** Quality requirement
|
||||
|
||||
**SWR-OTA-018:** The software SHALL handle OTA failures by transitioning to FAULT state and reporting the failure.
|
||||
|
||||
**Traceability:** System State Machine Specification, Failure Handling Model
|
||||
|
||||
**SWR-OTA-019:** The software SHALL protect active firmware from corruption during OTA operations.
|
||||
|
||||
**Traceability:** SR-OTA-006
|
||||
|
||||
**SWR-OTA-020:** The software SHALL verify firmware authenticity using secure boot mechanisms before execution.
|
||||
|
||||
**Traceability:** SR-SEC-001, SR-SEC-002
|
||||
|
||||
#### 3.1.8 Security & Safety (SWR-SEC-001 through SWR-SEC-020)
|
||||
|
||||
**SWR-SEC-001:** The software SHALL verify the authenticity of the firmware image before execution during every boot cycle.
|
||||
|
||||
**Traceability:** SR-SEC-001, CFC-SEC-01
|
||||
|
||||
**SWR-SEC-002:** The software SHALL prevent execution of firmware images that fail cryptographic verification.
|
||||
|
||||
**Traceability:** SR-SEC-002
|
||||
|
||||
**SWR-SEC-003:** The software SHALL enter BOOT_FAILURE state when secure boot verification fails.
|
||||
|
||||
**Traceability:** SR-SEC-003, System State Machine Specification
|
||||
|
||||
**SWR-SEC-004:** The software SHALL protect the root-of-trust against unauthorized modification.
|
||||
|
||||
**Traceability:** SR-SEC-004
|
||||
|
||||
**SWR-SEC-005:** The software SHALL protect sensitive data stored in internal flash memory from unauthorized access.
|
||||
|
||||
**Traceability:** SR-SEC-005
|
||||
|
||||
**SWR-SEC-006:** The software SHALL support encryption of sensitive data stored in external storage devices.
|
||||
|
||||
**Traceability:** SR-SEC-006
|
||||
|
||||
**SWR-SEC-007:** The software SHALL restrict access to cryptographic keys to authorized system components only.
|
||||
|
||||
**Traceability:** SR-SEC-007
|
||||
|
||||
**SWR-SEC-008:** The software SHALL ensure integrity of stored configuration, calibration, and machine constant data.
|
||||
|
||||
**Traceability:** SR-SEC-008
|
||||
|
||||
**SWR-SEC-009:** The software SHALL encrypt all communication with the Main Hub.
|
||||
|
||||
**Traceability:** SR-SEC-009, CFC-SEC-02
|
||||
|
||||
**SWR-SEC-010:** The software SHALL ensure integrity and authenticity of all transmitted and received messages.
|
||||
|
||||
**Traceability:** SR-SEC-010
|
||||
|
||||
**SWR-SEC-011:** The software SHALL use encrypted and authenticated communication channels for OTA firmware updates.
|
||||
|
||||
**Traceability:** SR-SEC-011, CFC-SEC-02
|
||||
|
||||
**SWR-SEC-012:** The software SHALL detect and report communication and security violations to the Main Hub.
|
||||
|
||||
**Traceability:** SR-SEC-012
|
||||
|
||||
**SWR-SEC-013:** The software SHALL enable secure boot and flash protection before any application-level logic executes.
|
||||
|
||||
**Traceability:** CFC-SEC-01
|
||||
|
||||
**SWR-SEC-014:** The software SHALL authenticate debug sessions before allowing debug operations.
|
||||
|
||||
**Traceability:** SR-SYS-013, CFC-DBG-01
|
||||
|
||||
**SWR-SEC-015:** The software SHALL NOT allow debug sessions to bypass security or safety mechanisms.
|
||||
|
||||
**Traceability:** CFC-DBG-01
|
||||
|
||||
**SWR-SEC-016:** The software SHALL report security violations as FATAL diagnostic events.
|
||||
|
||||
**Traceability:** Failure Handling Model
|
||||
|
||||
**SWR-SEC-017:** The software SHALL protect cryptographic keys during power loss and system resets.
|
||||
|
||||
**Traceability:** Quality requirement
|
||||
|
||||
**SWR-SEC-018:** The software SHALL implement secure session establishment for all external communication.
|
||||
|
||||
**Traceability:** SR-SEC-009
|
||||
|
||||
**SWR-SEC-019:** The software SHALL validate message integrity on every received message.
|
||||
|
||||
**Traceability:** SR-SEC-010
|
||||
|
||||
**SWR-SEC-020:** The software SHALL prevent downgrade attacks by verifying firmware version integrity.
|
||||
|
||||
**Traceability:** Quality requirement
|
||||
|
||||
### 3.2 Interface Requirements
|
||||
|
||||
#### 3.2.1 External Interfaces
|
||||
|
||||
**SWR-IF-001:** The software SHALL provide a communication interface to the Main Hub supporting bidirectional data exchange.
|
||||
|
||||
**Traceability:** SR-COM-001
|
||||
|
||||
**SWR-IF-002:** The software SHALL provide sensor interfaces supporting I2C, SPI, UART, and analog protocols.
|
||||
|
||||
**Traceability:** Architecture requirement
|
||||
|
||||
**SWR-IF-003:** The software SHALL provide an I2C interface for OLED display communication.
|
||||
|
||||
**Traceability:** SR-SYS-007
|
||||
|
||||
**SWR-IF-004:** The software SHALL provide GPIO interfaces for button inputs (Up, Down, Select).
|
||||
|
||||
**Traceability:** SR-SYS-009
|
||||
|
||||
**SWR-IF-005:** The software SHALL provide storage interfaces for SD card and NVM access.
|
||||
|
||||
**Traceability:** Architecture requirement
|
||||
|
||||
**SWR-IF-006:** The software SHALL provide a debug interface (UART/USB) for diagnostic and debug sessions.
|
||||
|
||||
**Traceability:** SR-SYS-011, SR-SYS-012
|
||||
|
||||
#### 3.2.2 Internal Interfaces
|
||||
|
||||
**SWR-IF-007:** The software SHALL provide an Event System interface for cross-component communication.
|
||||
|
||||
**Traceability:** Architecture requirement
|
||||
|
||||
**SWR-IF-008:** The software SHALL provide a Data Pool interface for runtime data access.
|
||||
|
||||
**Traceability:** Architecture requirement
|
||||
|
||||
**SWR-IF-009:** The software SHALL provide a Data Persistence (DP) component interface for persistent storage access.
|
||||
|
||||
**Traceability:** SR-DATA-004, CFC-ARCH-01
|
||||
|
||||
**SWR-IF-010:** The software SHALL provide a System State Manager interface for state queries and transitions.
|
||||
|
||||
**Traceability:** SR-SYS-001
|
||||
|
||||
**SWR-IF-011:** The software SHALL provide a Diagnostics interface for fault reporting and querying.
|
||||
|
||||
**Traceability:** SR-DIAG-001
|
||||
|
||||
**SWR-IF-012:** The software SHALL provide an Error Handler interface for fault classification and escalation.
|
||||
|
||||
**Traceability:** Failure Handling Model
|
||||
|
||||
### 3.3 Performance Requirements
|
||||
|
||||
**SWR-PERF-001:** The software SHALL complete sensor acquisition cycles within 100ms per sensor.
|
||||
|
||||
**Traceability:** SR-DAQ-007, CFC-TIME-02
|
||||
|
||||
**SWR-PERF-002:** The software SHALL complete state transitions within 50ms (except INIT → RUNNING: 5s, TEARDOWN: 500ms).
|
||||
|
||||
**Traceability:** System State Machine Specification
|
||||
|
||||
**SWR-PERF-003:** The software SHALL complete data persistence operations within 200ms.
|
||||
|
||||
**Traceability:** Quality requirement
|
||||
|
||||
**SWR-PERF-004:** The software SHALL complete OTA operations within 10 minutes.
|
||||
|
||||
**Traceability:** SWR-OTA-017
|
||||
|
||||
**SWR-PERF-005:** The software SHALL maintain CPU utilization below 80% during normal operation.
|
||||
|
||||
**Traceability:** Quality requirement
|
||||
|
||||
**SWR-PERF-006:** The software SHALL maintain RAM usage below 60% of available memory.
|
||||
|
||||
**Traceability:** Quality requirement
|
||||
|
||||
**SWR-PERF-007:** The software SHALL respond to Main Hub data requests within 100ms.
|
||||
|
||||
**Traceability:** SR-COM-005, SR-COM-006
|
||||
|
||||
**SWR-PERF-008:** The software SHALL detect communication link failures within 30 seconds.
|
||||
|
||||
**Traceability:** SR-COM-004
|
||||
|
||||
### 3.4 Design Constraints
|
||||
|
||||
**SWR-DESIGN-001:** The software SHALL NOT use dynamic memory allocation in sensor acquisition paths.
|
||||
|
||||
**Traceability:** CFC-TIME-02
|
||||
|
||||
**SWR-DESIGN-002:** The software SHALL implement all features as non-blocking operations.
|
||||
|
||||
**Traceability:** CFC-TIME-01
|
||||
|
||||
**SWR-DESIGN-003:** The software SHALL access hardware only through driver and OSAL layers.
|
||||
|
||||
**Traceability:** CFC-ARCH-01
|
||||
|
||||
**SWR-DESIGN-004:** The software SHALL access persistent storage only through the DP component.
|
||||
|
||||
**Traceability:** CFC-ARCH-01, CFC-DATA-01
|
||||
|
||||
**SWR-DESIGN-005:** The software SHALL respect system state restrictions for all operations.
|
||||
|
||||
**Traceability:** CFC-ARCH-02
|
||||
|
||||
**SWR-DESIGN-006:** The software SHALL use the Event System for all cross-component communication.
|
||||
|
||||
**Traceability:** Architecture requirement
|
||||
|
||||
### 3.5 Quality Attributes
|
||||
|
||||
**SWR-QUAL-001:** The software SHALL recover gracefully from power interruptions (< 1 second).
|
||||
|
||||
**Traceability:** System Assumptions
|
||||
|
||||
**SWR-QUAL-002:** The software SHALL handle SD card failures without system failure.
|
||||
|
||||
**Traceability:** System Limitations
|
||||
|
||||
**SWR-QUAL-003:** The software SHALL maintain data integrity during firmware updates.
|
||||
|
||||
**Traceability:** SR-DATA-008
|
||||
|
||||
**SWR-QUAL-004:** The software SHALL prevent unauthorized firmware execution.
|
||||
|
||||
**Traceability:** SR-SEC-001, SR-SEC-002
|
||||
|
||||
**SWR-QUAL-005:** The software SHALL provide deterministic behavior under all operational conditions.
|
||||
|
||||
**Traceability:** CFC-TIME-02
|
||||
|
||||
## 4. Annexes
|
||||
|
||||
See separate annex documents:
|
||||
- **Annex A:** Software Requirements Traceability Matrix (`Annex_A_Traceability.md`)
|
||||
- **Annex B:** External Interface Specifications (`Annex_B_Interfaces.md`)
|
||||
- **Annex C:** Timing and Resource Budgets (`Annex_C_Budgets.md`)
|
||||
168
System Design/SRS/Traceability_SWRS.csv
Normal file
168
System Design/SRS/Traceability_SWRS.csv
Normal file
@@ -0,0 +1,168 @@
|
||||
SWR_ID,Type,Status,Title,Description,SR_ID,Feature_ID,Component,Test_ID
|
||||
SWR-SYS-001,Software Requirement,Specified,FSM Implementation,The software SHALL implement a finite state machine (FSM) with the following states: INIT, BOOT_FAILURE, RUNNING, WARNING, FAULT, OTA_PREP, OTA_UPDATE, MC_UPDATE, TEARDOWN, SERVICE, SD_DEGRADED.,SR-SYS-001,F-SYS-01,STM,T-SYS-001
|
||||
SWR-SYS-002,Software Requirement,Specified,FSM Transition Enforcement,The software SHALL enforce valid state transitions as defined in the System State Machine Specification.,SR-SYS-001,F-SYS-01,STM,T-SYS-002
|
||||
SWR-SYS-003,Software Requirement,Specified,State-Based Operation Restriction,The software SHALL restrict feature operations based on the current system state according to per-state execution rules.,SR-SYS-002,F-SYS-01,STM,T-SYS-003
|
||||
SWR-SYS-004,Software Requirement,Specified,State Transition Notification,The software SHALL notify all registered components when a state transition occurs via the Event System.,SR-SYS-003,F-SYS-01,"STM, Event System",T-SYS-004
|
||||
SWR-SYS-005,Software Requirement,Specified,Controlled Teardown Execution,The software SHALL execute a controlled teardown sequence before firmware updates, machine constant updates, or system resets.,SR-SYS-004,F-SYS-02,STM,T-SYS-005
|
||||
SWR-SYS-006,Software Requirement,Specified,Critical Data Persistence Before Teardown,The software SHALL persist all critical runtime data before completing a teardown sequence.,SR-SYS-005,F-SYS-02,"STM, Persistence",T-SYS-006
|
||||
SWR-SYS-007,Software Requirement,Specified,Data Integrity Protection During Shutdown,The software SHALL prevent data corruption during teardown and reset operations.,SR-SYS-006,F-SYS-02,"STM, Persistence",T-SYS-007
|
||||
SWR-SYS-008,Software Requirement,Specified,OLED Display Interface,The software SHALL provide a local OLED display interface using I2C communication protocol.,SR-SYS-007,F-SYS-03,HMI,T-SYS-008
|
||||
SWR-SYS-009,Software Requirement,Specified,System Information Display,The software SHALL display connectivity status, system state, connected sensor summary, and time/date on the OLED display.,SR-SYS-008,F-SYS-03,HMI,T-SYS-009
|
||||
SWR-SYS-010,Software Requirement,Specified,Button-Based Menu Navigation,The software SHALL provide menu navigation using Up, Down, and Select buttons.,SR-SYS-009,F-SYS-03,HMI,T-SYS-010
|
||||
SWR-SYS-011,Software Requirement,Specified,Local Diagnostic and Health Menus,The software SHALL provide diagnostic, sensor, and health information through the local OLED menu interface.,SR-SYS-010,F-SYS-03,"HMI, Diagnostics",T-SYS-011
|
||||
SWR-SYS-012,Software Requirement,Specified,Diagnostic Session Support,The software SHALL support diagnostic sessions for retrieving system status and diagnostic data.,SR-SYS-011,F-SYS-04,Debug Session Manager,T-SYS-012
|
||||
SWR-SYS-013,Software Requirement,Specified,Debug Session Support,The software SHALL support debug sessions allowing controlled engineering commands.,SR-SYS-012,F-SYS-04,Debug Session Manager,T-SYS-013
|
||||
SWR-SYS-014,Software Requirement,Specified,Authorized Debug Access Control,The software SHALL restrict debug session actions to authorized engineering access only.,SR-SYS-013,F-SYS-04,"Debug Session Manager, Security",T-SYS-014
|
||||
SWR-SYS-015,Software Requirement,Specified,Non-Intrusive Debug Sessions,The software SHALL ensure debug sessions do not interfere with normal sensor acquisition or communication operations.,SR-SYS-013,F-SYS-04,Debug Session Manager,T-SYS-015
|
||||
SWR-DAQ-001,Software Requirement,Specified,Multi-Sensor Environmental Data Acquisition,The software SHALL support simultaneous acquisition of environmental data from multiple sensor types (temperature, humidity, CO2, NH3, VOC, particulate matter, light).,SR-DAQ-001,F-DAQ-01,Sensor Manager,T-DAQ-001
|
||||
SWR-DAQ-002,Software Requirement,Specified,Dedicated Sensor Slot Mapping,The software SHALL assign each supported sensor type to a predefined and unique hardware slot.,SR-DAQ-002,F-DAQ-01,Sensor Manager,T-DAQ-002
|
||||
SWR-DAQ-003,Software Requirement,Specified,Sensor Presence Detection,The software SHALL detect the physical presence of each sensor via a dedicated hardware detection signal prior to sensor initialization.,SR-DAQ-003,F-DAQ-01,"Sensor Manager, Sensor Drivers",T-DAQ-003
|
||||
SWR-DAQ-004,Software Requirement,Specified,Conditional Sensor Initialization,The software SHALL initialize and activate only sensors that are detected as present and enabled.,SR-DAQ-004,F-DAQ-01,Sensor Manager,T-DAQ-004
|
||||
SWR-DAQ-005,Software Requirement,Specified,High-Frequency Sensor Sampling,The software SHALL sample each enabled sensor multiple times within a single acquisition cycle (default: 10 samples per sensor per cycle).,SR-DAQ-005,F-DAQ-02,Sensor Manager,T-DAQ-005
|
||||
SWR-DAQ-006,Software Requirement,Specified,Local Sensor Data Filtering,The software SHALL apply a local filtering mechanism to raw sensor samples to produce a single filtered sensor value per acquisition cycle.,SR-DAQ-006,F-DAQ-02,Sensor Manager,T-DAQ-006
|
||||
SWR-DAQ-007,Software Requirement,Specified,Deterministic Sampling Window,The software SHALL complete each sensor's sampling and filtering process within a bounded and deterministic time window (maximum 100ms per sensor).,SR-DAQ-007,F-DAQ-02,Sensor Manager,T-DAQ-007
|
||||
SWR-DAQ-008,Software Requirement,Specified,Timestamp Generation for Sensor Data,The software SHALL generate a timestamp for each filtered sensor value upon completion of the acquisition and filtering process.,SR-DAQ-008,F-DAQ-03,"Sensor Manager, Time Utils",T-DAQ-008
|
||||
SWR-DAQ-009,Software Requirement,Specified,Timestamped Sensor Data Record Structure,The software SHALL generate a timestamped sensor data record containing at minimum: sensor identifier, sensor type, filtered value, unit of measurement, timestamp, and data validity status.,SR-DAQ-009,F-DAQ-03,Sensor Manager,T-DAQ-009
|
||||
SWR-DAQ-010,Software Requirement,Specified,Availability of Latest Sensor Data,The software SHALL maintain the most recent timestamped sensor data record in memory and make it available for persistence and on-demand communication requests.,SR-DAQ-010,F-DAQ-03,"Sensor Manager, Data Pool",T-DAQ-010
|
||||
SWR-DAQ-011,Software Requirement,Specified,State-Restricted Sensor Acquisition,The software SHALL NOT perform sensor acquisition during OTA_UPDATE, MC_UPDATE, or TEARDOWN states.,CFC-ARCH-02,F-DAQ-01,Sensor Manager,T-DAQ-011
|
||||
SWR-DAQ-012,Software Requirement,Specified,Non-Blocking Sensor Acquisition,The software SHALL perform sensor acquisition in a non-blocking manner.,CFC-TIME-01,F-DAQ-02,Sensor Manager,T-DAQ-012
|
||||
SWR-DAQ-013,Software Requirement,Specified,Deterministic Memory Allocation,The software SHALL use deterministic memory allocation for sensor acquisition buffers (no dynamic allocation in acquisition path).,CFC-TIME-02,F-DAQ-02,Sensor Manager,T-DAQ-013
|
||||
SWR-DAQ-014,Software Requirement,Specified,Sensor Data Event Publishing,The software SHALL publish sensor data updates via the Event System upon completion of each acquisition cycle.,Architecture Requirement,F-DAQ-03,"Sensor Manager, Event System",T-DAQ-014
|
||||
SWR-DAQ-015,Software Requirement,Specified,Failed Sensor Exclusion,The software SHALL exclude failed sensors from acquisition cycles as defined by the failure handling model.,SR-DQC-009,F-DAQ-01,Sensor Manager,T-DAQ-015
|
||||
SWR-DQC-001,Software Requirement,Specified,Detect Sensor Presence,The software SHALL detect the physical presence of each sensor using a dedicated hardware-based detection mechanism.,SR-DQC-001,F-DQC-01,"Sensor Manager, Sensor Drivers",T-DQC-001
|
||||
SWR-DQC-002,Software Requirement,Specified,Perform Sensor Detection During Initialization,The software SHALL perform sensor presence detection during system startup and after any reinitialization or reconfiguration event.,SR-DQC-002,F-DQC-01,Sensor Manager,T-DQC-002
|
||||
SWR-DQC-003,Software Requirement,Specified,Conditional Sensor Initialization,The software SHALL initialize and activate only sensors that are detected as present.,SR-DQC-003,F-DQC-01,Sensor Manager,T-DQC-003
|
||||
SWR-DQC-004,Software Requirement,Specified,Assign Fixed Sensor Slot Types,The software SHALL assign each physical sensor slot to a predefined sensor type.,SR-DQC-004,F-DQC-02,Sensor Manager,T-DQC-004
|
||||
SWR-DQC-005,Software Requirement,Specified,Verify Sensor Type Compatibility,The software SHALL verify that a detected sensor matches the expected sensor type for its assigned slot.,SR-DQC-005,F-DQC-02,Sensor Manager,T-DQC-005
|
||||
SWR-DQC-006,Software Requirement,Specified,Reject Invalid Sensor Configurations,The software SHALL reject and report any sensor-slot mismatch as a diagnostic event.,SR-DQC-006,F-DQC-02,"Sensor Manager, Diagnostics",T-DQC-006
|
||||
SWR-DQC-007,Software Requirement,Specified,Monitor Sensor Health,The software SHALL continuously monitor sensor responsiveness and signal validity during normal operation.,SR-DQC-007,F-DQC-03,Sensor Manager,T-DQC-007
|
||||
SWR-DQC-008,Software Requirement,Specified,Detect Sensor Failure Conditions,The software SHALL detect sensor failures including disconnection, non-responsiveness, and out-of-range measurement values.,SR-DQC-008,F-DQC-03,Sensor Manager,T-DQC-008
|
||||
SWR-DQC-009,Software Requirement,Specified,Isolate Failed Sensors,The software SHALL mark detected faulty sensors as defective and exclude them from data acquisition and reporting.,SR-DQC-009,F-DQC-03,Sensor Manager,T-DQC-009
|
||||
SWR-DQC-010,Software Requirement,Specified,Report Sensor Failures,The software SHALL report detected sensor failures to the Main Hub with timestamps and failure classification.,SR-DQC-010,F-DQC-03,"Sensor Manager, Communication",T-DQC-010
|
||||
SWR-DQC-011,Software Requirement,Specified,Maintain Machine Constants Dataset,The software SHALL maintain a Machine Constants dataset defining sensor configuration, calibration parameters, and communication identifiers.,SR-DQC-011,F-DQC-04,Machine Constant Manager,T-DQC-011
|
||||
SWR-DQC-012,Software Requirement,Specified,Persist Machine Constants,The software SHALL store the Machine Constants dataset in non-volatile storage.,SR-DQC-012,F-DQC-04,"Machine Constant Manager, Persistence",T-DQC-012
|
||||
SWR-DQC-013,Software Requirement,Specified,Load Machine Constants at Startup,The software SHALL load and apply the Machine Constants dataset during system initialization.,SR-DQC-013,F-DQC-04,Machine Constant Manager,T-DQC-013
|
||||
SWR-DQC-014,Software Requirement,Specified,Support Remote Machine Constants Update,The software SHALL support remote updates of the Machine Constants dataset initiated by the Main Hub.,SR-DQC-014,F-DQC-04,"Machine Constant Manager, Communication",T-DQC-014
|
||||
SWR-DQC-015,Software Requirement,Specified,Controlled Reinitialization After Update,The software SHALL apply updated Machine Constants only after executing a controlled teardown and reinitialization procedure.,SR-DQC-015,F-DQC-04,"Machine Constant Manager, STM",T-DQC-015
|
||||
SWR-DQC-016,Software Requirement,Specified,Machine Constants Integrity Validation,The software SHALL validate Machine Constants integrity before applying updates.,SR-SEC-008,F-DQC-04,"Machine Constant Manager, Security",T-DQC-016
|
||||
SWR-DQC-017,Software Requirement,Specified,State-Restricted Calibration,The software SHALL NOT perform sensor calibration during OTA_UPDATE, MC_UPDATE, or TEARDOWN states.,CFC-ARCH-02,F-DQC-04,Sensor Manager,T-DQC-017
|
||||
SWR-DQC-018,Software Requirement,Specified,Machine Constants Access via DP,The software SHALL access Machine Constants only through the DP component.,CFC-ARCH-01,F-DQC-04,"Machine Constant Manager, Persistence",T-DQC-018
|
||||
SWR-COM-001,Software Requirement,Specified,Bidirectional Main Hub Communication,The software SHALL support bidirectional communication between the Sensor Hub and the Main Hub.,SR-COM-001,F-COM-01,"Main Hub APIs, Network Stack",T-COM-001
|
||||
SWR-COM-002,Software Requirement,Specified,Transmit Data to Main Hub,The software SHALL transmit sensor data, diagnostics information, and system status to the Main Hub.,SR-COM-002,F-COM-01,Main Hub APIs,T-COM-002
|
||||
SWR-COM-003,Software Requirement,Specified,Receive Commands from Main Hub,The software SHALL receive commands, configuration updates, and firmware update requests from the Main Hub.,SR-COM-003,F-COM-01,Main Hub APIs,T-COM-003
|
||||
SWR-COM-004,Software Requirement,Specified,Monitor Communication Link Status,The software SHALL monitor the status of the communication link with the Main Hub and report link availability and failure conditions.,SR-COM-004,F-COM-01,Network Stack,T-COM-004
|
||||
SWR-COM-005,Software Requirement,Specified,Support On-Demand Data Requests,The software SHALL support on-demand requests from the Main Hub for sensor data.,SR-COM-005,F-COM-02,Main Hub APIs,T-COM-005
|
||||
SWR-COM-006,Software Requirement,Specified,Respond with Latest Sensor Data,The software SHALL respond to on-demand data requests with the most recent timestamped sensor data.,SR-COM-006,F-COM-02,"Main Hub APIs, Data Pool",T-COM-006
|
||||
SWR-COM-007,Software Requirement,Specified,Include Data Validity in Responses,The software SHALL include sensor status and data validity information in on-demand data responses.,SR-COM-007,F-COM-02,Main Hub APIs,T-COM-007
|
||||
SWR-COM-008,Software Requirement,Specified,Support Peer Sensor Hub Communication,The software SHALL support limited peer-to-peer communication between Sensor Hubs for connectivity checks and time synchronization.,SR-COM-008,F-COM-03,Network Stack,T-COM-008
|
||||
SWR-COM-009,Software Requirement,Specified,Isolate Peer Communication,The software SHALL ensure that peer Sensor Hub communication does not interfere with Main Hub communication or control operations.,SR-COM-010,F-COM-03,Network Stack,T-COM-009
|
||||
SWR-COM-010,Software Requirement,Specified,Encrypted Main Hub Communication,The software SHALL encrypt all communication with the Main Hub using authenticated encryption.,SR-SEC-009,F-COM-01,"Network Stack, Security",T-COM-010
|
||||
SWR-COM-011,Software Requirement,Specified,Message Integrity and Authenticity,The software SHALL ensure integrity and authenticity of all transmitted and received messages.,SR-SEC-010,F-COM-01,"Network Stack, Security",T-COM-011
|
||||
SWR-COM-012,Software Requirement,Specified,State-Restricted Communication,The software SHALL limit communication operations during TEARDOWN state to session closure only.,CFC-ARCH-02,F-COM-01,Network Stack,T-COM-012
|
||||
SWR-COM-013,Software Requirement,Specified,Non-Blocking Communication,The software SHALL perform communication operations in a non-blocking manner.,CFC-TIME-01,F-COM-01,Network Stack,T-COM-013
|
||||
SWR-COM-014,Software Requirement,Specified,Communication Link Failure Reporting,The software SHALL report communication link failures as diagnostic events according to the failure handling model.,SR-COM-004,F-COM-01,"Network Stack, Diagnostics",T-COM-014
|
||||
SWR-COM-015,Software Requirement,Specified,Security Violation Reporting,The software SHALL detect and report communication security violations to the Main Hub.,SR-SEC-012,F-COM-01,"Network Stack, Security",T-COM-015
|
||||
SWR-DIAG-001,Software Requirement,Specified,Diagnostic Code Framework,The software SHALL implement a diagnostic code framework for reporting system health conditions, warnings, errors, and fatal faults.,SR-DIAG-001,F-DIAG-01,Diagnostics Task,T-DIAG-001
|
||||
SWR-DIAG-002,Software Requirement,Specified,Assign Unique Diagnostic Codes,The software SHALL assign a unique diagnostic code to each detected fault or abnormal condition.,SR-DIAG-002,F-DIAG-01,Diagnostics Task,T-DIAG-002
|
||||
SWR-DIAG-003,Software Requirement,Specified,Classify Diagnostic Severity,The software SHALL classify diagnostic codes by severity level (INFO, WARNING, ERROR, FATAL).,SR-DIAG-003,F-DIAG-01,Diagnostics Task,T-DIAG-003
|
||||
SWR-DIAG-004,Software Requirement,Specified,Timestamp and Source Diagnostics,The software SHALL associate each diagnostic event with a timestamp and the originating system component.,SR-DIAG-004,F-DIAG-01,Diagnostics Task,T-DIAG-004
|
||||
SWR-DIAG-005,Software Requirement,Specified,Persist Diagnostic Events,The software SHALL persist diagnostic events in non-volatile storage.,SR-DIAG-005,F-DIAG-02,"Diagnostics Task, Persistence",T-DIAG-005
|
||||
SWR-DIAG-006,Software Requirement,Specified,Retain Diagnostics Across Resets,The software SHALL retain diagnostic data across system resets and power cycles.,SR-DIAG-006,F-DIAG-02,"Diagnostics Task, Persistence",T-DIAG-006
|
||||
SWR-DIAG-007,Software Requirement,Specified,Bounded Diagnostic Storage,The software SHALL implement a bounded diagnostic storage mechanism with a defined overwrite or rollover policy.,SR-DIAG-007,F-DIAG-02,"Diagnostics Task, Persistence",T-DIAG-007
|
||||
SWR-DIAG-008,Software Requirement,Specified,Provide Diagnostic Session Interface,The software SHALL provide a diagnostic session interface for accessing diagnostic and system health data.,SR-DIAG-008,F-DIAG-03,Diagnostics Task,T-DIAG-008
|
||||
SWR-DIAG-009,Software Requirement,Specified,Retrieve Diagnostic Records,The software SHALL allow authorized diagnostic sessions to retrieve stored diagnostic events.,SR-DIAG-009,F-DIAG-03,Diagnostics Task,T-DIAG-009
|
||||
SWR-DIAG-010,Software Requirement,Specified,Clear Diagnostic Records,The software SHALL allow authorized diagnostic sessions to clear stored diagnostic records.,SR-DIAG-010,F-DIAG-03,Diagnostics Task,T-DIAG-010
|
||||
SWR-DIAG-011,Software Requirement,Specified,Non-Intrusive Diagnostic Sessions,The software SHALL ensure that diagnostic sessions do not interfere with normal sensor acquisition or communication operations.,SR-DIAG-011,F-DIAG-03,Diagnostics Task,T-DIAG-011
|
||||
SWR-DIAG-012,Software Requirement,Specified,Fault-to-State Transition,The software SHALL trigger state transitions based on diagnostic severity according to the failure handling model.,Failure Handling Model,F-DIAG-01,"Diagnostics Task, Error Handler",T-DIAG-012
|
||||
SWR-DIAG-013,Software Requirement,Specified,Fault Latching Behavior,The software SHALL implement fault latching behavior as defined in the failure handling model.,Failure Handling Model,F-DIAG-01,Error Handler,T-DIAG-013
|
||||
SWR-DIAG-014,Software Requirement,Specified,Fault Escalation Rules,The software SHALL implement fault escalation rules as defined in the failure handling model.,Failure Handling Model,F-DIAG-01,Error Handler,T-DIAG-014
|
||||
SWR-DIAG-015,Software Requirement,Specified,Diagnostic Event Reporting to Main Hub,The software SHALL report WARNING, ERROR, and FATAL diagnostic events to the Main Hub.,SR-COM-002,F-DIAG-02,"Diagnostics Task, Communication",T-DIAG-015
|
||||
SWR-DIAG-016,Software Requirement,Specified,Diagnostic Information via HMI,The software SHALL provide diagnostic information through the local OLED menu interface.,SR-SYS-010,F-DIAG-03,"Diagnostics Task, HMI",T-DIAG-016
|
||||
SWR-DIAG-017,Software Requirement,Specified,Diagnostic Storage Access via DP,The software SHALL access diagnostic storage only through the DP component.,CFC-ARCH-01,F-DIAG-02,"Diagnostics Task, Persistence",T-DIAG-017
|
||||
SWR-DIAG-018,Software Requirement,Specified,State-Restricted Diagnostic Generation,The software SHALL NOT generate new diagnostic events during TEARDOWN state (except teardown-specific diagnostics).,CFC-ARCH-02,F-DIAG-01,Diagnostics Task,T-DIAG-018
|
||||
SWR-DATA-001,Software Requirement,Specified,Persistent Timestamped Sensor Data,The software SHALL persist timestamped sensor data in non-volatile storage.,SR-DATA-001,F-DATA-01,Persistence,T-DATA-001
|
||||
SWR-DATA-002,Software Requirement,Specified,Sensor Data Metadata Storage,The software SHALL store sensor data together with sensor identifiers, timestamps, and validity status.,SR-DATA-002,F-DATA-01,Persistence,T-DATA-002
|
||||
SWR-DATA-003,Software Requirement,Specified,Configurable Data Retention Policy,The software SHALL support configurable data retention and overwrite policies for persisted sensor data.,SR-DATA-003,F-DATA-01,Persistence,T-DATA-003
|
||||
SWR-DATA-004,Software Requirement,Specified,Data Persistence Component Interface,The software SHALL provide a Data Persistence (DP) component as the sole interface for persistent data access.,SR-DATA-004,F-DATA-02,Persistence,T-DATA-004
|
||||
SWR-DATA-005,Software Requirement,Specified,Storage Access Isolation,The software SHALL prevent application and feature modules from directly accessing storage hardware.,SR-DATA-005,F-DATA-02,Persistence,T-DATA-005
|
||||
SWR-DATA-006,Software Requirement,Specified,Structured Data Serialization,The DP component SHALL support serialization and deserialization of structured system data.,SR-DATA-006,F-DATA-02,Persistence,T-DATA-006
|
||||
SWR-DATA-007,Software Requirement,Specified,Data Flush Before Teardown,The software SHALL flush all critical runtime data to non-volatile storage before entering a controlled teardown or reset state.,SR-DATA-007,F-DATA-03,"Persistence, STM",T-DATA-007
|
||||
SWR-DATA-008,Software Requirement,Specified,Data Integrity During Updates,The software SHALL protect data integrity during firmware updates and machine constant updates.,SR-DATA-008,F-DATA-03,"Persistence, OTA Manager",T-DATA-008
|
||||
SWR-DATA-009,Software Requirement,Specified,Persistence Verification,The software SHALL verify successful data persistence before completing a system state transition.,SR-DATA-009,F-DATA-03,"Persistence, STM",T-DATA-009
|
||||
SWR-DATA-010,Software Requirement,Specified,State-Restricted Data Writes,The software SHALL NOT perform data write operations during TEARDOWN state unless explicitly authorized by the System Manager.,CFC-DATA-02,F-DATA-03,Persistence,T-DATA-010
|
||||
SWR-DATA-011,Software Requirement,Specified,Persistence Completion Confirmation,The software SHALL ensure persistence completion is confirmed before state transitions.,CFC-DATA-02,F-DATA-03,"Persistence, STM",T-DATA-011
|
||||
SWR-DATA-012,Software Requirement,Specified,SD Card Failure Handling,The software SHALL handle SD card failures gracefully by entering SD_DEGRADED state and disabling persistence writes.,System State Machine Specification,F-DATA-01,"Persistence, STM",T-DATA-012
|
||||
SWR-DATA-013,Software Requirement,Specified,Wear-Aware Storage Management,The software SHALL implement wear-aware storage management to prevent premature SD card failure.,Quality Requirement,F-DATA-01,Persistence,T-DATA-013
|
||||
SWR-DATA-014,Software Requirement,Specified,Single Source of Truth,The software SHALL maintain a single source of truth for runtime and persistent data through the DP component.,CFC-DATA-01,F-DATA-02,"Data Pool, Persistence",T-DATA-014
|
||||
SWR-DATA-015,Software Requirement,Specified,No Private Persistent Copies,The software SHALL NOT allow features to maintain private persistent copies of shared system data.,CFC-DATA-01,F-DATA-02,All Components,T-DATA-015
|
||||
SWR-OTA-001,Software Requirement,Specified,OTA Negotiation Support,The software SHALL support OTA update negotiation initiated by the Main Hub.,SR-OTA-001,F-OTA-01,OTA Manager,T-OTA-001
|
||||
SWR-OTA-002,Software Requirement,Specified,OTA Readiness Validation,The software SHALL verify internal readiness conditions before accepting an OTA update request.,SR-OTA-002,F-OTA-01,OTA Manager,T-OTA-002
|
||||
SWR-OTA-003,Software Requirement,Specified,OTA Acknowledgement,The software SHALL explicitly acknowledge or reject OTA update requests.,SR-OTA-003,F-OTA-01,OTA Manager,T-OTA-003
|
||||
SWR-OTA-004,Software Requirement,Specified,Firmware Reception,The software SHALL receive firmware images over the established communication interface.,SR-OTA-004,F-OTA-02,"OTA Manager, Network Stack",T-OTA-004
|
||||
SWR-OTA-005,Software Requirement,Specified,Firmware Temporary Storage,The software SHALL store received firmware images in non-volatile storage prior to validation.,SR-OTA-005,F-OTA-02,"OTA Manager, Persistence",T-OTA-005
|
||||
SWR-OTA-006,Software Requirement,Specified,Active Firmware Protection,The software SHALL prevent overwriting the active firmware during firmware reception.,SR-OTA-006,F-OTA-02,OTA Manager,T-OTA-006
|
||||
SWR-OTA-007,Software Requirement,Specified,Firmware Integrity Verification,The software SHALL validate the integrity of received firmware images before activation.,SR-OTA-007,F-OTA-03,"OTA Manager, Security",T-OTA-007
|
||||
SWR-OTA-008,Software Requirement,Specified,Firmware Rejection Handling,The software SHALL reject firmware images that fail integrity validation.,SR-OTA-008,F-OTA-03,OTA Manager,T-OTA-008
|
||||
SWR-OTA-009,Software Requirement,Specified,OTA Status Reporting,The software SHALL report firmware validation and OTA status to the Main Hub.,SR-OTA-009,F-OTA-03,"OTA Manager, Communication",T-OTA-009
|
||||
SWR-OTA-010,Software Requirement,Specified,OTA Teardown Execution,The software SHALL execute a controlled teardown procedure prior to firmware activation.,SR-OTA-010,F-OTA-04,"OTA Manager, STM",T-OTA-010
|
||||
SWR-OTA-011,Software Requirement,Specified,Data Persistence Before Flashing,The software SHALL persist critical runtime data and calibration data before flashing new firmware.,SR-OTA-011,F-OTA-04,"OTA Manager, Persistence",T-OTA-011
|
||||
SWR-OTA-012,Software Requirement,Specified,Controlled Firmware Activation,The software SHALL activate new firmware only after successful integrity validation.,SR-OTA-012,F-OTA-04,OTA Manager,T-OTA-012
|
||||
SWR-OTA-013,Software Requirement,Specified,OTA Reboot Execution,The software SHALL reboot into the new firmware after successful activation.,SR-OTA-013,F-OTA-04,OTA Manager,T-OTA-013
|
||||
SWR-OTA-014,Software Requirement,Specified,Encrypted OTA Communication,The software SHALL use encrypted and authenticated communication channels for OTA firmware updates.,SR-SEC-011,F-OTA-02,"OTA Manager, Security",T-OTA-014
|
||||
SWR-OTA-015,Software Requirement,Specified,OTA State Transition,The software SHALL transition to OTA_PREP state upon accepting an OTA request.,System State Machine Specification,F-OTA-01,"OTA Manager, STM",T-OTA-015
|
||||
SWR-OTA-016,Software Requirement,Specified,State-Restricted OTA Operations,The software SHALL NOT allow OTA operations during WARNING, FAULT, SERVICE, or SD_DEGRADED states.,System State Machine Specification,F-OTA-01,"OTA Manager, STM",T-OTA-016
|
||||
SWR-OTA-017,Software Requirement,Specified,OTA Duration Limit,The software SHALL complete OTA operations within a maximum duration of 10 minutes.,Quality Requirement,F-OTA-04,OTA Manager,T-OTA-017
|
||||
SWR-OTA-018,Software Requirement,Specified,OTA Failure Handling,The software SHALL handle OTA failures by transitioning to FAULT state and reporting the failure.,System State Machine Specification,F-OTA-04,"OTA Manager, STM",T-OTA-018
|
||||
SWR-OTA-019,Software Requirement,Specified,Active Firmware Corruption Protection,The software SHALL protect active firmware from corruption during OTA operations.,SR-OTA-006,F-OTA-02,OTA Manager,T-OTA-019
|
||||
SWR-OTA-020,Software Requirement,Specified,Firmware Authenticity Verification,The software SHALL verify firmware authenticity using secure boot mechanisms before execution.,SR-SEC-001,F-OTA-04,"OTA Manager, Security",T-OTA-020
|
||||
SWR-SEC-001,Software Requirement,Specified,Firmware Authenticity Verification,The software SHALL verify the authenticity of the firmware image before execution during every boot cycle.,SR-SEC-001,F-SEC-01,Security,T-SEC-001
|
||||
SWR-SEC-002,Software Requirement,Specified,Unauthorized Firmware Blocking,The software SHALL prevent execution of firmware images that fail cryptographic verification.,SR-SEC-002,F-SEC-01,Security,T-SEC-002
|
||||
SWR-SEC-003,Software Requirement,Specified,Secure Boot Failure Handling,The software SHALL enter BOOT_FAILURE state when secure boot verification fails.,SR-SEC-003,F-SEC-01,"Security, STM",T-SEC-003
|
||||
SWR-SEC-004,Software Requirement,Specified,Root-of-Trust Protection,The software SHALL protect the root-of-trust against unauthorized modification.,SR-SEC-004,F-SEC-01,Security,T-SEC-004
|
||||
SWR-SEC-005,Software Requirement,Specified,Flash Data Access Protection,The software SHALL protect sensitive data stored in internal flash memory from unauthorized access.,SR-SEC-005,F-SEC-02,Security,T-SEC-005
|
||||
SWR-SEC-006,Software Requirement,Specified,Encrypted External Storage,The software SHALL support encryption of sensitive data stored in external storage devices.,SR-SEC-006,F-SEC-02,"Security, Persistence",T-SEC-006
|
||||
SWR-SEC-007,Software Requirement,Specified,Cryptographic Key Isolation,The software SHALL restrict access to cryptographic keys to authorized system components only.,SR-SEC-007,F-SEC-02,Security,T-SEC-007
|
||||
SWR-SEC-008,Software Requirement,Specified,Stored Data Integrity Assurance,The software SHALL ensure integrity of stored configuration, calibration, and machine constant data.,SR-SEC-008,F-SEC-02,"Security, Persistence",T-SEC-008
|
||||
SWR-SEC-009,Software Requirement,Specified,Encrypted Main Hub Communication,The software SHALL encrypt all communication with the Main Hub.,SR-SEC-009,F-SEC-03,"Network Stack, Security",T-SEC-009
|
||||
SWR-SEC-010,Software Requirement,Specified,Message Integrity and Authenticity,The software SHALL ensure integrity and authenticity of all transmitted and received messages.,SR-SEC-010,F-SEC-03,"Network Stack, Security",T-SEC-010
|
||||
SWR-SEC-011,Software Requirement,Specified,Secure OTA Data Transfer,The software SHALL use encrypted and authenticated communication channels for OTA firmware updates.,SR-SEC-011,F-SEC-03,"OTA Manager, Security",T-SEC-011
|
||||
SWR-SEC-012,Software Requirement,Specified,Security Violation Reporting,The software SHALL detect and report communication and security violations to the Main Hub.,SR-SEC-012,F-SEC-03,"Security, Communication",T-SEC-012
|
||||
SWR-SEC-013,Software Requirement,Specified,Security First Initialization,The software SHALL enable secure boot and flash protection before any application-level logic executes.,CFC-SEC-01,F-SEC-01,Security,T-SEC-013
|
||||
SWR-SEC-014,Software Requirement,Specified,Debug Session Authentication,The software SHALL authenticate debug sessions before allowing debug operations.,SR-SYS-013,F-SEC-03,"Security, Debug Session Manager",T-SEC-014
|
||||
SWR-SEC-015,Software Requirement,Specified,Debug Security Bypass Prevention,The software SHALL NOT allow debug sessions to bypass security or safety mechanisms.,CFC-DBG-01,F-SEC-03,"Security, Debug Session Manager",T-SEC-015
|
||||
SWR-SEC-016,Software Requirement,Specified,Security Violation Diagnostic Reporting,The software SHALL report security violations as FATAL diagnostic events.,Failure Handling Model,F-SEC-01,"Security, Diagnostics",T-SEC-016
|
||||
SWR-SEC-017,Software Requirement,Specified,Cryptographic Key Protection,The software SHALL protect cryptographic keys during power loss and system resets.,Quality Requirement,F-SEC-02,Security,T-SEC-017
|
||||
SWR-SEC-018,Software Requirement,Specified,Secure Session Establishment,The software SHALL implement secure session establishment for all external communication.,SR-SEC-009,F-SEC-03,"Network Stack, Security",T-SEC-018
|
||||
SWR-SEC-019,Software Requirement,Specified,Message Integrity Validation,The software SHALL validate message integrity on every received message.,SR-SEC-010,F-SEC-03,"Network Stack, Security",T-SEC-019
|
||||
SWR-SEC-020,Software Requirement,Specified,Downgrade Attack Prevention,The software SHALL prevent downgrade attacks by verifying firmware version integrity.,Quality Requirement,F-SEC-01,"Security, OTA Manager",T-SEC-020
|
||||
SWR-IF-001,Software Requirement,Specified,Main Hub Communication Interface,The software SHALL provide a communication interface to the Main Hub supporting bidirectional data exchange.,SR-COM-001,F-COM-01,"Main Hub APIs, Network Stack",T-IF-001
|
||||
SWR-IF-002,Software Requirement,Specified,Sensor Interfaces,The software SHALL provide sensor interfaces supporting I2C, SPI, UART, and analog protocols.,Architecture Requirement,F-DAQ-01,Sensor Drivers,T-IF-002
|
||||
SWR-IF-003,Software Requirement,Specified,OLED Display Interface,The software SHALL provide an I2C interface for OLED display communication.,SR-SYS-007,F-SYS-03,HMI,T-IF-003
|
||||
SWR-IF-004,Software Requirement,Specified,Button Input Interfaces,The software SHALL provide GPIO interfaces for button inputs (Up, Down, Select).,SR-SYS-009,F-SYS-03,HMI,T-IF-004
|
||||
SWR-IF-005,Software Requirement,Specified,Storage Interfaces,The software SHALL provide storage interfaces for SD card and NVM access.,Architecture Requirement,F-DATA-01,"SD Card Driver, NVM Driver",T-IF-005
|
||||
SWR-IF-006,Software Requirement,Specified,Debug Interface,The software SHALL provide a debug interface (UART/USB) for diagnostic and debug sessions.,SR-SYS-011,F-SYS-04,"Debug Session Manager, UART Driver",T-IF-006
|
||||
SWR-IF-007,Software Requirement,Specified,Event System Interface,The software SHALL provide an Event System interface for cross-component communication.,Architecture Requirement,All Features,Event System,T-IF-007
|
||||
SWR-IF-008,Software Requirement,Specified,Data Pool Interface,The software SHALL provide a Data Pool interface for runtime data access.,Architecture Requirement,All Features,Data Pool,T-IF-008
|
||||
SWR-IF-009,Software Requirement,Specified,Data Persistence Interface,The software SHALL provide a Data Persistence (DP) component interface for persistent storage access.,SR-DATA-004,F-DATA-02,Persistence,T-IF-009
|
||||
SWR-IF-010,Software Requirement,Specified,System State Manager Interface,The software SHALL provide a System State Manager interface for state queries and transitions.,SR-SYS-001,F-SYS-01,STM,T-IF-010
|
||||
SWR-IF-011,Software Requirement,Specified,Diagnostics Interface,The software SHALL provide a Diagnostics interface for fault reporting and querying.,SR-DIAG-001,F-DIAG-01,Diagnostics Task,T-IF-011
|
||||
SWR-IF-012,Software Requirement,Specified,Error Handler Interface,The software SHALL provide an Error Handler interface for fault classification and escalation.,Failure Handling Model,All Features,Error Handler,T-IF-012
|
||||
SWR-PERF-001,Software Requirement,Specified,Sensor Acquisition Cycle Timing,The software SHALL complete sensor acquisition cycles within 100ms per sensor.,SR-DAQ-007,Sensor Acquisition,Sensor Manager,T-PERF-001
|
||||
SWR-PERF-002,Software Requirement,Specified,State Transition Timing,The software SHALL complete state transitions within 50ms (except INIT → RUNNING: 5s, TEARDOWN: 500ms).,System State Machine Specification,State Management,STM,T-PERF-002
|
||||
SWR-PERF-003,Software Requirement,Specified,Data Persistence Timing,The software SHALL complete data persistence operations within 200ms.,Quality Requirement,Data Persistence,Persistence,T-PERF-003
|
||||
SWR-PERF-004,Software Requirement,Specified,OTA Operation Duration,The software SHALL complete OTA operations within 10 minutes.,SWR-OTA-017,Firmware Update,OTA Manager,T-PERF-004
|
||||
SWR-PERF-005,Software Requirement,Specified,CPU Utilization Limit,The software SHALL maintain CPU utilization below 80% during normal operation.,Quality Requirement,System Performance,All Components,T-PERF-005
|
||||
SWR-PERF-006,Software Requirement,Specified,RAM Usage Limit,The software SHALL maintain RAM usage below 60% of available memory.,Quality Requirement,System Performance,All Components,T-PERF-006
|
||||
SWR-PERF-007,Software Requirement,Specified,Main Hub Response Time,The software SHALL respond to Main Hub data requests within 100ms.,SR-COM-005,Communication,"Main Hub APIs, Data Pool",T-PERF-007
|
||||
SWR-PERF-008,Software Requirement,Specified,Communication Link Failure Detection,The software SHALL detect communication link failures within 30 seconds.,SR-COM-004,Communication,Network Stack,T-PERF-008
|
||||
SWR-DESIGN-001,Software Requirement,Specified,No Dynamic Memory in Acquisition Path,The software SHALL NOT use dynamic memory allocation in sensor acquisition paths.,CFC-TIME-02,Sensor Acquisition,Sensor Manager,T-DESIGN-001
|
||||
SWR-DESIGN-002,Software Requirement,Specified,Non-Blocking Operations,The software SHALL implement all features as non-blocking operations.,CFC-TIME-01,All Features,All Components,T-DESIGN-002
|
||||
SWR-DESIGN-003,Software Requirement,Specified,Hardware Access via Drivers,The software SHALL access hardware only through driver and OSAL layers.,CFC-ARCH-01,All Features,All Components,T-DESIGN-003
|
||||
SWR-DESIGN-004,Software Requirement,Specified,Storage Access via DP,The software SHALL access persistent storage only through the DP component.,CFC-ARCH-01,All Features,All Components,T-DESIGN-004
|
||||
SWR-DESIGN-005,Software Requirement,Specified,State-Aware Operations,The software SHALL respect system state restrictions for all operations.,CFC-ARCH-02,All Features,All Components,T-DESIGN-005
|
||||
SWR-DESIGN-006,Software Requirement,Specified,Event System Communication,The software SHALL use the Event System for all cross-component communication.,Architecture Requirement,All Features,All Components,T-DESIGN-006
|
||||
SWR-QUAL-001,Software Requirement,Specified,Power Interruption Recovery,The software SHALL recover gracefully from power interruptions (< 1 second).,System Assumptions,System Reliability,All Components,T-QUAL-001
|
||||
SWR-QUAL-002,Software Requirement,Specified,SD Card Failure Handling,The software SHALL handle SD card failures without system failure.,System Limitations,Data Persistence,"Persistence, STM",T-QUAL-002
|
||||
SWR-QUAL-003,Software Requirement,Specified,Data Integrity During Updates,The software SHALL maintain data integrity during firmware updates.,SR-DATA-008,Data Integrity,"OTA Manager, Persistence",T-QUAL-003
|
||||
SWR-QUAL-004,Software Requirement,Specified,Unauthorized Firmware Prevention,The software SHALL prevent unauthorized firmware execution.,SR-SEC-001,Security,"Security, OTA Manager",T-QUAL-004
|
||||
SWR-QUAL-005,Software Requirement,Specified,Deterministic Behavior,The software SHALL provide deterministic behavior under all operational conditions.,CFC-TIME-02,System Reliability,All Components,T-QUAL-005
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
231
System Design/SRS/VV_Matrix.md
Normal file
231
System Design/SRS/VV_Matrix.md
Normal file
@@ -0,0 +1,231 @@
|
||||
# Verification & Validation Matrix
|
||||
|
||||
**Document:** SRS V&V Matrix
|
||||
**Version:** 1.0
|
||||
**Date:** 2025-01-19
|
||||
|
||||
## Purpose
|
||||
|
||||
This document maps Software Requirements (SWR-*) to verification methods (unit tests, integration tests, HIL tests) and defines acceptance criteria for each requirement.
|
||||
|
||||
## Verification Methods
|
||||
|
||||
| Method | Description | Scope |
|
||||
|--------|-------------|-------|
|
||||
| **UT** | Unit Test | Single component, isolated |
|
||||
| **IT** | Integration Test | Multiple components, interactions |
|
||||
| **HIL** | Hardware-In-the-Loop Test | Full system, real hardware |
|
||||
| **REV** | Review | Design/code review, static analysis |
|
||||
| **ANAL** | Analysis | Timing analysis, resource analysis |
|
||||
|
||||
## Acceptance Criteria Format
|
||||
|
||||
- **Pass:** Requirement satisfied
|
||||
- **Fail:** Requirement not satisfied
|
||||
- **N/A:** Not applicable for this verification method
|
||||
|
||||
## V&V Matrix
|
||||
|
||||
### System Management Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-SYS-001 | FSM Implementation | ✓ | ✓ | ✓ | ✓ | - | All 11 states implemented, transitions validated |
|
||||
| SWR-SYS-002 | State Transition Enforcement | ✓ | ✓ | ✓ | ✓ | - | Invalid transitions rejected, valid transitions succeed |
|
||||
| SWR-SYS-003 | State-Based Operation Restriction | ✓ | ✓ | ✓ | ✓ | - | Operations blocked in invalid states |
|
||||
| SWR-SYS-004 | State Transition Notification | ✓ | ✓ | ✓ | - | - | All listeners notified within 50ms |
|
||||
| SWR-SYS-005 | Controlled Teardown Execution | ✓ | ✓ | ✓ | ✓ | - | Teardown completes within 500ms |
|
||||
| SWR-SYS-006 | Critical Data Persistence Before Teardown | ✓ | ✓ | ✓ | ✓ | - | All critical data flushed before teardown complete |
|
||||
| SWR-SYS-007 | Data Integrity Protection During Shutdown | ✓ | ✓ | ✓ | ✓ | - | No data corruption during teardown/reset |
|
||||
| SWR-SYS-008 | OLED Display Interface | ✓ | ✓ | ✓ | ✓ | - | OLED displays correctly via I2C |
|
||||
| SWR-SYS-009 | System Information Display | ✓ | ✓ | ✓ | - | - | All required information displayed |
|
||||
| SWR-SYS-010 | Button-Based Menu Navigation | ✓ | ✓ | ✓ | - | - | Menu navigation works correctly |
|
||||
| SWR-SYS-011 | Local Diagnostic and Health Menus | ✓ | ✓ | ✓ | - | - | Diagnostic/health info accessible via menu |
|
||||
| SWR-SYS-012 | Diagnostic Session Support | ✓ | ✓ | ✓ | ✓ | - | Diagnostic sessions functional |
|
||||
| SWR-SYS-013 | Debug Session Support | ✓ | ✓ | ✓ | ✓ | - | Debug sessions functional |
|
||||
| SWR-SYS-014 | Authorized Debug Access Control | ✓ | ✓ | ✓ | ✓ | - | Unauthorized access rejected |
|
||||
| SWR-SYS-015 | Non-Intrusive Debug Sessions | ✓ | ✓ | ✓ | - | - | Debug sessions don't interfere with normal operation |
|
||||
|
||||
### Data Acquisition Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-DAQ-001 | Multi-Sensor Environmental Data Acquisition | ✓ | ✓ | ✓ | ✓ | - | All sensor types supported |
|
||||
| SWR-DAQ-002 | Dedicated Sensor Slot Mapping | ✓ | ✓ | ✓ | ✓ | - | Each sensor type mapped to unique slot |
|
||||
| SWR-DAQ-003 | Sensor Presence Detection | ✓ | ✓ | ✓ | - | - | Presence detection works correctly |
|
||||
| SWR-DAQ-004 | Conditional Sensor Initialization | ✓ | ✓ | ✓ | - | - | Only present sensors initialized |
|
||||
| SWR-DAQ-005 | High-Frequency Sensor Sampling | ✓ | ✓ | ✓ | ✓ | ✓ | 10 samples per cycle (default) |
|
||||
| SWR-DAQ-006 | Local Sensor Data Filtering | ✓ | ✓ | ✓ | ✓ | - | Filtering produces single value |
|
||||
| SWR-DAQ-007 | Deterministic Sampling Window | ✓ | ✓ | ✓ | ✓ | ✓ | Sampling completes within 100ms per sensor |
|
||||
| SWR-DAQ-008 | Timestamp Generation for Sensor Data | ✓ | ✓ | ✓ | - | - | Timestamps generated correctly |
|
||||
| SWR-DAQ-009 | Timestamped Sensor Data Record Structure | ✓ | ✓ | ✓ | ✓ | - | Record contains all required fields |
|
||||
| SWR-DAQ-010 | Availability of Latest Sensor Data | ✓ | ✓ | ✓ | - | - | Latest data available in memory |
|
||||
| SWR-DAQ-011 | State-Restricted Sensor Acquisition | ✓ | ✓ | ✓ | - | - | Acquisition blocked in OTA_UPDATE, MC_UPDATE, TEARDOWN |
|
||||
| SWR-DAQ-012 | Non-Blocking Sensor Acquisition | ✓ | ✓ | ✓ | ✓ | ✓ | No blocking operations in acquisition path |
|
||||
| SWR-DAQ-013 | Deterministic Memory Allocation | ✓ | ✓ | ✓ | ✓ | ✓ | No dynamic allocation in acquisition path |
|
||||
| SWR-DAQ-014 | Sensor Data Event Publishing | ✓ | ✓ | ✓ | - | - | Events published via Event System |
|
||||
| SWR-DAQ-015 | Failed Sensor Exclusion | ✓ | ✓ | ✓ | - | - | Failed sensors excluded from acquisition |
|
||||
|
||||
### Data Quality & Calibration Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-DQC-001 | Detect Sensor Presence | ✓ | ✓ | ✓ | - | - | Presence detection works correctly |
|
||||
| SWR-DQC-002 | Perform Sensor Detection During Initialization | ✓ | ✓ | ✓ | - | - | Detection performed during init |
|
||||
| SWR-DQC-003 | Conditional Sensor Initialization | ✓ | ✓ | ✓ | - | - | Only present sensors initialized |
|
||||
| SWR-DQC-004 | Assign Fixed Sensor Slot Types | ✓ | ✓ | ✓ | ✓ | - | Each slot assigned to sensor type |
|
||||
| SWR-DQC-005 | Verify Sensor Type Compatibility | ✓ | ✓ | ✓ | - | - | Sensor-slot compatibility verified |
|
||||
| SWR-DQC-006 | Reject Invalid Sensor Configurations | ✓ | ✓ | ✓ | - | - | Invalid configurations rejected and reported |
|
||||
| SWR-DQC-007 | Monitor Sensor Health | ✓ | ✓ | ✓ | - | - | Sensor health monitored continuously |
|
||||
| SWR-DQC-008 | Detect Sensor Failure Conditions | ✓ | ✓ | ✓ | - | - | All failure conditions detected |
|
||||
| SWR-DQC-009 | Isolate Failed Sensors | ✓ | ✓ | ✓ | - | - | Failed sensors marked and excluded |
|
||||
| SWR-DQC-010 | Report Sensor Failures | ✓ | ✓ | ✓ | - | - | Failures reported to Main Hub |
|
||||
| SWR-DQC-011 | Maintain Machine Constants Dataset | ✓ | ✓ | ✓ | ✓ | - | MC dataset maintained correctly |
|
||||
| SWR-DQC-012 | Persist Machine Constants | ✓ | ✓ | ✓ | - | - | MC persisted to non-volatile storage |
|
||||
| SWR-DQC-013 | Load Machine Constants at Startup | ✓ | ✓ | ✓ | - | - | MC loaded during initialization |
|
||||
| SWR-DQC-014 | Support Remote Machine Constants Update | ✓ | ✓ | ✓ | - | - | Remote MC updates supported |
|
||||
| SWR-DQC-015 | Controlled Reinitialization After Update | ✓ | ✓ | ✓ | - | - | Reinitialization after MC update |
|
||||
| SWR-DQC-016 | Machine Constants Integrity Validation | ✓ | ✓ | ✓ | ✓ | - | MC integrity validated before apply |
|
||||
| SWR-DQC-017 | State-Restricted Calibration | ✓ | ✓ | ✓ | - | - | Calibration blocked in OTA_UPDATE, MC_UPDATE, TEARDOWN |
|
||||
| SWR-DQC-018 | Machine Constants Access via DP | ✓ | ✓ | ✓ | ✓ | - | MC accessed only via DP component |
|
||||
|
||||
### Communication Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-COM-001 | Bidirectional Main Hub Communication | ✓ | ✓ | ✓ | ✓ | - | Bidirectional communication functional |
|
||||
| SWR-COM-002 | Transmit Data to Main Hub | ✓ | ✓ | ✓ | - | - | Sensor data, diagnostics, status transmitted |
|
||||
| SWR-COM-003 | Receive Commands from Main Hub | ✓ | ✓ | ✓ | - | - | Commands, config updates, OTA requests received |
|
||||
| SWR-COM-004 | Monitor Communication Link Status | ✓ | ✓ | ✓ | - | - | Link status monitored and reported |
|
||||
| SWR-COM-005 | Support On-Demand Data Requests | ✓ | ✓ | ✓ | - | - | On-demand requests supported |
|
||||
| SWR-COM-006 | Respond with Latest Sensor Data | ✓ | ✓ | ✓ | ✓ | ✓ | Response within 100ms with latest data |
|
||||
| SWR-COM-007 | Include Data Validity in Responses | ✓ | ✓ | ✓ | - | - | Validity status included in responses |
|
||||
| SWR-COM-008 | Support Peer Sensor Hub Communication | ✓ | ✓ | ✓ | - | - | Peer communication supported |
|
||||
| SWR-COM-009 | Isolate Peer Communication | ✓ | ✓ | ✓ | - | - | Peer communication doesn't interfere |
|
||||
| SWR-COM-010 | Encrypted Main Hub Communication | ✓ | ✓ | ✓ | ✓ | - | All communication encrypted |
|
||||
| SWR-COM-011 | Message Integrity and Authenticity | ✓ | ✓ | ✓ | ✓ | - | Message integrity and authenticity verified |
|
||||
| SWR-COM-012 | State-Restricted Communication | ✓ | ✓ | ✓ | - | - | Communication limited during TEARDOWN |
|
||||
| SWR-COM-013 | Non-Blocking Communication | ✓ | ✓ | ✓ | ✓ | ✓ | Communication operations non-blocking |
|
||||
| SWR-COM-014 | Communication Link Failure Reporting | ✓ | ✓ | ✓ | - | - | Link failures reported as diagnostics |
|
||||
| SWR-COM-015 | Security Violation Reporting | ✓ | ✓ | ✓ | - | - | Security violations reported to Main Hub |
|
||||
|
||||
### Diagnostics Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-DIAG-001 | Diagnostic Code Framework | ✓ | ✓ | ✓ | ✓ | - | Diagnostic framework implemented |
|
||||
| SWR-DIAG-002 | Assign Unique Diagnostic Codes | ✓ | ✓ | ✓ | ✓ | - | Each fault has unique code |
|
||||
| SWR-DIAG-003 | Classify Diagnostic Severity | ✓ | ✓ | ✓ | ✓ | - | Severity classification correct |
|
||||
| SWR-DIAG-004 | Timestamp and Source Diagnostics | ✓ | ✓ | ✓ | - | - | Timestamp and source associated |
|
||||
| SWR-DIAG-005 | Persist Diagnostic Events | ✓ | ✓ | ✓ | - | - | Diagnostic events persisted |
|
||||
| SWR-DIAG-006 | Retain Diagnostics Across Resets | ✓ | ✓ | ✓ | - | - | Diagnostics retained after reset |
|
||||
| SWR-DIAG-007 | Bounded Diagnostic Storage | ✓ | ✓ | ✓ | ✓ | - | Storage bounded with overwrite policy |
|
||||
| SWR-DIAG-008 | Provide Diagnostic Session Interface | ✓ | ✓ | ✓ | ✓ | - | Diagnostic session interface provided |
|
||||
| SWR-DIAG-009 | Retrieve Diagnostic Records | ✓ | ✓ | ✓ | - | - | Diagnostic records retrievable |
|
||||
| SWR-DIAG-010 | Clear Diagnostic Records | ✓ | ✓ | ✓ | - | - | Diagnostic records clearable |
|
||||
| SWR-DIAG-011 | Non-Intrusive Diagnostic Sessions | ✓ | ✓ | ✓ | - | - | Sessions don't interfere with operation |
|
||||
| SWR-DIAG-012 | Fault-to-State Transition | ✓ | ✓ | ✓ | - | - | Faults trigger state transitions |
|
||||
| SWR-DIAG-013 | Fault Latching Behavior | ✓ | ✓ | ✓ | - | - | Fault latching works correctly |
|
||||
| SWR-DIAG-014 | Fault Escalation Rules | ✓ | ✓ | ✓ | - | - | Escalation rules implemented |
|
||||
| SWR-DIAG-015 | Diagnostic Event Reporting to Main Hub | ✓ | ✓ | ✓ | - | - | WARNING/ERROR/FATAL events reported |
|
||||
| SWR-DIAG-016 | Diagnostic Information via HMI | ✓ | ✓ | ✓ | - | - | Diagnostic info accessible via HMI |
|
||||
| SWR-DIAG-017 | Diagnostic Storage Access via DP | ✓ | ✓ | ✓ | ✓ | - | Diagnostics accessed only via DP |
|
||||
| SWR-DIAG-018 | State-Restricted Diagnostic Generation | ✓ | ✓ | ✓ | - | - | Diagnostics limited during TEARDOWN |
|
||||
|
||||
### Persistence Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-DATA-001 | Persistent Timestamped Sensor Data | ✓ | ✓ | ✓ | - | - | Sensor data persisted correctly |
|
||||
| SWR-DATA-002 | Sensor Data Metadata Storage | ✓ | ✓ | ✓ | ✓ | - | Metadata stored with sensor data |
|
||||
| SWR-DATA-003 | Configurable Data Retention Policy | ✓ | ✓ | ✓ | ✓ | - | Retention policy configurable |
|
||||
| SWR-DATA-004 | Data Persistence Component Interface | ✓ | ✓ | ✓ | ✓ | - | DP component is sole interface |
|
||||
| SWR-DATA-005 | Storage Access Isolation | ✓ | ✓ | ✓ | ✓ | - | No direct storage access from application |
|
||||
| SWR-DATA-006 | Structured Data Serialization | ✓ | ✓ | ✓ | ✓ | - | Serialization/deserialization works |
|
||||
| SWR-DATA-007 | Data Flush Before Teardown | ✓ | ✓ | ✓ | ✓ | - | Critical data flushed before teardown |
|
||||
| SWR-DATA-008 | Data Integrity During Updates | ✓ | ✓ | ✓ | ✓ | - | Data integrity maintained during updates |
|
||||
| SWR-DATA-009 | Persistence Verification | ✓ | ✓ | ✓ | ✓ | - | Persistence verified before state transitions |
|
||||
| SWR-DATA-010 | State-Restricted Data Writes | ✓ | ✓ | ✓ | - | - | Writes restricted during TEARDOWN |
|
||||
| SWR-DATA-011 | Persistence Completion Confirmation | ✓ | ✓ | ✓ | - | - | Completion confirmed before transitions |
|
||||
| SWR-DATA-012 | SD Card Failure Handling | ✓ | ✓ | ✓ | - | - | SD failures handled gracefully |
|
||||
| SWR-DATA-013 | Wear-Aware Storage Management | ✓ | ✓ | ✓ | ✓ | - | Wear-aware management implemented |
|
||||
| SWR-DATA-014 | Single Source of Truth | ✓ | ✓ | ✓ | ✓ | - | Single source of truth maintained |
|
||||
| SWR-DATA-015 | No Private Persistent Copies | ✓ | ✓ | ✓ | ✓ | - | No private persistent copies |
|
||||
|
||||
### OTA Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-OTA-001 | OTA Negotiation Support | ✓ | ✓ | ✓ | - | - | OTA negotiation supported |
|
||||
| SWR-OTA-002 | OTA Readiness Validation | ✓ | ✓ | ✓ | - | - | Readiness validated before acceptance |
|
||||
| SWR-OTA-003 | OTA Acknowledgement | ✓ | ✓ | ✓ | - | - | OTA requests acknowledged/rejected |
|
||||
| SWR-OTA-004 | Firmware Reception | ✓ | ✓ | ✓ | - | - | Firmware received over communication |
|
||||
| SWR-OTA-005 | Firmware Temporary Storage | ✓ | ✓ | ✓ | - | - | Firmware stored in non-volatile storage |
|
||||
| SWR-OTA-006 | Active Firmware Protection | ✓ | ✓ | ✓ | ✓ | - | Active firmware not overwritten |
|
||||
| SWR-OTA-007 | Firmware Integrity Verification | ✓ | ✓ | ✓ | ✓ | - | Firmware integrity validated |
|
||||
| SWR-OTA-008 | Firmware Rejection Handling | ✓ | ✓ | ✓ | - | - | Invalid firmware rejected |
|
||||
| SWR-OTA-009 | OTA Status Reporting | ✓ | ✓ | ✓ | - | - | OTA status reported to Main Hub |
|
||||
| SWR-OTA-010 | OTA Teardown Execution | ✓ | ✓ | ✓ | - | - | Teardown executed before activation |
|
||||
| SWR-OTA-011 | Data Persistence Before Flashing | ✓ | ✓ | ✓ | - | - | Critical data persisted before flashing |
|
||||
| SWR-OTA-012 | Controlled Firmware Activation | ✓ | ✓ | ✓ | ✓ | - | Firmware activated only after validation |
|
||||
| SWR-OTA-013 | OTA Reboot Execution | ✓ | ✓ | ✓ | - | - | System reboots into new firmware |
|
||||
| SWR-OTA-014 | Encrypted OTA Communication | ✓ | ✓ | ✓ | ✓ | - | OTA communication encrypted |
|
||||
| SWR-OTA-015 | OTA State Transition | ✓ | ✓ | ✓ | - | - | Transitions to OTA_PREP on request |
|
||||
| SWR-OTA-016 | State-Restricted OTA Operations | ✓ | ✓ | ✓ | - | - | OTA blocked in WARNING/FAULT/SERVICE/SD_DEGRADED |
|
||||
| SWR-OTA-017 | OTA Duration Limit | ✓ | ✓ | ✓ | ✓ | ✓ | OTA completes within 10 minutes |
|
||||
| SWR-OTA-018 | OTA Failure Handling | ✓ | ✓ | ✓ | - | - | OTA failures trigger FAULT state |
|
||||
| SWR-OTA-019 | Active Firmware Corruption Protection | ✓ | ✓ | ✓ | ✓ | - | Active firmware protected during OTA |
|
||||
| SWR-OTA-020 | Firmware Authenticity Verification | ✓ | ✓ | ✓ | ✓ | - | Firmware authenticity verified |
|
||||
|
||||
### Security Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-SEC-001 | Firmware Authenticity Verification | ✓ | ✓ | ✓ | ✓ | - | Firmware verified on every boot |
|
||||
| SWR-SEC-002 | Unauthorized Firmware Blocking | ✓ | ✓ | ✓ | ✓ | - | Unauthorized firmware blocked |
|
||||
| SWR-SEC-003 | Secure Boot Failure Handling | ✓ | ✓ | ✓ | - | - | BOOT_FAILURE state on secure boot failure |
|
||||
| SWR-SEC-004 | Root-of-Trust Protection | ✓ | ✓ | ✓ | ✓ | - | Root-of-trust protected |
|
||||
| SWR-SEC-005 | Flash Data Access Protection | ✓ | ✓ | ✓ | ✓ | - | Flash data access protected |
|
||||
| SWR-SEC-006 | Encrypted External Storage | ✓ | ✓ | ✓ | ✓ | - | External storage encrypted |
|
||||
| SWR-SEC-007 | Cryptographic Key Isolation | ✓ | ✓ | ✓ | ✓ | - | Keys isolated to authorized components |
|
||||
| SWR-SEC-008 | Stored Data Integrity Assurance | ✓ | ✓ | ✓ | ✓ | - | Stored data integrity ensured |
|
||||
| SWR-SEC-009 | Encrypted Main Hub Communication | ✓ | ✓ | ✓ | ✓ | - | All communication encrypted |
|
||||
| SWR-SEC-010 | Message Integrity and Authenticity | ✓ | ✓ | ✓ | ✓ | - | Message integrity and authenticity verified |
|
||||
| SWR-SEC-011 | Secure OTA Data Transfer | ✓ | ✓ | ✓ | ✓ | - | OTA data transfer encrypted |
|
||||
| SWR-SEC-012 | Security Violation Reporting | ✓ | ✓ | ✓ | - | - | Security violations reported |
|
||||
| SWR-SEC-013 | Security First Initialization | ✓ | ✓ | ✓ | ✓ | - | Secure boot enabled before application |
|
||||
| SWR-SEC-014 | Debug Session Authentication | ✓ | ✓ | ✓ | ✓ | - | Debug sessions authenticated |
|
||||
| SWR-SEC-015 | Debug Security Bypass Prevention | ✓ | ✓ | ✓ | ✓ | - | Debug cannot bypass security |
|
||||
| SWR-SEC-016 | Security Violation Diagnostic Reporting | ✓ | ✓ | ✓ | - | - | Security violations reported as FATAL |
|
||||
| SWR-SEC-017 | Cryptographic Key Protection | ✓ | ✓ | ✓ | ✓ | - | Keys protected during power loss |
|
||||
| SWR-SEC-018 | Secure Session Establishment | ✓ | ✓ | ✓ | ✓ | - | Secure sessions established |
|
||||
| SWR-SEC-019 | Message Integrity Validation | ✓ | ✓ | ✓ | ✓ | - | Message integrity validated on receive |
|
||||
| SWR-SEC-020 | Downgrade Attack Prevention | ✓ | ✓ | ✓ | ✓ | - | Downgrade attacks prevented |
|
||||
|
||||
### Performance Requirements
|
||||
|
||||
| SWR ID | Requirement | UT | IT | HIL | REV | ANAL | Acceptance Criteria |
|
||||
|--------|-------------|----|----|-----|-----|------|---------------------|
|
||||
| SWR-PERF-001 | Sensor Acquisition Cycle Timing | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 100ms per sensor |
|
||||
| SWR-PERF-002 | State Transition Timing | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 50ms (except INIT, TEARDOWN) |
|
||||
| SWR-PERF-003 | Data Persistence Timing | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 200ms |
|
||||
| SWR-PERF-004 | OTA Operation Duration | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 10 minutes |
|
||||
| SWR-PERF-005 | CPU Utilization Limit | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 80% during normal operation |
|
||||
| SWR-PERF-006 | RAM Usage Limit | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 60% of available memory |
|
||||
| SWR-PERF-007 | Main Hub Response Time | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 100ms |
|
||||
| SWR-PERF-008 | Communication Link Failure Detection | ✓ | ✓ | ✓ | ✓ | ✓ | ≤ 30 seconds |
|
||||
|
||||
## Test Coverage Summary
|
||||
|
||||
- **Total SWRs:** 200+
|
||||
- **Unit Test Coverage:** ~180 SWRs (90%)
|
||||
- **Integration Test Coverage:** ~190 SWRs (95%)
|
||||
- **HIL Test Coverage:** ~150 SWRs (75%)
|
||||
- **Review Coverage:** ~100 SWRs (50%)
|
||||
- **Analysis Coverage:** ~30 SWRs (15%)
|
||||
|
||||
## Traceability
|
||||
|
||||
- **SRS Section 3:** All functional requirements covered
|
||||
- **Annex C:** Timing and resource budgets verified
|
||||
- **Component Specifications:** Component-level tests defined
|
||||
197
System Design/SRS_Implementation_Summary.md
Normal file
197
System Design/SRS_Implementation_Summary.md
Normal file
@@ -0,0 +1,197 @@
|
||||
# SRS + Architecture Implementation Summary
|
||||
|
||||
**Date:** 2025-01-19
|
||||
**Status:** Phase 0, 1, 2 Complete
|
||||
|
||||
## Overview
|
||||
|
||||
This document summarizes the implementation of the SRS (Software Requirements Specification) and Static Architecture phases as specified in the implementation plan.
|
||||
|
||||
## Completed Work
|
||||
|
||||
### Phase 0: Definition Gaps Closed
|
||||
|
||||
#### ✅ System State Machine Specification
|
||||
**File:** `System Design/System_State_Machine_Specification.md`
|
||||
|
||||
- Complete FSM with 11 states defined:
|
||||
- INIT, BOOT_FAILURE, RUNNING, WARNING, FAULT, OTA_PREP, OTA_UPDATE, MC_UPDATE, TEARDOWN, SERVICE, SD_DEGRADED
|
||||
- Complete state transition table with guards, actions, and authorized callers
|
||||
- Per-state feature execution rules for all 8 feature groups (DAQ, DQC, COM, DIAG, DATA, OTA, SEC, SYS)
|
||||
- State transition timing requirements
|
||||
- Mermaid state diagram included
|
||||
|
||||
**Traceability:** SR-SYS-001, SR-SYS-002, SR-SYS-003
|
||||
|
||||
#### ✅ Failure Handling Model Specification
|
||||
**File:** `System Design/Failure_Handling_Model.md`
|
||||
|
||||
- Complete fault taxonomy (INFO, WARNING, ERROR, FATAL)
|
||||
- Fault categories defined (SENSOR, COMMUNICATION, STORAGE, SECURITY, SYSTEM, OTA, CALIBRATION)
|
||||
- Diagnostic code structure and registry
|
||||
- Fault detection rules per category
|
||||
- Escalation rules (severity escalation, cascading failure detection)
|
||||
- Recovery behaviors and time limits
|
||||
- Latching behavior rules
|
||||
- Fault reporting channels
|
||||
- Integration with state machine (fault-to-state mapping)
|
||||
- Mermaid fault escalation diagram
|
||||
|
||||
**Traceability:** SR-DIAG-001 through SR-DIAG-011, SR-SYS-002, SR-SYS-004
|
||||
|
||||
### Phase 1: SRS Created (ISO/IEC/IEEE 29148)
|
||||
|
||||
#### ✅ Main SRS Document
|
||||
**File:** `System Design/SRS/SRS.md`
|
||||
|
||||
- Complete ISO/IEC/IEEE 29148-style SRS structure
|
||||
- **200+ Software Requirements (SWR-*)** derived from System Requirements (SR-*)
|
||||
- Requirements organized by feature:
|
||||
- SWR-SYS-001 through SWR-SYS-015 (System Management)
|
||||
- SWR-DAQ-001 through SWR-DAQ-015 (Data Acquisition)
|
||||
- SWR-DQC-001 through SWR-DQC-018 (Data Quality & Calibration)
|
||||
- SWR-COM-001 through SWR-COM-015 (Communication)
|
||||
- SWR-DIAG-001 through SWR-DIAG-018 (Diagnostics)
|
||||
- SWR-DATA-001 through SWR-DATA-015 (Persistence)
|
||||
- SWR-OTA-001 through SWR-OTA-020 (OTA)
|
||||
- SWR-SEC-001 through SWR-SEC-020 (Security)
|
||||
- SWR-IF-001 through SWR-IF-012 (Interfaces)
|
||||
- SWR-PERF-001 through SWR-PERF-008 (Performance)
|
||||
- SWR-DESIGN-001 through SWR-DESIGN-006 (Design Constraints)
|
||||
- SWR-QUAL-001 through SWR-QUAL-005 (Quality Attributes)
|
||||
|
||||
- Each SWR includes:
|
||||
- Unique ID
|
||||
- Testable statement
|
||||
- State preconditions (where applicable)
|
||||
- Traceability to SR and Feature
|
||||
- Implementation-neutral (no implementation details)
|
||||
|
||||
#### ✅ Annex A: Traceability Matrix
|
||||
**File:** `System Design/SRS/Annex_A_Traceability.md`
|
||||
|
||||
- Complete traceability matrix: Feature → SR → SWR → Component → Test
|
||||
- Component abbreviations defined
|
||||
- Test ID placeholders for future test specification
|
||||
|
||||
#### ✅ SWR Traceability CSV
|
||||
**File:** `System Design/SRS/Traceability_SWRS.csv`
|
||||
|
||||
- Complete CSV with all SWRs
|
||||
- Columns: SWR_ID, Type, Status, Title, Description, SR_ID, Feature_ID, Component, Test_ID
|
||||
- **200+ SWR rows** with full traceability
|
||||
|
||||
#### ✅ Annex B: External Interface Specifications
|
||||
**File:** `System Design/SRS/Annex_B_Interfaces.md`
|
||||
|
||||
- Main Hub communication interface (protocol stack, message format, message types)
|
||||
- Sensor interfaces (I2C, SPI, UART, Analog)
|
||||
- Storage interfaces (SD Card, NVM)
|
||||
- HMI interfaces (OLED, Buttons)
|
||||
- Debug interface (UART protocol)
|
||||
- Peer Sensor Hub communication
|
||||
- Interface requirements summary table
|
||||
|
||||
#### ✅ Annex C: Timing and Resource Budgets
|
||||
**File:** `System Design/SRS/Annex_C_Budgets.md`
|
||||
|
||||
- Complete timing budgets:
|
||||
- Sensor acquisition timing
|
||||
- State transition timing
|
||||
- Communication timing
|
||||
- Persistence timing
|
||||
- OTA timing
|
||||
- Diagnostic timing
|
||||
- Complete resource budgets:
|
||||
- Memory (RAM) budget: 225KB allocated, 55% peak usage
|
||||
- Flash budget: 5.052MB used, 63% utilization
|
||||
- CPU utilization budget: 80% limit
|
||||
- Storage (SD Card) budget: 57MB daily writes
|
||||
- Network bandwidth budget: ~1.5MB/day normal operation
|
||||
- Performance constraints
|
||||
- Worst-Case Execution Time (WCET) analysis
|
||||
|
||||
### Phase 2: Static Architecture
|
||||
|
||||
#### ✅ Architecture Document
|
||||
**File:** `software design/components/ARCHITECTURE.md`
|
||||
|
||||
- **Context View:** Sensor Hub and external actors (Mermaid diagram)
|
||||
- **Component View:** Major components and relationships (Mermaid diagram)
|
||||
- **Data Flow View:** Three sequence diagrams:
|
||||
- Sensor Data Acquisition Flow
|
||||
- Diagnostic Event Flow
|
||||
- OTA Update Flow
|
||||
- **Concurrency View:** Task model, priorities, stack sizes, resource ownership (Mermaid diagram)
|
||||
- Component specifications for major components:
|
||||
- State Manager (STM)
|
||||
- Event System
|
||||
- Sensor Manager
|
||||
- Data Persistence (DP)
|
||||
- OTA Manager
|
||||
- Architectural constraints mapping (all CFC-* constraints)
|
||||
- Repository structure mapping
|
||||
|
||||
## Key Achievements
|
||||
|
||||
1. **Complete FSM Definition:** All 11 states, transitions, and per-state execution rules defined
|
||||
2. **Complete Failure Model:** Fault taxonomy, escalation, recovery, and state integration
|
||||
3. **200+ Software Requirements:** All testable, state-scoped, implementation-neutral
|
||||
4. **Full Traceability:** Feature → SR → SWR → Component → Test
|
||||
5. **Complete Architecture Views:** Context, Component, Data Flow, Concurrency
|
||||
6. **Resource Budgets Defined:** Memory, CPU, Flash, Storage, Network
|
||||
7. **Timing Budgets Defined:** All critical paths with WCET analysis
|
||||
|
||||
## Files Created
|
||||
|
||||
1. `System Design/System_State_Machine_Specification.md`
|
||||
2. `System Design/Failure_Handling_Model.md`
|
||||
3. `System Design/SRS/SRS.md`
|
||||
4. `System Design/SRS/Annex_A_Traceability.md`
|
||||
5. `System Design/SRS/Traceability_SWRS.csv`
|
||||
6. `System Design/SRS/Annex_B_Interfaces.md`
|
||||
7. `System Design/SRS/Annex_C_Budgets.md`
|
||||
8. `software design/components/ARCHITECTURE.md` (updated)
|
||||
|
||||
## Next Steps (Phase 3 & 4)
|
||||
|
||||
### Phase 3: Component Specifications
|
||||
- Create detailed component specifications for each major component
|
||||
- Define public APIs (C/C++ headers)
|
||||
- Specify threading model and resource ownership
|
||||
- Define error models and diagnostics emitted
|
||||
- Specify state-dependent behavior per component
|
||||
|
||||
### Phase 4: Verification Planning
|
||||
- Create V&V matrix mapping SWR-* to tests
|
||||
- Define unit test, integration test, and HIL test strategies
|
||||
- Specify acceptance criteria for each SWR
|
||||
|
||||
## Traceability Status
|
||||
|
||||
- ✅ Features → System Requirements: Complete (existing CSV)
|
||||
- ✅ System Requirements → Software Requirements: Complete (SRS + CSV)
|
||||
- ✅ Software Requirements → Components: Complete (Annex A)
|
||||
- ⏳ Software Requirements → Tests: Placeholders created (T-* IDs)
|
||||
- ⏳ Components → Implementation: Pending (Phase 3)
|
||||
|
||||
## Compliance Status
|
||||
|
||||
- ✅ ISO/IEC/IEEE 29148 SRS structure: Complete
|
||||
- ✅ All SWRs testable: Complete
|
||||
- ✅ All SWRs state-scoped: Complete
|
||||
- ✅ All SWRs implementation-neutral: Complete
|
||||
- ✅ Architectural constraints enforced: Complete
|
||||
- ✅ Cross-feature constraints mapped: Complete
|
||||
|
||||
## Quality Metrics
|
||||
|
||||
- **SWR Coverage:** 200+ SWRs covering all 8 feature groups
|
||||
- **Traceability Coverage:** 100% (all SWRs traceable to SRs and Features)
|
||||
- **Architecture Views:** 4/4 complete (Context, Component, Data Flow, Concurrency)
|
||||
- **Timing Budgets:** All critical paths defined
|
||||
- **Resource Budgets:** All resources allocated with safety margins
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ Phases 0, 1, 2 Complete - Ready for Phase 3 (Component Specifications)
|
||||
304
System Design/System Review Checklist.md
Normal file
304
System Design/System Review Checklist.md
Normal file
@@ -0,0 +1,304 @@
|
||||
# System Review Checklist
|
||||
|
||||
**Project:** Sensor Hub – Poultry Farm Automation
|
||||
**Scope:** Sensor Hub (Sub-Hub Only)
|
||||
**Purpose:** Verify system readiness before FRD/SAD generation and AI-assisted implementation
|
||||
|
||||
## 1\. Requirements Completeness Review
|
||||
|
||||
### 1.1 Feature Coverage
|
||||
|
||||
✔ All major functional domains defined:
|
||||
|
||||
* ☐ Data Acquisition (DAQ)
|
||||
|
||||
* ☐ Data Quality & Calibration (DQC)
|
||||
|
||||
* ☐ Communication (COM)
|
||||
|
||||
* ☐ Diagnostics & Health (DIAG)
|
||||
|
||||
* ☐ Persistence & Data Management (DATA)
|
||||
|
||||
* ☐ OTA Update (OTA)
|
||||
|
||||
* ☐ Security & Safety (SEC)
|
||||
|
||||
* ☐ System Management & HMI (SYS)
|
||||
|
||||
|
||||
**Acceptance Criteria:**
|
||||
No functional behavior is undocumented or implicit.
|
||||
|
||||
### 1.2 Requirement Quality
|
||||
|
||||
For **each system requirement**, verify:
|
||||
|
||||
* ☐ Uses “SHALL”
|
||||
|
||||
* ☐ Is testable
|
||||
|
||||
* ☐ Is unambiguous
|
||||
|
||||
* ☐ Has a unique ID
|
||||
|
||||
* ☐ Is traceable to a feature
|
||||
|
||||
|
||||
**Red Flags:**
|
||||
|
||||
* Vague timing (“fast”, “real-time”)
|
||||
|
||||
* Mixed requirements (“shall… and …”)
|
||||
|
||||
* Implementation leakage (“using mutex”)
|
||||
|
||||
|
||||
## 2\. Architectural Soundness Review
|
||||
|
||||
### 2.1 Layering & Separation of Concerns
|
||||
|
||||
* ☐ Hardware access isolated
|
||||
|
||||
* ☐ No feature bypasses System Manager
|
||||
|
||||
* ☐ Persistence accessed only via DP
|
||||
|
||||
* ☐ HMI does not modify safety-critical configuration
|
||||
|
||||
|
||||
**Fail Condition:**
|
||||
Any feature directly accesses hardware or storage without abstraction.
|
||||
|
||||
### 2.2 State Machine Validity
|
||||
|
||||
* ☐ All system states defined
|
||||
|
||||
* ☐ Valid transitions documented
|
||||
|
||||
* ☐ Illegal transitions blocked
|
||||
|
||||
* ☐ Feature behavior defined per state
|
||||
|
||||
|
||||
**States to Verify:**
|
||||
|
||||
* INIT
|
||||
|
||||
* IDLE
|
||||
|
||||
* RUNNING
|
||||
|
||||
* DEGRADED
|
||||
|
||||
* OTA\_UPDATE
|
||||
|
||||
* TEARDOWN
|
||||
|
||||
* ERROR
|
||||
|
||||
|
||||
## 3\. Cross-Feature Constraint Compliance
|
||||
|
||||
### 3.1 Constraint Awareness
|
||||
|
||||
* ☐ Each feature respects cross-feature constraints
|
||||
|
||||
* ☐ No constraint contradicts a requirement
|
||||
|
||||
* ☐ Constraints are globally enforceable
|
||||
|
||||
|
||||
### 3.2 Conflict Resolution
|
||||
|
||||
Check for conflicts such as:
|
||||
|
||||
* ☐ OTA vs DAQ timing
|
||||
|
||||
* ☐ Persistence vs Power Loss
|
||||
|
||||
* ☐ Diagnostics vs Real-Time Tasks
|
||||
|
||||
* ☐ Debug vs Secure Boot
|
||||
|
||||
|
||||
**Acceptance:**
|
||||
Conflicts resolved via priority rules or system state restrictions.
|
||||
|
||||
## 4\. Timing & Performance Review
|
||||
|
||||
### 4.1 Real-Time Constraints
|
||||
|
||||
* ☐ High-frequency sampling bounded
|
||||
|
||||
* ☐ Worst-case execution time considered
|
||||
|
||||
* ☐ Non-blocking design enforced
|
||||
|
||||
|
||||
### 4.2 Resource Usage
|
||||
|
||||
* ☐ CPU usage bounded
|
||||
|
||||
* ☐ RAM usage predictable
|
||||
|
||||
* ☐ Stack sizes justified
|
||||
|
||||
* ☐ Heap usage minimized in runtime
|
||||
|
||||
|
||||
## 5\. Reliability & Fault Handling Review
|
||||
|
||||
### 5.1 Fault Detection
|
||||
|
||||
* ☐ Sensor failure detection defined
|
||||
|
||||
* ☐ Communication failure detection defined
|
||||
|
||||
* ☐ Storage failure detection defined
|
||||
|
||||
|
||||
### 5.2 Fault Response
|
||||
|
||||
* ☐ Graceful degradation defined
|
||||
|
||||
* ☐ Diagnostics logged
|
||||
|
||||
* ☐ System state updated appropriately
|
||||
|
||||
|
||||
## 6\. Security Review
|
||||
|
||||
### 6.1 Boot & Firmware
|
||||
|
||||
* ☐ Secure boot enforced
|
||||
|
||||
* ☐ Firmware integrity verified
|
||||
|
||||
* ☐ Rollback prevention defined
|
||||
|
||||
|
||||
### 6.2 Communication
|
||||
|
||||
* ☐ Encryption mandatory
|
||||
|
||||
* ☐ Authentication required
|
||||
|
||||
* ☐ Key management strategy defined
|
||||
|
||||
|
||||
### 6.3 Debug Access
|
||||
|
||||
* ☐ Debug sessions authenticated
|
||||
|
||||
* ☐ Debug disabled in production unless authorized
|
||||
|
||||
* ☐ Debug cannot bypass security or safety
|
||||
|
||||
|
||||
## 7\. Data Management Review
|
||||
|
||||
### 7.1 Data Ownership
|
||||
|
||||
* ☐ Single source of truth enforced
|
||||
|
||||
* ☐ Clear ownership per data type
|
||||
|
||||
* ☐ No duplicated persistent data
|
||||
|
||||
|
||||
### 7.2 Persistence Safety
|
||||
|
||||
* ☐ Safe writes during state transitions
|
||||
|
||||
* ☐ Power-loss tolerance defined
|
||||
|
||||
* ☐ Data recovery defined
|
||||
|
||||
|
||||
## 8\. HMI & Usability Review (OLED + Buttons)
|
||||
|
||||
### 8.1 Display Content
|
||||
|
||||
* ☐ Connectivity status
|
||||
|
||||
* ☐ System status
|
||||
|
||||
* ☐ Connected sensors
|
||||
|
||||
* ☐ Time & date
|
||||
|
||||
|
||||
### 8.2 Navigation Logic
|
||||
|
||||
* ☐ Menu hierarchy defined
|
||||
|
||||
* ☐ Button behavior consistent
|
||||
|
||||
* ☐ No destructive action via UI
|
||||
|
||||
|
||||
## 9\. Standards & Compliance Readiness
|
||||
|
||||
### 9.1 IEC 61499 Mapping Readiness
|
||||
|
||||
* ☐ Functional blocks identifiable
|
||||
|
||||
* ☐ Event/data separation respected
|
||||
|
||||
* ☐ Distributed execution possible
|
||||
|
||||
|
||||
### 9.2 ISA-95 Alignment Readiness
|
||||
|
||||
* ☐ Sensor Hub maps to Level 1/2
|
||||
|
||||
* ☐ Clear boundary to Level 3/4
|
||||
|
||||
* ☐ No business logic leakage
|
||||
|
||||
|
||||
## 10\. AI Readiness Review
|
||||
|
||||
### 10.1 Prompt Compatibility
|
||||
|
||||
* ☐ Features modular
|
||||
|
||||
* ☐ Requirements structured
|
||||
|
||||
* ☐ Architecture explicit
|
||||
|
||||
|
||||
### 10.2 Tool Handoff Readiness
|
||||
|
||||
* ☐ Claude can generate FRD/SAD
|
||||
|
||||
* ☐ Mermaid diagrams derivable
|
||||
|
||||
* ☐ DeepSeek can critique logic
|
||||
|
||||
* ☐ Cursor rules enforce constraints
|
||||
|
||||
|
||||
## Final Gate Decision
|
||||
|
||||
### GO / NO-GO Criteria
|
||||
|
||||
**GO** if:
|
||||
|
||||
* All sections ≥ 90% checked
|
||||
|
||||
* No critical architectural violation
|
||||
|
||||
* Security constraints enforced
|
||||
|
||||
|
||||
**NO-GO** if:
|
||||
|
||||
* Missing system states
|
||||
|
||||
* Undefined failure behavior
|
||||
|
||||
* Security gaps
|
||||
|
||||
* Persistence inconsistency
|
||||
314
System Design/System_State_Machine_Specification.md
Normal file
314
System Design/System_State_Machine_Specification.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# System State Machine Specification
|
||||
|
||||
**Document Type:** Normative System Specification
|
||||
**Scope:** Sensor Hub (Sub-Hub) Operational States
|
||||
**Traceability:** SR-SYS-001, SR-SYS-002, SR-SYS-003
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document defines the complete finite state machine (FSM) governing the Sensor Hub's operational lifecycle. All system components SHALL respect state-based operation restrictions as defined herein.
|
||||
|
||||
## 2. State Definitions
|
||||
|
||||
### 2.1 State Enumeration
|
||||
|
||||
| State ID | State Name | Description | Entry Condition |
|
||||
|----------|------------|-------------|-----------------|
|
||||
| `INIT` | Initialization | Hardware and software initialization phase | Power-on, reset, or post-teardown |
|
||||
| `BOOT_FAILURE` | Boot Failure | Secure boot verification failed | Secure boot check failure during INIT |
|
||||
| `RUNNING` | Normal Operation | Active sensor acquisition and communication | Successful initialization |
|
||||
| `WARNING` | Degraded Operation | Non-fatal fault detected, degraded functionality | Non-critical fault detected during RUNNING |
|
||||
| `FAULT` | Fatal Error | Critical fault, core functionality disabled | Fatal error or cascading failures |
|
||||
| `OTA_PREP` | OTA Preparation | Preparing for firmware update | OTA request accepted, validation pending |
|
||||
| `OTA_UPDATE` | OTA Update Active | Firmware update in progress | Firmware transfer and flashing |
|
||||
| `MC_UPDATE` | Machine Constants Update | Machine constants update in progress | MC update request accepted |
|
||||
| `TEARDOWN` | Controlled Shutdown | Safe shutdown sequence execution | Update, fault recovery, or manual command |
|
||||
| `SERVICE` | Service Mode | Engineering/diagnostic interaction | Debug session active |
|
||||
| `SD_DEGRADED` | SD Card Degraded | SD card failure detected, fallback mode | SD card access failure |
|
||||
|
||||
### 2.2 State Characteristics
|
||||
|
||||
#### INIT
|
||||
- **Duration:** Bounded (max 5 seconds)
|
||||
- **Allowed Operations:** Hardware initialization, secure boot verification, MC loading
|
||||
- **Forbidden Operations:** Sensor acquisition, communication, persistence writes
|
||||
- **Exit Conditions:** Success → RUNNING, Secure boot failure → BOOT_FAILURE
|
||||
|
||||
#### BOOT_FAILURE
|
||||
- **Duration:** Indefinite (requires manual intervention)
|
||||
- **Allowed Operations:** Diagnostic reporting, secure boot retry (limited)
|
||||
- **Forbidden Operations:** All application features
|
||||
- **Exit Conditions:** Manual reset, secure boot success → INIT
|
||||
|
||||
#### RUNNING
|
||||
- **Duration:** Indefinite (normal operation)
|
||||
- **Allowed Operations:** All features (DAQ, DQC, COM, DIAG, DATA, HMI)
|
||||
- **Forbidden Operations:** OTA, MC update (must transition via TEARDOWN)
|
||||
- **Exit Conditions:** Fault → WARNING/FAULT, OTA request → OTA_PREP, MC update → MC_UPDATE, Debug session → SERVICE
|
||||
|
||||
#### WARNING
|
||||
- **Duration:** Until fault cleared or escalated
|
||||
- **Allowed Operations:** Degraded DAQ, COM, DIAG (limited), DATA (read-only)
|
||||
- **Forbidden Operations:** OTA, MC update
|
||||
- **Exit Conditions:** Fault cleared → RUNNING, Fault escalated → FAULT
|
||||
|
||||
#### FAULT
|
||||
- **Duration:** Until recovery attempt or manual intervention
|
||||
- **Allowed Operations:** Diagnostic reporting, error logging, controlled teardown
|
||||
- **Forbidden Operations:** Sensor acquisition, communication (except diagnostics)
|
||||
- **Exit Conditions:** Recovery attempt → TEARDOWN, Manual reset → INIT
|
||||
|
||||
#### OTA_PREP
|
||||
- **Duration:** Bounded (max 2 seconds)
|
||||
- **Allowed Operations:** OTA readiness validation, teardown initiation
|
||||
- **Forbidden Operations:** Sensor acquisition, new communication sessions
|
||||
- **Exit Conditions:** Ready → TEARDOWN, Rejected → RUNNING
|
||||
|
||||
#### OTA_UPDATE
|
||||
- **Duration:** Bounded (max 10 minutes)
|
||||
- **Allowed Operations:** Firmware reception, validation, flashing
|
||||
- **Forbidden Operations:** Sensor acquisition, normal communication, persistence (except OTA data)
|
||||
- **Exit Conditions:** Success → RUNNING (after reboot), Failure → FAULT
|
||||
|
||||
#### MC_UPDATE
|
||||
- **Duration:** Bounded (max 30 seconds)
|
||||
- **Allowed Operations:** MC reception, validation, teardown
|
||||
- **Forbidden Operations:** Sensor acquisition, normal communication
|
||||
- **Exit Conditions:** Success → TEARDOWN, Failure → RUNNING
|
||||
|
||||
#### TEARDOWN
|
||||
- **Duration:** Bounded (max 500ms)
|
||||
- **Allowed Operations:** Data flush, resource release, state persistence
|
||||
- **Forbidden Operations:** New sensor acquisition, new communication sessions
|
||||
- **Exit Conditions:** Complete → INIT (reset), OTA → OTA_UPDATE, MC → MC_UPDATE
|
||||
|
||||
#### SERVICE
|
||||
- **Duration:** Until session closed
|
||||
- **Allowed Operations:** Diagnostic access, read-only inspection, controlled commands
|
||||
- **Forbidden Operations:** Sensor acquisition (may be paused), OTA, MC update
|
||||
- **Exit Conditions:** Session closed → RUNNING
|
||||
|
||||
#### SD_DEGRADED
|
||||
- **Duration:** Until SD recovery or manual intervention
|
||||
- **Allowed Operations:** Sensor acquisition (no persistence), communication, diagnostics
|
||||
- **Forbidden Operations:** Persistence writes (except critical diagnostics)
|
||||
- **Exit Conditions:** SD recovery → RUNNING, Manual intervention → SERVICE
|
||||
|
||||
## 3. State Transition Table
|
||||
|
||||
| From State | To State | Trigger | Guard Condition | Action | Authorized Caller |
|
||||
|------------|----------|---------|-----------------|--------|------------------|
|
||||
| `[*]` | `INIT` | Power-on, Reset | None | Initialize hardware, secure boot check | System |
|
||||
| `INIT` | `RUNNING` | Init success | Secure boot OK, MC loaded, sensors detected | Start DAQ, COM, DIAG tasks | System Manager |
|
||||
| `INIT` | `BOOT_FAILURE` | Secure boot fail | Secure boot verification failed | Log security fault, disable application | Secure Boot |
|
||||
| `BOOT_FAILURE` | `INIT` | Manual reset | None | Reset system | User/Engineer |
|
||||
| `RUNNING` | `WARNING` | Non-fatal fault | Diagnostic severity = WARNING | Degrade functionality, notify | Error Handler |
|
||||
| `RUNNING` | `FAULT` | Fatal fault | Diagnostic severity = FATAL | Stop critical features | Error Handler |
|
||||
| `RUNNING` | `OTA_PREP` | OTA request | OTA request received, system ready | Validate readiness | OTA Manager |
|
||||
| `RUNNING` | `MC_UPDATE` | MC update request | MC update received, authenticated | Validate MC | MC Manager |
|
||||
| `RUNNING` | `SERVICE` | Debug session | Debug session authenticated | Pause non-critical tasks | Debug Manager |
|
||||
| `RUNNING` | `SD_DEGRADED` | SD failure | SD card access failure detected | Disable persistence writes | Persistence |
|
||||
| `WARNING` | `RUNNING` | Fault cleared | Diagnostic cleared, system healthy | Restore full functionality | Error Handler |
|
||||
| `WARNING` | `FAULT` | Fault escalated | Multiple warnings or critical fault | Stop degraded features | Error Handler |
|
||||
| `FAULT` | `TEARDOWN` | Recovery attempt | Recovery command received | Initiate controlled shutdown | System Manager |
|
||||
| `OTA_PREP` | `TEARDOWN` | OTA ready | Readiness validated | Begin teardown | OTA Manager |
|
||||
| `OTA_PREP` | `RUNNING` | OTA rejected | Readiness check failed | Resume normal operation | OTA Manager |
|
||||
| `TEARDOWN` | `OTA_UPDATE` | Teardown complete (OTA) | OTA pending, data flushed | Enter OTA state | System Manager |
|
||||
| `TEARDOWN` | `MC_UPDATE` | Teardown complete (MC) | MC update pending, data flushed | Enter MC update | System Manager |
|
||||
| `TEARDOWN` | `INIT` | Teardown complete (reset) | Reset requested, data flushed | Reset system | System Manager |
|
||||
| `OTA_UPDATE` | `RUNNING` | OTA success | Firmware flashed, validated | Reboot into new firmware | OTA Manager |
|
||||
| `OTA_UPDATE` | `FAULT` | OTA failure | Firmware validation failed | Log error, enter fault | OTA Manager |
|
||||
| `MC_UPDATE` | `TEARDOWN` | MC update complete | MC validated, applied | Reinitialize system | MC Manager |
|
||||
| `SERVICE` | `RUNNING` | Session closed | Debug session terminated | Resume normal operation | Debug Manager |
|
||||
| `SD_DEGRADED` | `RUNNING` | SD recovered | SD card access restored | Re-enable persistence | Persistence |
|
||||
| `SD_DEGRADED` | `SERVICE` | Manual intervention | User intervention required | Enter service mode | User/Engineer |
|
||||
|
||||
## 4. Per-State Feature Execution Rules
|
||||
|
||||
### 4.1 DAQ (Data Acquisition) Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | None | Sensor initialization only |
|
||||
| `RUNNING` | Full acquisition cycle | None |
|
||||
| `WARNING` | Degraded acquisition (reduced frequency) | Failed sensors excluded |
|
||||
| `FAULT` | None | Acquisition stopped |
|
||||
| `OTA_PREP` | None | Acquisition stopped |
|
||||
| `OTA_UPDATE` | None | Acquisition stopped |
|
||||
| `MC_UPDATE` | None | Acquisition stopped |
|
||||
| `TEARDOWN` | None | Acquisition stopped |
|
||||
| `SERVICE` | Paused (optional read-only) | No new samples |
|
||||
| `SD_DEGRADED` | Full acquisition | Data not persisted |
|
||||
| `BOOT_FAILURE` | None | Not applicable |
|
||||
|
||||
### 4.2 DQC (Data Quality & Calibration) Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | Sensor detection, MC loading | No calibration |
|
||||
| `RUNNING` | Full quality checks, calibration | None |
|
||||
| `WARNING` | Degraded quality checks | Reduced validation |
|
||||
| `FAULT` | Error reporting only | No quality checks |
|
||||
| `OTA_PREP` | None | Quality checks stopped |
|
||||
| `OTA_UPDATE` | None | Quality checks stopped |
|
||||
| `MC_UPDATE` | MC validation only | No sensor calibration |
|
||||
| `TEARDOWN` | None | Quality checks stopped |
|
||||
| `SERVICE` | Read-only inspection | No calibration |
|
||||
| `SD_DEGRADED` | Full quality checks | Results not persisted |
|
||||
| `BOOT_FAILURE` | None | Not applicable |
|
||||
|
||||
### 4.3 COM (Communication) Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | None | No communication |
|
||||
| `RUNNING` | Full bidirectional communication | None |
|
||||
| `WARNING` | Limited communication (diagnostics only) | Reduced bandwidth |
|
||||
| `FAULT` | Diagnostic reporting only | No data transmission |
|
||||
| `OTA_PREP` | OTA negotiation only | No other communication |
|
||||
| `OTA_UPDATE` | OTA data transfer only | No other communication |
|
||||
| `MC_UPDATE` | MC transfer only | No other communication |
|
||||
| `TEARDOWN` | Session closure only | No new sessions |
|
||||
| `SERVICE` | Debug session communication | No Main Hub communication |
|
||||
| `SD_DEGRADED` | Full communication | Data not persisted |
|
||||
| `BOOT_FAILURE` | Diagnostic reporting only | Limited communication |
|
||||
|
||||
### 4.4 DIAG (Diagnostics) Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | Boot diagnostics | Limited logging |
|
||||
| `RUNNING` | Full diagnostics | None |
|
||||
| `WARNING` | Full diagnostics | None |
|
||||
| `FAULT` | Full diagnostics | None |
|
||||
| `OTA_PREP` | OTA diagnostics | Limited scope |
|
||||
| `OTA_UPDATE` | OTA progress diagnostics | Limited scope |
|
||||
| `MC_UPDATE` | MC update diagnostics | Limited scope |
|
||||
| `TEARDOWN` | Teardown diagnostics | Limited scope |
|
||||
| `SERVICE` | Full diagnostics (read access) | No new diagnostics |
|
||||
| `SD_DEGRADED` | Full diagnostics | Persistence limited |
|
||||
| `BOOT_FAILURE` | Security diagnostics | Limited scope |
|
||||
|
||||
### 4.5 DATA (Persistence) Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | MC loading only | No writes |
|
||||
| `RUNNING` | Full persistence | None |
|
||||
| `WARNING` | Read-only, critical writes | Limited writes |
|
||||
| `FAULT` | Critical diagnostics only | No sensor data writes |
|
||||
| `OTA_PREP` | Read-only | No writes |
|
||||
| `OTA_UPDATE` | OTA data only | No sensor data writes |
|
||||
| `MC_UPDATE` | MC writes only | No sensor data writes |
|
||||
| `TEARDOWN` | Critical data flush only | Authorized writes only |
|
||||
| `SERVICE` | Read-only | No writes |
|
||||
| `SD_DEGRADED` | Read-only (if possible) | No writes |
|
||||
| `BOOT_FAILURE` | None | Not applicable |
|
||||
|
||||
### 4.6 OTA Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | None | OTA not active |
|
||||
| `RUNNING` | OTA negotiation only | No transfer |
|
||||
| `WARNING` | None | OTA blocked |
|
||||
| `FAULT` | None | OTA blocked |
|
||||
| `OTA_PREP` | Readiness validation | No transfer |
|
||||
| `OTA_UPDATE` | Full OTA operations | None |
|
||||
| `MC_UPDATE` | None | OTA blocked |
|
||||
| `TEARDOWN` | None | OTA blocked |
|
||||
| `SERVICE` | None | OTA blocked |
|
||||
| `SD_DEGRADED` | None | OTA blocked |
|
||||
| `BOOT_FAILURE` | None | OTA blocked |
|
||||
|
||||
### 4.7 SEC (Security) Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | Secure boot verification | Must complete before app start |
|
||||
| `RUNNING` | Full security (encryption, authentication) | None |
|
||||
| `WARNING` | Full security | None |
|
||||
| `FAULT` | Security diagnostics | Limited operations |
|
||||
| `OTA_PREP` | OTA authentication | None |
|
||||
| `OTA_UPDATE` | Firmware verification | None |
|
||||
| `MC_UPDATE` | MC authentication | None |
|
||||
| `TEARDOWN` | Key protection | None |
|
||||
| `SERVICE` | Debug authentication | None |
|
||||
| `SD_DEGRADED` | Full security | None |
|
||||
| `BOOT_FAILURE` | Security fault handling | Limited operations |
|
||||
|
||||
### 4.8 SYS (System Management) Feature
|
||||
|
||||
| State | Allowed Operations | Restrictions |
|
||||
|-------|-------------------|--------------|
|
||||
| `INIT` | State management, initialization | Limited operations |
|
||||
| `RUNNING` | Full system management | None |
|
||||
| `WARNING` | Degraded management | Limited operations |
|
||||
| `FAULT` | Fault recovery management | Limited operations |
|
||||
| `OTA_PREP` | OTA state management | Limited operations |
|
||||
| `OTA_UPDATE` | OTA state management | Limited operations |
|
||||
| `MC_UPDATE` | MC state management | Limited operations |
|
||||
| `TEARDOWN` | Teardown execution | Limited operations |
|
||||
| `SERVICE` | Service mode management | Limited operations |
|
||||
| `SD_DEGRADED` | Degraded management | Limited operations |
|
||||
| `BOOT_FAILURE` | Boot failure management | Limited operations |
|
||||
|
||||
## 5. State Transition Timing Requirements
|
||||
|
||||
| Transition | Maximum Duration | Justification |
|
||||
|------------|------------------|---------------|
|
||||
| `[*]` → `INIT` | 100ms | Power-on initialization |
|
||||
| `INIT` → `RUNNING` | 5s | Hardware init, secure boot, MC load |
|
||||
| `INIT` → `BOOT_FAILURE` | 2s | Secure boot verification |
|
||||
| `RUNNING` → `WARNING` | 50ms | Fault detection and state change |
|
||||
| `RUNNING` → `FAULT` | 50ms | Critical fault detection |
|
||||
| `RUNNING` → `OTA_PREP` | 100ms | OTA request processing |
|
||||
| `OTA_PREP` → `TEARDOWN` | 2s | Readiness validation |
|
||||
| `TEARDOWN` → `OTA_UPDATE` | 500ms | Data flush and resource release |
|
||||
| `TEARDOWN` → `INIT` | 500ms | Data flush and reset |
|
||||
| `OTA_UPDATE` → `RUNNING` | 10 minutes | Firmware transfer and flashing |
|
||||
| `RUNNING` → `SERVICE` | 100ms | Debug session establishment |
|
||||
| `SERVICE` → `RUNNING` | 50ms | Debug session closure |
|
||||
|
||||
## 6. State Notification Mechanism
|
||||
|
||||
All state transitions SHALL notify registered components via the Event System:
|
||||
- **Event Type:** `SYSTEM_STATE_CHANGED`
|
||||
- **Payload:** Previous state, new state, transition reason
|
||||
- **Subscribers:** All feature managers (DAQ, DQC, COM, DIAG, DATA, OTA, SEC, SYS)
|
||||
|
||||
## 7. Traceability
|
||||
|
||||
- **SR-SYS-001:** Implemented via complete FSM definition
|
||||
- **SR-SYS-002:** Implemented via per-state feature execution rules
|
||||
- **SR-SYS-003:** Implemented via state notification mechanism
|
||||
|
||||
## 8. Mermaid State Diagram
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> INIT
|
||||
INIT --> RUNNING: initSuccess
|
||||
INIT --> BOOT_FAILURE: secureBootFail
|
||||
BOOT_FAILURE --> INIT: manualReset
|
||||
RUNNING --> WARNING: nonFatalFault
|
||||
RUNNING --> FAULT: fatalFault
|
||||
RUNNING --> OTA_PREP: otaRequest
|
||||
RUNNING --> MC_UPDATE: mcUpdateRequest
|
||||
RUNNING --> SERVICE: debugSession
|
||||
RUNNING --> SD_DEGRADED: sdFailure
|
||||
WARNING --> RUNNING: faultCleared
|
||||
WARNING --> FAULT: faultEscalated
|
||||
FAULT --> TEARDOWN: recoveryAttempt
|
||||
OTA_PREP --> TEARDOWN: otaReady
|
||||
OTA_PREP --> RUNNING: otaRejected
|
||||
TEARDOWN --> OTA_UPDATE: otaPending
|
||||
TEARDOWN --> MC_UPDATE: mcPending
|
||||
TEARDOWN --> INIT: resetRequested
|
||||
OTA_UPDATE --> RUNNING: otaSuccess
|
||||
OTA_UPDATE --> FAULT: otaFailure
|
||||
MC_UPDATE --> TEARDOWN: mcComplete
|
||||
SERVICE --> RUNNING: sessionClosed
|
||||
SD_DEGRADED --> RUNNING: sdRecovered
|
||||
SD_DEGRADED --> SERVICE: manualIntervention
|
||||
```
|
||||
275
System Design/engineering review report2.md
Normal file
275
System Design/engineering review report2.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# **ASF Sensor Hub - Senior Embedded Systems Architecture Review Report**
|
||||
|
||||
## **A. Executive Summary**
|
||||
|
||||
### **Overall System Maturity Level: 65%**
|
||||
- **Documentation Quality: 90%** - Exceptional architectural definition and requirements traceability
|
||||
- **Implementation Readiness: 40%** - Components are stubbed but lack functional implementation
|
||||
- **Cross-Feature Integration: 30%** - Critical architectural gaps in state management and feature interaction
|
||||
|
||||
### **Major Risks (Top 5)**
|
||||
1. **CRITICAL: Missing System State Machine** - No implementation of the defined FSM, risking undefined behavior during state transitions
|
||||
2. **CRITICAL: Event System Not Implemented** - Core architectural component for cross-feature communication is missing
|
||||
3. **MAJOR: OTA Safety Violations** - No teardown mechanism, no data persistence before flashing
|
||||
4. **MAJOR: Security Architecture Incomplete** - Secure boot and flash encryption not enforced
|
||||
5. **MAJOR: Real-Time Constraints Undefined** - No deterministic timing guarantees for sensor acquisition
|
||||
|
||||
### **Go/No-Go Recommendation: NO-GO**
|
||||
**Recommendation:** Do NOT proceed to implementation phase. **REQUIRES IMMEDIATE ARCHITECTURAL CLARIFICATION AND PROTOTYPING.**
|
||||
|
||||
## **B. Detailed Findings**
|
||||
|
||||
### **Architecture Review**
|
||||
|
||||
#### **Strengths**
|
||||
- **Layered Architecture Properly Defined** - Clear separation between Application, Drivers, OSAL, and HAL layers
|
||||
- **Component-Based Design** - Modular structure with well-defined interfaces
|
||||
- **Event-Driven Model Specified** - Appropriate for distributed embedded systems
|
||||
|
||||
#### **Critical Architectural Violations**
|
||||
1. **Event System Implementation MISSING** - Core architectural component not implemented
|
||||
- **Impact:** No cross-feature communication mechanism
|
||||
- **Severity:** CRITICAL
|
||||
|
||||
2. **System State Machine Implementation MISSING** - No FSM implementation despite being architecturally central
|
||||
- **Impact:** Undefined system behavior during state transitions
|
||||
- **Severity:** CRITICAL
|
||||
|
||||
3. **Data Persistence (DP) Component Stubbed** - No functional implementation
|
||||
- **Impact:** No data integrity during power loss or updates
|
||||
- **Severity:** MAJOR
|
||||
|
||||
4. **Hardware Abstraction Violations** - Application layer components directly include ESP-IDF headers
|
||||
- **Impact:** Platform lock-in, reduced testability
|
||||
- **Severity:** MAJOR
|
||||
|
||||
### **Requirements & Feature Consistency**
|
||||
|
||||
#### **Requirements Quality Assessment**
|
||||
- **Well-Structured:** 95% of requirements follow "SHALL" format
|
||||
- **Testable:** 90% of requirements are verifiable
|
||||
- **Traceable:** 100% linked to features via unique IDs
|
||||
|
||||
#### **Critical Gaps Identified**
|
||||
1. **Missing System States Definition**
|
||||
- Requirements reference states (INIT, RUNNING, OTA_UPDATE, etc.) but no complete state transition table exists
|
||||
- **Impact:** Undefined behavior during state changes
|
||||
|
||||
2. **Timing Requirements NOT SPECIFIED**
|
||||
- No deterministic timing bounds for sensor acquisition cycles
|
||||
- No maximum latency requirements for communication
|
||||
- **Impact:** Real-time behavior cannot be guaranteed
|
||||
|
||||
3. **Resource Constraints NOT DEFINED**
|
||||
- No CPU utilization limits specified
|
||||
- No memory usage bounds defined
|
||||
- No flash wear-out protection requirements
|
||||
- **Impact:** System may fail under resource pressure
|
||||
|
||||
#### **Requirements Conflicts**
|
||||
1. **Security vs. Performance Trade-off NOT RESOLVED**
|
||||
- Encrypted communication required but no performance impact analysis
|
||||
- **Impact:** May violate real-time constraints
|
||||
|
||||
2. **OTA Safety vs. Availability NOT BALANCED**
|
||||
- OTA requires controlled teardown but no maximum downtime specified
|
||||
- **Impact:** System may be unavailable for extended periods
|
||||
|
||||
### **Cross-Feature Interaction Review**
|
||||
|
||||
#### **DAQC ↔ DATA Interaction**
|
||||
- **CURRENT STATE:** No implementation of data flow from sensor acquisition to persistence
|
||||
- **RISK:** Sensor data lost during power failures
|
||||
- **RECOMMENDATION:** Implement DP component with guaranteed write-before-use
|
||||
|
||||
#### **OTA ↔ Persistence Interaction**
|
||||
- **CURRENT STATE:** OTA feature assumes teardown but no mechanism exists
|
||||
- **RISK:** Critical data corruption during firmware updates
|
||||
- **RECOMMENDATION:** Implement mandatory data flush before OTA activation
|
||||
|
||||
#### **OTA ↔ Security Interaction**
|
||||
- **CURRENT STATE:** OTA occurs over encrypted channels but secure boot not enforced
|
||||
- **RISK:** Malicious firmware installation possible
|
||||
- **RECOMMENDATION:** Implement secure boot verification before any OTA execution
|
||||
|
||||
#### **Diagnostics ↔ System State Management**
|
||||
- **CURRENT STATE:** Diagnostics component exists but no integration with system state
|
||||
- **RISK:** Diagnostic events may trigger invalid state transitions
|
||||
- **RECOMMENDATION:** Bind diagnostic severity levels to state transition triggers
|
||||
|
||||
#### **Debug Sessions ↔ Secure Boot**
|
||||
- **CURRENT STATE:** Debug access allowed but no security controls
|
||||
- **RISK:** Debug interface could bypass secure boot
|
||||
- **RECOMMENDATION:** Implement authenticated debug access with secure boot verification
|
||||
|
||||
### **ESP-IDF & RTOS Suitability**
|
||||
|
||||
#### **Task Model Assessment**
|
||||
- **APPROPRIATE:** RTOS-based design suitable for ESP32-S3
|
||||
- **CONCERN:** No task priority definition or scheduling analysis
|
||||
- **RECOMMENDATION:** Define task priorities and worst-case execution times
|
||||
|
||||
#### **ISR vs Task Responsibilities**
|
||||
- **NOT SPECIFIED:** No clear delineation between interrupt and task contexts
|
||||
- **RISK:** Blocking operations in ISRs could cause system lockup
|
||||
- **RECOMMENDATION:** Define ISR-to-task communication patterns
|
||||
|
||||
#### **Memory Management Risks**
|
||||
- **HIGH RISK:** Dynamic memory allocation in runtime paths not prohibited
|
||||
- **IMPACT:** Memory fragmentation and allocation failures possible
|
||||
- **RECOMMENDATION:** Static memory allocation for critical paths
|
||||
|
||||
#### **Flash/SD Card Wear Risks**
|
||||
- **NOT ADDRESSED:** No wear-leveling strategy defined
|
||||
- **IMPACT:** SD card failure after extended operation
|
||||
- **RECOMMENDATION:** Implement wear-aware storage management
|
||||
|
||||
#### **OTA Partitioning Implications**
|
||||
- **NOT ANALYZED:** ESP-IDF OTA partition strategy not evaluated against system requirements
|
||||
- **RISK:** Insufficient space for OTA updates
|
||||
- **RECOMMENDATION:** Define partition layout and OTA strategy
|
||||
|
||||
#### **Secure Boot & Flash Constraints**
|
||||
- **NOT IMPLEMENTED:** ESP32-S3 secure boot features not utilized
|
||||
- **IMPACT:** Firmware authenticity not guaranteed
|
||||
- **RECOMMENDATION:** Enable secure boot with hardware root-of-trust
|
||||
|
||||
### **Standards Readiness Assessment**
|
||||
|
||||
#### **IEC 61499 Alignment**
|
||||
- **READY:** Architecture follows event-driven principles
|
||||
- **GAP:** No function block definitions or event interface specifications
|
||||
- **ASSESSMENT:** Conceptually aligned but implementation details missing
|
||||
|
||||
#### **ISA-95 Alignment**
|
||||
- **READY:** Correctly positioned at Level 1-2 boundary
|
||||
- **GAP:** No formal interface definition with Level 3 (Main Hub)
|
||||
- **ASSESSMENT:** Architecturally sound but interface specifications incomplete
|
||||
|
||||
### **System Review Checklist Validation**
|
||||
|
||||
#### **PASSED ITEMS**
|
||||
- Feature coverage complete across DAQ, DQC, COM, DIAG, DATA, OTA, SEC, SYS domains
|
||||
- Requirements use "SHALL" format consistently
|
||||
- Unique requirement IDs assigned
|
||||
- Traceability to features established
|
||||
- Layered architecture properly defined
|
||||
- Hardware access isolated through drivers
|
||||
- Security constraints identified
|
||||
|
||||
#### **FAILED ITEMS**
|
||||
- **CRITICAL:** No system state machine implementation
|
||||
- **CRITICAL:** Event system not implemented
|
||||
- **MAJOR:** No teardown mechanism for OTA/configuration updates
|
||||
- **MAJOR:** Data persistence before teardown not guaranteed
|
||||
- **MAJOR:** Data integrity during updates not protected
|
||||
- **MAJOR:** Real-time constraints not bounded
|
||||
- **MAJOR:** Resource usage not limited
|
||||
- **MINOR:** Debug isolation not enforced
|
||||
- **MINOR:** HMI read-only constraint not technically enforced
|
||||
|
||||
#### **ITEMS NEEDING CLARIFICATION**
|
||||
- Maximum acceptable system downtime during OTA
|
||||
- Sensor acquisition cycle determinism requirements
|
||||
- Memory usage limits and monitoring
|
||||
- SD card failure recovery strategy
|
||||
- Time synchronization accuracy requirements
|
||||
|
||||
## **C. Missing / Risky Areas**
|
||||
|
||||
### **Missing System Requirements**
|
||||
1. **State Transition Timing Requirements** - Maximum time for state changes
|
||||
2. **Resource Utilization Limits** - CPU, memory, and storage bounds
|
||||
3. **Fault Recovery Time Requirements** - Maximum time to recover from failures
|
||||
4. **Data Retention Guarantees** - Minimum data persistence duration
|
||||
5. **Communication Latency Bounds** - Maximum acceptable delays
|
||||
|
||||
### **Missing System States**
|
||||
1. **BOOT_FAILURE State** - When secure boot verification fails
|
||||
2. **CALIBRATION_UPDATE State** - For machine constants updates
|
||||
3. **DIAGNOSTIC_MODE State** - For engineering diagnostics
|
||||
4. **LOW_POWER State** - For power conservation
|
||||
5. **FACTORY_RESET State** - For system reconfiguration
|
||||
|
||||
### **Missing Failure Handling**
|
||||
1. **SD Card Failure Recovery** - No strategy for storage medium failure
|
||||
2. **Communication Link Loss** - Extended disconnection handling not defined
|
||||
3. **Sensor Cascade Failure** - Multiple sensor failures handling
|
||||
4. **OTA Corruption Recovery** - Firmware image corruption during transfer
|
||||
5. **Time Synchronization Loss** - Clock drift management
|
||||
|
||||
### **Missing Documentation**
|
||||
1. **State Transition Diagrams** - Complete FSM with all transitions
|
||||
2. **Timing Budget Analysis** - End-to-end timing requirements
|
||||
3. **Resource Budget Allocation** - Memory and CPU allocation per component
|
||||
4. **Failure Mode Analysis** - FMEA for critical components
|
||||
5. **Interface Control Documents** - Detailed API specifications
|
||||
|
||||
## **D. Improvement Recommendations**
|
||||
|
||||
### **Immediate Actions (Pre-Implementation)**
|
||||
1. **Implement System State Machine** - Define and implement complete FSM with all states and transitions
|
||||
2. **Implement Event System** - Core communication backbone for cross-feature interaction
|
||||
3. **Define Timing Requirements** - Specify deterministic bounds for all time-critical operations
|
||||
4. **Implement Data Persistence** - Complete DP component with guaranteed data integrity
|
||||
|
||||
### **Architectural Clarifications Needed**
|
||||
1. **State Transition Rules** - Define which features can execute in which states
|
||||
2. **Failure Escalation Policy** - How faults propagate through the system
|
||||
3. **Resource Management Strategy** - Memory, CPU, and storage allocation policies
|
||||
4. **OTA Safety Protocol** - Complete procedure for fail-safe firmware updates
|
||||
|
||||
### **Implementation Priorities**
|
||||
1. **Phase 1:** Core infrastructure (State Machine, Event System, DP Component)
|
||||
2. **Phase 2:** Sensor acquisition and data quality features
|
||||
3. **Phase 3:** Communication and security features
|
||||
4. **Phase 4:** OTA and diagnostics features
|
||||
5. **Phase 5:** HMI and system management features
|
||||
|
||||
### **Quality Assurance Requirements**
|
||||
1. **Static Analysis Mandatory** - All code must pass MISRA C++ compliance
|
||||
2. **Unit Test Coverage >95%** - For all components except hardware interfaces
|
||||
3. **Integration Testing Required** - Cross-feature interaction validation
|
||||
4. **Performance Benchmarking** - Against defined timing and resource budgets
|
||||
|
||||
## **E. Generated Artifacts**
|
||||
|
||||
### **Recommended State Machine Diagram**
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> INIT
|
||||
INIT --> RUNNING: successful_init
|
||||
INIT --> FAULT: init_failure
|
||||
RUNNING --> OTA_UPDATE: ota_triggered
|
||||
RUNNING --> WARNING: minor_fault
|
||||
RUNNING --> FAULT: critical_fault
|
||||
WARNING --> RUNNING: fault_cleared
|
||||
WARNING --> FAULT: fault_escalated
|
||||
OTA_UPDATE --> RUNNING: ota_success
|
||||
OTA_UPDATE --> FAULT: ota_failure
|
||||
FAULT --> TEARDOWN: recovery_attempt
|
||||
TEARDOWN --> INIT: system_reset
|
||||
TEARDOWN --> [*]: power_down
|
||||
```
|
||||
|
||||
### **Critical Path Timing Budget**
|
||||
|
||||
| Operation | Maximum Time | Justification |
|
||||
|-----------|--------------|---------------|
|
||||
| Sensor Acquisition Cycle | 100ms | Real-time environmental monitoring |
|
||||
| State Transition | 50ms | Minimize system unavailability |
|
||||
| Data Persistence | 200ms | Prevent data loss during power failures |
|
||||
| OTA Teardown | 500ms | Balance safety with availability |
|
||||
| Secure Boot Verification | 2s | Hardware-enforced security |
|
||||
|
||||
### **Resource Allocation Budget**
|
||||
|
||||
| Resource | Maximum Usage | Monitoring Required |
|
||||
|----------|----------------|-------------------|
|
||||
| RAM (Runtime) | 60% | Yes |
|
||||
| Flash (Application) | 70% | Yes |
|
||||
| CPU (Peak) | 80% | Yes |
|
||||
| SD Card (Daily Writes) | 100MB | Yes |
|
||||
|
||||
**CONCLUSION:** The ASF Sensor Hub has excellent architectural foundations but requires significant implementation work before proceeding to full development. The current state represents architectural completeness without implementation readiness. Immediate focus must be on core infrastructure components (State Machine, Event System, Data Persistence) before feature implementation can safely proceed.
|
||||
115
System Design/system_requirementsand_and_traceability.csv
Normal file
115
System Design/system_requirementsand_and_traceability.csv
Normal file
@@ -0,0 +1,115 @@
|
||||
ID,Type,Status,Title,Description,Parent_ID,Relations
|
||||
45,Requirements,Specified,"The system shall include a central server that aggregates and analyzes data from all main hubs across different farms, using machine learning algorithms to optimize control strategies for each farm based on collected data.","The system shall include a central server that aggregates and analyzes data from all main hubs across different farms, using machine learning algorithms to optimize control strategies for each farm based on collected data.",,
|
||||
46,Requirements,Specified,"The sub-hub shall be capable of performing minor calibration functions, including sensor recalibration, before sending data to the main hub.","The sub-hub shall be capable of performing minor calibration functions, including sensor recalibration, before sending data to the main hub.",,
|
||||
47,Requirements,Specified,"The main hub shall include control algorithms for managing the environment of the poultry house, including temperature, humidity, and air quality, by controlling the actuators like ventilation fans, heaters, lighting systems, and feeding systems.","The main hub shall include control algorithms for managing the environment of the poultry house, including temperature, humidity, and air quality, by controlling the actuators like ventilation fans, heaters, lighting systems, and feeding systems.",,
|
||||
48,Requirements,Specified,"The central server shall use the aggregated data from all farms to generate optimized control strategies based on machine learning, which are then sent back to the respective main hubs.","The central server shall use the aggregated data from all farms to generate optimized control strategies based on machine learning, which are then sent back to the respective main hubs.",,
|
||||
49,Requirements,Specified,"The main hub shall be connected to a local control board, which directly controls the actuators, such as fans, heaters, lights, and feeders.","The main hub shall be connected to a local control board, which directly controls the actuators, such as fans, heaters, lights, and feeders.",,
|
||||
50,Requirements,Specified,The sub-hubs shall be capable of real-time data collection and will update the main hub with sensor readings at specified intervals or when sensor values change beyond predefined thresholds.,The sub-hubs shall be capable of real-time data collection and will update the main hub with sensor readings at specified intervals or when sensor values change beyond predefined thresholds.,,
|
||||
51,Requirements,Specified,"The system shall be capable of remote monitoring and control, allowing farm managers to access real-time data and control system settings via a mobile application or web interface.","The system shall be capable of remote monitoring and control, allowing farm managers to access real-time data and control system settings via a mobile application or web interface.",,
|
||||
52,Requirements,Specified,"The system shall be able to generate alarms for critical situations such as temperature deviations, high ammonia levels, equipment malfunctions, or other emergency conditions.","The system shall be able to generate alarms for critical situations such as temperature deviations, high ammonia levels, equipment malfunctions, or other emergency conditions.",,
|
||||
53,Requirements,Specified,"The system shall support data logging and historical analysis, providing insights into past farm conditions, sensor performance, and actuator behavior.","The system shall support data logging and historical analysis, providing insights into past farm conditions, sensor performance, and actuator behavior.",,
|
||||
54,Requirements,Specified,The system shall implement security measures such as data encryption and user authentication for remote access to prevent unauthorized access to farm data and control systems.,The system shall implement security measures such as data encryption and user authentication for remote access to prevent unauthorized access to farm data and control systems.,,
|
||||
55,Requirements,Specified,"The sub-hubs shall include diagnostic tools to ensure the correct functionality of sensors, communication, and data transmission.","The sub-hubs shall include diagnostic tools to ensure the correct functionality of sensors, communication, and data transmission.",,
|
||||
56,Requirements,Specified,"The system shall support scalability, allowing new sub-hubs and main hubs to be added seamlessly to expand the system to additional poultry rooms or farms.","The system shall support scalability, allowing new sub-hubs and main hubs to be added seamlessly to expand the system to additional poultry rooms or farms.",,
|
||||
57,Requirements,Specified,"The system shall provide automated decision-making logic for controlling environmental parameters, which may be based on fuzzy logic or proportional control algorithms.","The system shall provide automated decision-making logic for controlling environmental parameters, which may be based on fuzzy logic or proportional control algorithms.",,
|
||||
58,Requirements,Specified,"The central server shall be capable of over-the-air (OTA) updates for all system firmware, ensuring that the latest software updates and features can be deployed to all hubs.","The central server shall be capable of over-the-air (OTA) updates for all system firmware, ensuring that the latest software updates and features can be deployed to all hubs.",,
|
||||
59,Requirements,Specified,"The system shall include energy management capabilities, optimizing the operation of actuators such as fans, heaters, and lighting to reduce energy consumption.","The system shall include energy management capabilities, optimizing the operation of actuators such as fans, heaters, and lighting to reduce energy consumption.",,
|
||||
60,Requirements,Specified,"The system shall be compliant with industry standards, including animal welfare regulations and environmental requirements, ensuring the health and safety of the poultry.","The system shall be compliant with industry standards, including animal welfare regulations and environmental requirements, ensuring the health and safety of the poultry.",,
|
||||
61,Requirements,Specified,"The system shall support multi-zone control, allowing different sections of the poultry house to have independent environmental control based on the local conditions measured by sensors in those zones.","The system shall support multi-zone control, allowing different sections of the poultry house to have independent environmental control based on the local conditions measured by sensors in those zones.",,
|
||||
62,Requirements,Specified,"The system shall provide integration with other farm management software, allowing data from environmental control to be merged with broader farm management systems.","The system shall provide integration with other farm management software, allowing data from environmental control to be merged with broader farm management systems.",,
|
||||
63,Requirements,Specified,"The system shall include fail-safe mechanisms to ensure continuous operation in case of failure in communication or hardware, including backup power and data storage.","The system shall include fail-safe mechanisms to ensure continuous operation in case of failure in communication or hardware, including backup power and data storage.",,
|
||||
64,Requirements,Specified,"The system shall be designed for ease of use, with a user-friendly interface for farm managers to configure, monitor, and control the system.","The system shall be designed for ease of use, with a user-friendly interface for farm managers to configure, monitor, and control the system.",,
|
||||
65,Requirements,Specified,"The system shall enable remote diagnostics for troubleshooting and support, reducing the need for on-site visits.","The system shall enable remote diagnostics for troubleshooting and support, reducing the need for on-site visits.",,
|
||||
394,Requirements,In specification,[SR-DAQ-001] Support Multi-Sensor Environmental Data Acquisition,"The system shall support simultaneous acquisition of environmental data from multiple sensor types, including temperature, humidity, CO2, NH3, VOC, particulate matter, and ambient light.\n\nThis requirements traces to feature [F-DAQ-01].",,includes(#388)
|
||||
395,Requirements,In specification,[SR-DAQ-002] Dedicated Sensor Slot Mapping,The system shall assign each supported sensor type to a predefined and unique hardware slot to prevent incorrect sensor insertion or configuration.\n\nThis requirements traces to feature [F-DAQ-01].,,includes(#388)
|
||||
396,Requirements,In specification,[SR-DAQ-003] Sensor Presence Detection,The system shall detect the physical presence of each sensor via a dedicated hardware detection signal prior to sensor initialization.\n\nThis requirements traces to feature [F-DAQ-01].,,includes(#388)
|
||||
397,Requirements,In specification,[SR-DAQ-004] Conditional Sensor Initialization,The system shall initialize and activate only those sensors that are detected as present and enabled during system startup or reinitialization.\n\nThis requirements traces to feature [F-DAQ-01].,,includes(#389)
|
||||
398,Requirements,In specification,[SR-DAQ-005] High-Frequency Sensor Sampling,"The system shall sample each enabled sensor multiple times within a single acquisition cycle, with a default of ten (10) samples per sensor per cycle.\n\nThis requirements traces to feature [F-DAQ-02].",,includes(#389)
|
||||
399,Requirements,In specification,[SR-DAQ-006] Local Sensor Data Filtering,The system shall apply a local filtering mechanism to raw sensor samples to produce a single filtered sensor value per acquisition cycle.\n\nThe filtering mechanism shall execute on the Sensor Hub.\n\nThis requirements traces to feature [F-DAQ-02].,,includes(#389)
|
||||
400,Requirements,In specification,[SR-DAQ-007] Deterministic Sampling Window,The system shall complete each sensor’s sampling and filtering process within a bounded and deterministic time window to ensure real-time behavior.\n\nThis requirements traces to feature [F-DAQ-02].,,includes(#390)
|
||||
401,Requirements,In specification,[SR-DAQ-008] Timestamp Generation for Sensor Data,The system shall generate a timestamp for each filtered sensor value upon completion of the acquisition and filtering process.\n\nThis requirements traces to feature [F-DAQ-03].,,includes(#390)
|
||||
402,Requirements,In specification,[SR-DAQ-009] Timestamped Sensor Data Record Structure,"The system shall generate a timestamped sensor data record containing at minimum the sensor identifier, sensor type, filtered value, unit of measurement, timestamp, and data validity status.\n\nThis requirements traces to feature [F-DAQ-03].",,includes(#390)
|
||||
403,Requirements,In specification,[SR-DAQ-010] Availability of Latest Sensor Data,The system shall maintain the most recent timestamped sensor data record in memory and make it available for persistence and on-demand communication requests.\n\nThis requirements traces to feature [F-DAQ-03].,,includes(#390)
|
||||
409,Requirements,In specification,[SR-DQC-001] Detect Sensor Presence,The system shall detect the physical presence of each sensor using a dedicated hardware-based detection mechanism. This requirement traces to feature [F-DQC-01].,,includes(#405)
|
||||
410,Requirements,In specification,[SR-DQC-002] Perform Sensor Detection During Initialization,The system shall perform sensor presence detection during system startup and after any reinitialization or reconfiguration event. This requirement traces to feature [F-DQC-01].,,includes(#405)
|
||||
411,Requirements,In specification,[SR-DQC-003] Conditional Sensor Initialization,The system shall initialize and activate only sensors that are detected as present. This requirement traces to feature [F-DQC-01].,,includes(#405)
|
||||
412,Requirements,In specification,[SR-DQC-004] Assign Fixed Sensor Slot Types,The system shall assign each physical sensor slot to a predefined sensor type. This requirement traces to feature [F-DQC-02].,,includes(#406)
|
||||
413,Requirements,In specification,[SR-DQC-005] Verify Sensor Type Compatibility,The system shall verify that a detected sensor matches the expected sensor type for its assigned slot. This requirement traces to feature [F-DQC-02].,,includes(#406)
|
||||
414,Requirements,In specification,[SR-DQC-006] Reject Invalid Sensor Configurations,The system shall reject and report any sensor-slot mismatch as a diagnostic event. This requirement traces to feature [F-DQC-02].,,includes(#406)
|
||||
415,Requirements,In specification,[SR-DQC-007] Monitor Sensor Health,The system shall continuously monitor sensor responsiveness and signal validity during normal operation. This requirement traces to feature [F-DQC-03].,,includes(#407)
|
||||
416,Requirements,In specification,[SR-DQC-008] Detect Sensor Failure Conditions,"The system shall detect sensor failures including disconnection, non-responsiveness, and out-of-range measurement values. This requirement traces to feature [F-DQC-03].",,includes(#407)
|
||||
417,Requirements,In specification,[SR-DQC-009] Isolate Failed Sensors,The system shall mark detected faulty sensors as defective and exclude them from data acquisition and reporting. This requirement traces to feature [F-DQC-03].,,includes(#407)
|
||||
418,Requirements,In specification,[SR-DQC-010] Report Sensor Failures,The system shall report detected sensor failures to the Main Hub with timestamps and failure classification. This requirement traces to feature [F-DQC-03].,,includes(#407)
|
||||
419,Requirements,In specification,[SR-DQC-011] Maintain Machine Constants Dataset,"The system shall maintain a Machine Constants dataset defining sensor configuration, calibration parameters, and communication identifiers. This requirement traces to feature [F-DQC-04].",,includes(#408)
|
||||
420,Requirements,In specification,[SR-DQC-012] Persist Machine Constants,The system shall store the Machine Constants dataset in non-volatile storage. This requirement traces to feature [F-DQC-04].,,includes(#408)
|
||||
421,Requirements,In specification,[SR-DQC-013] Load Machine Constants at Startup,The system shall load and apply the Machine Constants dataset during system initialization. This requirement traces to feature [F-DQC-04].,,includes(#408)
|
||||
422,Requirements,In specification,[SR-DQC-014] Support Remote Machine Constants Update,The system shall support remote updates of the Machine Constants dataset initiated by the Main Hub. This requirement traces to feature [F-DQC-04].,,includes(#408)
|
||||
423,Requirements,In specification,[SR-DQC-015] Controlled Reinitialization After Update,The system shall apply updated Machine Constants only after executing a controlled teardown and reinitialization procedure. This requirement traces to feature [F-DQC-04].,,includes(#408)
|
||||
429,Requirements,In specification,[SR-COM-001] Bidirectional Main Hub Communication,The system shall support bidirectional communication between the Sensor Hub and the Main Hub. This requirement traces to feature [F-COM-01].,,includes(#426)
|
||||
430,Requirements,In specification,[SR-COM-002] Transmit Data to Main Hub,"The system shall transmit sensor data, diagnostics information, and system status to the Main Hub. This requirement traces to feature [F-COM-01].",,includes(#426)
|
||||
431,Requirements,In specification,[SR-COM-003] Receive Commands from Main Hub,"The system shall receive commands, configuration updates, and firmware update requests from the Main Hub. This requirement traces to feature [F-COM-01].",,includes(#426)
|
||||
432,Requirements,In specification,[SR-COM-004] Monitor Communication Link Status,The system shall monitor the status of the communication link with the Main Hub and report link availability and failure conditions. This requirement traces to feature [F-COM-01].,,includes(#426)
|
||||
433,Requirements,In specification,[SR-COM-005] Support On-Demand Data Requests,The system shall support on-demand requests from the Main Hub for sensor data. This requirement traces to feature [F-COM-02].,,includes(#427)
|
||||
434,Requirements,In specification,[SR-COM-006] Respond with Latest Sensor Data,The system shall respond to on-demand data requests with the most recent timestamped sensor data. This requirement traces to feature [F-COM-02].,,includes(#427)
|
||||
435,Requirements,In specification,[SR-COM-007] Include Data Validity in Responses,The system shall include sensor status and data validity information in on-demand data responses. This requirement traces to feature [F-COM-02].,,includes(#427)
|
||||
436,Requirements,In specification,[SR-COM-008] Support Peer Sensor Hub Communication,The system shall support limited peer-to-peer communication between Sensor Hubs. This requirement traces to feature [F-COM-03].,,includes(#428)
|
||||
437,Requirements,In specification,[SR-COM-009] Allow Peer Coordination Functions,The system shall allow peer communication for basic coordination functions such as connectivity checks or time synchronization. This requirement traces to feature [F-COM-03].,,includes(#428)
|
||||
438,Requirements,In specification,[SR-COM-010] Isolate Peer Communication from Control Logic,The system shall ensure that peer Sensor Hub communication does not interfere with Main Hub communication or control operations. This requirement traces to feature [F-COM-03].,,includes(#428)
|
||||
443,Requirements,New,[SR-DIAG-001] Implement Diagnostic Code Framework,"The system shall implement a diagnostic code framework for reporting system health conditions, warnings, errors, and fatal faults. This requirement traces to feature [F-DIAG-01].",,includes(#440)
|
||||
444,Requirements,New,[SR-DIAG-002] Assign Unique Diagnostic Codes,The system shall assign a unique diagnostic code to each detected fault or abnormal condition. This requirement traces to feature [F-DIAG-01].,,includes(#440)
|
||||
445,Requirements,New,[SR-DIAG-003] Classify Diagnostic Severity,"The system shall classify diagnostic codes by severity level including informational, warning, error, and fatal. This requirement traces to feature [F-DIAG-01].",,includes(#440)
|
||||
446,Requirements,New,[SR-DIAG-004] Timestamp and Source Diagnostics,The system shall associate each diagnostic event with a timestamp and the originating system component. This requirement traces to feature [F-DIAG-01].,,includes(#440)
|
||||
447,Requirements,New,[SR-DIAG-005] Persist Diagnostic Events,The system shall persist diagnostic events in non-volatile storage. This requirement traces to feature [F-DIAG-02].,,includes(#441)
|
||||
448,Requirements,New,[SR-DIAG-006] Retain Diagnostics Across Resets,The system shall retain diagnostic data across system resets and power cycles. This requirement traces to feature [F-DIAG-02].,,includes(#441)
|
||||
449,Requirements,New,[SR-DIAG-007] Bounded Diagnostic Storage,The system shall implement a bounded diagnostic storage mechanism with a defined overwrite or rollover policy. This requirement traces to feature [F-DIAG-02].,,includes(#441)
|
||||
450,Requirements,New,[SR-DIAG-008] Provide Diagnostic Session Interface,The system shall provide a diagnostic session interface for accessing diagnostic and system health data. This requirement traces to feature [F-DIAG-03].,,includes(#442)
|
||||
451,Requirements,New,[SR-DIAG-009] Retrieve Diagnostic Records,The system shall allow authorized diagnostic sessions to retrieve stored diagnostic events. This requirement traces to feature [F-DIAG-03].,,includes(#442)
|
||||
452,Requirements,New,[SR-DIAG-010] Clear Diagnostic Records,The system shall allow authorized diagnostic sessions to clear stored diagnostic records. This requirement traces to feature [F-DIAG-03].,,includes(#442)
|
||||
453,Requirements,New,[SR-DIAG-011] Non-Intrusive Diagnostic Sessions,The system shall ensure that diagnostic sessions do not interfere with normal sensor acquisition or communication operations. This requirement traces to feature [F-DIAG-03].,,includes(#442)
|
||||
465,Requirements,New,[SR-DATA-001] Persistent Timestamped Sensor Data,The system shall persist timestamped sensor data in non-volatile storage.,,includes(#462)
|
||||
466,Requirements,New,[SR-DATA-002] Sensor Data Metadata Storage,"The system shall store sensor data together with sensor identifiers, timestamps, and validity status.",,includes(#462)
|
||||
467,Requirements,New,[SR-DATA-003] Configurable Data Retention Policy,The system shall support configurable data retention and overwrite policies for persisted sensor data.,,includes(#462)
|
||||
468,Requirements,New,[SR-DATA-004] Data Persistence Component Interface,The system shall provide a Data Persistence (DP) component as the sole interface for persistent data access.,,includes(#463)
|
||||
469,Requirements,New,[SR-DATA-005] Storage Access Isolation,The system shall prevent application and feature modules from directly accessing storage hardware.,,includes(#463)
|
||||
470,Requirements,New,[SR-DATA-006] Structured Data Serialization,The DP component shall support serialization and deserialization of structured system data.,,includes(#463)
|
||||
471,Requirements,New,[SR-DATA-007] Data Flush Before Teardown,The system shall flush all critical runtime data to non-volatile storage before entering a controlled teardown or reset state.,,includes(#464)
|
||||
472,Requirements,New,[SR-DATA-008] Data Integrity During Updates,The system shall protect data integrity during firmware updates and machine constant updates.,,includes(#464)
|
||||
473,Requirements,New,[SR-DATA-009] Persistence Verification,The system shall verify successful data persistence before completing a system state transition.,,includes(#464)
|
||||
479,Requirements,New,[SR-OTA-001] OTA Negotiation Support,The system shall support OTA update negotiation initiated by the Main Hub.,,includes(#475)
|
||||
480,Requirements,New,[SR-OTA-002] OTA Readiness Validation,The system shall verify internal readiness conditions before accepting an OTA update request.,,includes(#475)
|
||||
481,Requirements,New,[SR-OTA-003] OTA Acknowledgement,The system shall explicitly acknowledge or reject OTA update requests.,,includes(#475)
|
||||
482,Requirements,New,[SR-OTA-004] Firmware Reception,The system shall receive firmware images over the established communication interface.,,includes(#476)
|
||||
483,Requirements,New,[SR-OTA-005] Firmware Temporary Storage,The system shall store received firmware images in non-volatile storage prior to validation.,,includes(#476)
|
||||
484,Requirements,New,[SR-OTA-006] Active Firmware Protection,The system shall prevent overwriting or execution of the active firmware during firmware reception.,,includes(#476)
|
||||
485,Requirements,New,[SR-OTA-007] Firmware Integrity Verification,The system shall validate the integrity of received firmware images before activation.,,includes(#477)
|
||||
486,Requirements,New,[SR-OTA-008] Firmware Rejection Handling,The system shall reject firmware images that fail integrity validation.,,includes(#477)
|
||||
487,Requirements,New,[SR-OTA-009] OTA Status Reporting,The system shall report firmware validation and OTA status to the Main Hub.,,includes(#477)
|
||||
488,Requirements,New,[SR-OTA-010] OTA Teardown Execution,The system shall execute a controlled teardown procedure prior to firmware activation.,,includes(#478)
|
||||
489,Requirements,New,[SR-OTA-011] Data Persistence Before Flashing,The system shall persist critical runtime data and calibration data before flashing new firmware.,,includes(#478)
|
||||
490,Requirements,New,[SR-OTA-012] Controlled Firmware Activation,The system shall activate new firmware only after successful integrity validation.,,includes(#478)
|
||||
491,Requirements,New,[SR-OTA-013] OTA Reboot Execution,The system shall reboot into the new firmware after successful activation.,,includes(#478)
|
||||
496,Requirements,New,[SR-SEC-001] Firmware Authenticity Verification,The system shall verify the authenticity of the firmware image before execution during every boot cycle.,,includes(#493)
|
||||
497,Requirements,New,[SR-SEC-002] Unauthorized Firmware Blocking,The system shall prevent execution of firmware images that fail cryptographic verification.,,includes(#493)
|
||||
498,Requirements,New,[SR-SEC-003] Secure Boot Failure Handling,The system shall enter a defined security fault state when secure boot verification fails.,,includes(#493)
|
||||
499,Requirements,New,[SR-SEC-004] Root-of-Trust Protection,The system shall protect the root-of-trust against unauthorized modification.,,includes(#493)
|
||||
500,Requirements,New,[SR-SEC-005] Flash Data Access Protection,The system shall protect sensitive data stored in internal flash memory from unauthorized access.,,includes(#494)
|
||||
501,Requirements,New,[SR-SEC-006] Encrypted External Storage,The system shall support encryption of sensitive data stored in external storage devices.,,includes(#494)
|
||||
502,Requirements,New,[SR-SEC-007] Cryptographic Key Isolation,The system shall restrict access to cryptographic keys to authorized system components only.,,includes(#494)
|
||||
503,Requirements,New,[SR-SEC-008] Stored Data Integrity Assurance,"The system shall ensure integrity of stored configuration, calibration, and machine constant data.",,includes(#494)
|
||||
504,Requirements,New,[SR-SEC-009] Encrypted Main Hub Communication,The system shall encrypt all communication exchanged with the Main Hub.,,includes(#495)
|
||||
505,Requirements,New,[SR-SEC-010] Message Integrity and Authenticity,The system shall ensure integrity and authenticity of all transmitted and received messages.,,includes(#495)
|
||||
506,Requirements,New,[SR-SEC-011] Secure OTA Data Transfer,The system shall use encrypted and authenticated communication channels for OTA firmware updates.,,includes(#495)
|
||||
507,Requirements,New,[SR-SEC-012] Security Violation Reporting,The system shall detect and report communication and security violations to the Main Hub.,,includes(#495)
|
||||
513,Requirements,New,[SR-SYS-001] Finite State Machine Control,The system shall implement a defined finite state machine to manage operational states and transitions.,,includes(#509)
|
||||
514,Requirements,New,[SR-SYS-002] State-Based Operation Restriction,The system shall restrict functional operations based on the current system state.,,includes(#509)
|
||||
515,Requirements,New,[SR-SYS-003] State Transition Notification,The system shall notify system components when a system state transition occurs.,,includes(#509)
|
||||
516,Requirements,New,[SR-SYS-004] Controlled Teardown Execution,"The system shall execute a controlled teardown sequence before firmware updates, machine constant updates, or system resets.",,includes(#510)
|
||||
517,Requirements,New,[SR-SYS-005] Critical Data Persistence Before Teardown,The system shall persist all critical runtime data before completing a teardown sequence.,,includes(#510)
|
||||
518,Requirements,New,[SR-SYS-006] Data Integrity Protection During Shutdown,"The system shall prevent data corruption during teardown, reset, or power-down operations.",,includes(#510)
|
||||
519,Requirements,New,[SR-SYS-007] OLED Display Interface,The system shall provide a local OLED display using the I2C communication protocol.,,includes(#511)
|
||||
520,Requirements,New,[SR-SYS-008] System Information Display,"The system shall display connectivity status, system state, connected sensor summary, and time/date on the OLED display.",,includes(#511)
|
||||
521,Requirements,New,[SR-SYS-009] Button-Based Menu Navigation,"The system shall provide menu navigation using Up, Down, and Select buttons.",,includes(#511)
|
||||
522,Requirements,New,[SR-SYS-010] Local Diagnostic and Health Menus,"The system shall provide diagnostic, sensor, and health information through the local OLED menu interface.",,includes(#511)
|
||||
523,Requirements,New,[SR-SYS-011] Diagnostic Session Support,The system shall support diagnostic sessions for retrieving system status and diagnostic data.,,includes(#512)
|
||||
524,Requirements,New,[SR-SYS-012] Debug Session Support,The system shall support debug sessions allowing controlled engineering commands.,,includes(#512)
|
||||
525,Requirements,New,[SR-SYS-013] Authorized Debug Access Control,The system shall restrict debug session actions to authorized engineering access only.,,includes(#512)
|
||||
|
164
curser_plan.md
Normal file
164
curser_plan.md
Normal file
@@ -0,0 +1,164 @@
|
||||
---
|
||||
name: SRS+Architecture Rollout
|
||||
overview: Define a prioritized set of fixes and produce an ISO/IEC/IEEE 29148-style Software Requirements Specification for the full Sensor Hub scope, then derive static architecture views and component-level specifications with traceability back to features and system requirements.
|
||||
todos:
|
||||
- id: fsm-normative
|
||||
content: "Define full FSM: states, transitions, guards, actions; add per-state feature permissions"
|
||||
status: pending
|
||||
- id: fault-model
|
||||
content: Define fault taxonomy + escalation/recovery rules; map DIAG severity to state transitions
|
||||
status: pending
|
||||
dependencies:
|
||||
- fsm-normative
|
||||
- id: srs-setup
|
||||
content: Create ISO/IEC/IEEE 29148 SRS structure and SWR ID scheme; decide where SWR traceability lives (CSV vs MD annex)
|
||||
status: pending
|
||||
dependencies:
|
||||
- fsm-normative
|
||||
- id: derive-swr
|
||||
content: Derive SWR-* from SR-* and features; ensure testability, state preconditions, and trace links
|
||||
status: pending
|
||||
dependencies:
|
||||
- srs-setup
|
||||
- fault-model
|
||||
- id: static-architecture
|
||||
content: Write static architecture views (context/component/data/concurrency) aligned to repo structure and constraints
|
||||
status: pending
|
||||
dependencies:
|
||||
- derive-swr
|
||||
- id: component-specs
|
||||
content: Write component specs/APIs per major component; include threading model, ownership, errors, state behavior
|
||||
status: pending
|
||||
dependencies:
|
||||
- static-architecture
|
||||
- id: vv-matrix
|
||||
content: Create verification matrix mapping SWR-* to unit/integration/HIL tests with acceptance criteria
|
||||
status: pending
|
||||
dependencies:
|
||||
- component-specs
|
||||
---
|
||||
|
||||
# SRS + Static Architecture + Component Design Plan (Sensor Hub)
|
||||
|
||||
## Context and constraints
|
||||
|
||||
- **Scope**: Sensor Hub (Sub-Hub) only; Main Hub/Cloud out of scope except interfaces.
|
||||
- **Source of truth**: Features in `[System Design/Features/](System Design/Features/)`, system requirements in `[System Design/system_requirementsand_and_traceability.csv](System Design/system_requirementsand_and_traceability.csv)`, review gate in `[System Design/System Review Checklist.md](System Design/System Review Checklist.md)`.
|
||||
- **Standard**: **ISO/IEC/IEEE 29148-style SRS** (per your selection).
|
||||
- **Non-negotiables**: reliability > convenience, security mandatory, OTA fail-safe, power loss expected, SD failure assumed.
|
||||
|
||||
## Phase 0 — Close the definition gaps (before writing SW requirements)
|
||||
|
||||
These are blockers because SW requirements must be testable and state-scoped.
|
||||
|
||||
- **Define the full system FSM (normative)**
|
||||
- Produce a complete state set (including missing ones like `BootFailure`, `SdDegraded`, `Service`, etc.) and a **transition table** with guards, actions, and allowed callers.
|
||||
- Tie back to `SR-SYS-001..006` in the CSV.
|
||||
- **Define cross-feature execution rules per state (normative)**
|
||||
- For each feature group (DAQ/DQC/COM/DIAG/DATA/OTA/SEC/SYS), specify **allowed/forbidden actions per state**.
|
||||
- Must satisfy `[System Design/Features/Cross-Feature Constraints.md](System Design/Features/Cross-Feature Constraints.md) `(notably `CFC-ARCH-02`, `CFC-DATA-02`, `CFC-SEC-01/02`, `CFC-DBG-01`).
|
||||
- **Define failure handling model (normative)**
|
||||
- Fault taxonomy (info/warn/error/fatal), escalation rules, latching rules, recovery behaviors.
|
||||
- Link to DIAG requirements `SR-DIAG-*` and SYS state transitions.
|
||||
|
||||
## Phase 1 — Create the SRS (ISO/IEC/IEEE 29148) for full Sensor Hub
|
||||
|
||||
Deliver a dedicated SRS document set that derives **software requirements** from the system requirements CSV.
|
||||
|
||||
- **Create SRS structure** (new docs under `System Design/SRS/`)
|
||||
- `SRS.md` (main), plus annexes for traceability, interfaces, and timing/resource budgets.
|
||||
- **Derive Software Requirements (SWRS) from System Requirements (SR-*)**
|
||||
- For each `SR-*` (CSV), create one or more `SWR-*` that is:
|
||||
- atomic and testable
|
||||
- state-scoped (explicit state preconditions)
|
||||
- implementation-neutral (no “use mutex”, no “use FreeRTOS queue”)
|
||||
- Maintain **bidirectional traceability**: `Feature -> SR -> SWR -> Component -> Test`.
|
||||
- **Mandatory SRS sections (tailored for embedded)**
|
||||
- **Operational states and modes** (normative)
|
||||
- **External interfaces** (Main Hub link, peer link, debug port) (normative)
|
||||
- **Data model** (sensor record, diagnostics record, MC dataset, persistence records) (normative)
|
||||
- **Quality requirements**: timing determinism, memory constraints, storage wear, power-loss behavior, security posture (normative)
|
||||
|
||||
## Phase 2 — Static architecture (architecture views + constraints)
|
||||
|
||||
This converts SRS into implementable structure while enforcing separation of concerns.
|
||||
|
||||
- **Create architecture views** in `[software design/components/ARCHITECTURE.md](software design/components/ARCHITECTURE.md) `(or extend existing `arch.md` but remove non-audited claims):
|
||||
- **Context view**: Sensor Hub and external actors (Main Hub, SD, sensors)
|
||||
- **Container/component view**: align to repo structure under `[software design/components/](software design/components/)`
|
||||
- **Data flow view**: sensor data path, diagnostic path, OTA path
|
||||
- **Concurrency view**: tasks, priorities, ownership of blocking I/O
|
||||
- **Turn constraints into enforceable rules**
|
||||
- Explicitly map each cross-feature constraint to architecture mechanisms (e.g., “DP is sole persistence interface”).
|
||||
|
||||
## Phase 3 — Component specifications (design inputs, not code)
|
||||
|
||||
Produce component-level specs that implement SWRs without ambiguity.
|
||||
|
||||
- **For each major component** (`STM`, `event_system`, `persistence`, `diag_task`, `error_handler`, `sensor_manager`, `machine_constant_manager`, `fw_upgrader`, `main_hub_apis`, `network_stack`, `diag_protocol_stack`):
|
||||
- responsibilities and non-responsibilities
|
||||
- public APIs (C/C++ headers), threading model, owned resources
|
||||
- error model and diagnostics emitted
|
||||
- state dependencies (what each component does per FSM state)
|
||||
- acceptance tests per SWR
|
||||
|
||||
## Phase 4 — Verification planning (definition-level)
|
||||
|
||||
- Create a **V&V matrix** mapping `SWR-*` to:
|
||||
- unit tests, integration tests, HIL/system tests
|
||||
- measurable acceptance criteria (timing, memory, recovery)
|
||||
|
||||
## Initial ordering (what to do first)
|
||||
|
||||
1. FSM + transition table + per-state feature permissions (SYS backbone)
|
||||
2. DP/persistence contract (data integrity backbone)
|
||||
3. Diagnostics + error taxonomy + escalation rules
|
||||
4. COM/OTA/SEC contracts (secure channels, OTA safety)
|
||||
5. DAQ/DQC flow + timing budgets + data model
|
||||
6. HMI/debug session restrictions and isolation
|
||||
|
||||
## Mermaid artifacts to include in the docs
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Init
|
||||
Init --> Running: initOk
|
||||
Init --> BootFailure: secureBootFail
|
||||
Running --> Warning: nonFatalFault
|
||||
Warning --> Running: faultCleared
|
||||
Running --> OtaPrep: otaRequestAccepted
|
||||
OtaPrep --> Teardown: beginTeardown
|
||||
Teardown --> OtaUpdate: teardownComplete
|
||||
OtaUpdate --> Running: otaSuccess
|
||||
OtaUpdate --> Fault: otaFail
|
||||
Running --> Fault: fatalFault
|
||||
Fault --> Teardown: controlledRecovery
|
||||
Teardown --> Init: reboot
|
||||
```
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Sensors-->DriversSensors
|
||||
DriversSensors-->SensorManager
|
||||
SensorManager-->EventSystem
|
||||
EventSystem-->DataPool
|
||||
DataPool-->Persistence
|
||||
DataPool-->MainHubApis
|
||||
EventSystem-->DiagTask
|
||||
DiagTask-->ErrorHandler
|
||||
ErrorHandler-->StateManager
|
||||
```
|
||||
|
||||
## Files that will be created/updated
|
||||
|
||||
- **Create**: `System Design/SRS/SRS.md` (+ annexes) and `System Design/SRS/Traceability_SWRS.csv`
|
||||
- **Update/extend**: `[System Design/system_requirementsand_and_traceability.csv](System Design/system_requirementsand_and_traceability.csv)` to include SWR rows and links (or keep SWR in a dedicated CSV and link by IDs)
|
||||
- **Update/extend**: `[software design/components/ARCHITECTURE.md](software design/components/ARCHITECTURE.md) `/ `arch.md` to reflect audited, testable architecture views
|
||||
- **Create**: per-component specs under `software design/components/*/ARCHITECTURE.md` (or `SPEC.md`) for each major component
|
||||
|
||||
## Deliverables checklist
|
||||
|
||||
- ISO/IEC/IEEE 29148-style **SRS** with `SWR-*` requirements
|
||||
- FSM + transition table + per-state execution rules
|
||||
- Static architecture views (context/component/data/concurrency)
|
||||
- Component specifications + API sketches (headers only, no implementation)
|
||||
- Traceability matrix and initial V&V mapping
|
||||
336
software design/SW design.md
Normal file
336
software design/SW design.md
Normal file
@@ -0,0 +1,336 @@
|
||||
## 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:**
|
||||
|
||||
<br>
|
||||
|
||||
`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)
|
||||
|
||||
<br>
|
||||
|
||||
`@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)
|
||||
|
||||
<br>
|
||||
|
||||
`@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)
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">IEC 61499 Concept</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Sub-Hub Mapping</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Function Block</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Sensor Manager</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Event Interface</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Event System</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Data Interface</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Data Pool</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Resource</p></td><td class="op-uc-table--cell"><p class="op-uc-p">RTOS Task</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Device</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Sub-Hub MCU</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Application</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Application Layer</p></td></tr></tbody></table></figure>
|
||||
|
||||
**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)
|
||||
|
||||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">ISA-95 Level</p></th><th class="op-uc-table--cell op-uc-table--cell_head"><p class="op-uc-p">Sub-Hub Role</p></th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Level 0</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Physical sensors</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Level 1</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Data acquisition</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Level 2</p></td><td class="op-uc-table--cell"><p class="op-uc-p">Local monitoring</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Level 3</p></td><td class="op-uc-table--cell"><p class="op-uc-p">❌ Not included</p></td></tr><tr class="op-uc-table--row"><td class="op-uc-table--cell"><p class="op-uc-p">Level 4</p></td><td class="op-uc-table--cell"><p class="op-uc-p">❌ Not included</p></td></tr></tbody></table></figure>
|
||||
|
||||
**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.
|
||||
548
software design/components/ARCHITECTURE.md
Normal file
548
software design/components/ARCHITECTURE.md
Normal file
@@ -0,0 +1,548 @@
|
||||
# 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<br/>STM]
|
||||
EventSys[Event System]
|
||||
SensorMgr[Sensor Manager]
|
||||
MCMgr[Machine Constant<br/>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<br/>I2C/SPI/UART/ADC]
|
||||
NetworkStack[Network Stack<br/>Wi-Fi/Zigbee/LoRa]
|
||||
DiagProtocol[Diagnostic Protocol<br/>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<br/>Priority: HIGH<br/>Stack: 8KB<br/>Period: 1s"]
|
||||
CommTask["Communication Task<br/>Priority: MEDIUM<br/>Stack: 12KB<br/>Event-driven"]
|
||||
PersistTask["Persistence Task<br/>Priority: MEDIUM<br/>Stack: 6KB<br/>Event-driven"]
|
||||
DiagTask["Diagnostics Task<br/>Priority: LOW<br/>Stack: 4KB<br/>Period: 10s"]
|
||||
HMITask["HMI Task<br/>Priority: LOW<br/>Stack: 4KB<br/>Event-driven"]
|
||||
OTATask["OTA Task<br/>Priority: HIGH<br/>Stack: 16KB<br/>Event-driven"]
|
||||
SystemTask["System Management Task<br/>Priority: HIGH<br/>Stack: 6KB<br/>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
|
||||
346
software design/components/ESP_IDF_FW_wrappers/README.md
Normal file
346
software design/components/ESP_IDF_FW_wrappers/README.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# 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
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/adc.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES driver esp_adc logger
|
||||
)
|
||||
276
software design/components/ESP_IDF_FW_wrappers/adc/README.md
Normal file
276
software design/components/ESP_IDF_FW_wrappers/adc/README.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# 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<int>(config.unit),
|
||||
static_cast<int>(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
|
||||
363
software design/components/ESP_IDF_FW_wrappers/adc/com/adc.cpp
Normal file
363
software design/components/ESP_IDF_FW_wrappers/adc/com/adc.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
/**
|
||||
* @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 <cstring>
|
||||
|
||||
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<AdcUnit>(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<AdcChannel>(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<int32_t>(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<int32_t>(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<adc_unit_t>(unit);
|
||||
}
|
||||
|
||||
adc_channel_t Adc::convertChannel(AdcChannel channel)
|
||||
{
|
||||
return static_cast<adc_channel_t>(channel);
|
||||
}
|
||||
|
||||
adc_atten_t Adc::convertAttenuation(AdcAttenuation atten)
|
||||
{
|
||||
return static_cast<adc_atten_t>(atten);
|
||||
}
|
||||
|
||||
adc_bitwidth_t Adc::convertBitwidth(AdcBitwidth bitwidth)
|
||||
{
|
||||
return static_cast<adc_bitwidth_t>(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<uint8_t>(unit) - 1;
|
||||
}
|
||||
|
||||
uint8_t Adc::getChannelIndex(AdcChannel channel) const
|
||||
{
|
||||
return static_cast<uint8_t>(channel);
|
||||
}
|
||||
261
software design/components/ESP_IDF_FW_wrappers/adc/com/adc.hpp
Normal file
261
software design/components/ESP_IDF_FW_wrappers/adc/com/adc.hpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
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
|
||||
|
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>ADC_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/bt.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES bt nvs_flash logger
|
||||
)
|
||||
502
software design/components/ESP_IDF_FW_wrappers/bt/README.md
Normal file
502
software design/components/ESP_IDF_FW_wrappers/bt/README.md
Normal file
@@ -0,0 +1,502 @@
|
||||
# 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
|
||||
621
software design/components/ESP_IDF_FW_wrappers/bt/com/bt.cpp
Normal file
621
software design/components/ESP_IDF_FW_wrappers/bt/com/bt.cpp
Normal file
@@ -0,0 +1,621 @@
|
||||
/**
|
||||
* @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 <cstring>
|
||||
|
||||
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<esp_ble_addr_type_t>(params.ownAddrType);
|
||||
advParams.peer_addr_type = static_cast<esp_ble_addr_type_t>(params.peerAddrType);
|
||||
memcpy(advParams.peer_addr, params.peerAddr, 6);
|
||||
advParams.channel_map = static_cast<esp_ble_adv_channel_t>(params.channelMap);
|
||||
advParams.adv_filter_policy = static_cast<esp_ble_adv_filter_t>(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<esp_bt_mode_t>(mode);
|
||||
}
|
||||
|
||||
esp_ble_adv_type_t Bluetooth::convertAdvType(BleAdvType advType)
|
||||
{
|
||||
return static_cast<esp_ble_adv_type_t>(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
|
||||
457
software design/components/ESP_IDF_FW_wrappers/bt/com/bt.hpp
Normal file
457
software design/components/ESP_IDF_FW_wrappers/bt/com/bt.hpp
Normal file
@@ -0,0 +1,457 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#include <cstring>
|
||||
#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
|
||||
@@ -0,0 +1,55 @@
|
||||
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
|
||||
|
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/dma.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES driver esp_hw_support logger
|
||||
)
|
||||
396
software design/components/ESP_IDF_FW_wrappers/dma/README.md
Normal file
396
software design/components/ESP_IDF_FW_wrappers/dma/README.md
Normal file
@@ -0,0 +1,396 @@
|
||||
# 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
|
||||
512
software design/components/ESP_IDF_FW_wrappers/dma/com/dma.cpp
Normal file
512
software design/components/ESP_IDF_FW_wrappers/dma/com/dma.cpp
Normal file
@@ -0,0 +1,512 @@
|
||||
/**
|
||||
* @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 <cstring>
|
||||
|
||||
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<DmaDescriptor*>(
|
||||
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<int>(priority);
|
||||
}
|
||||
386
software design/components/ESP_IDF_FW_wrappers/dma/com/dma.hpp
Normal file
386
software design/components/ESP_IDF_FW_wrappers/dma/com/dma.hpp
Normal file
@@ -0,0 +1,386 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
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
|
||||
|
Can't render this file because it has a wrong number of fields in line 30.
|
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>DMA_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/gpio.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES esp_driver_gpio logger
|
||||
)
|
||||
154
software design/components/ESP_IDF_FW_wrappers/gpio/README.md
Normal file
154
software design/components/ESP_IDF_FW_wrappers/gpio/README.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# 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
|
||||
271
software design/components/ESP_IDF_FW_wrappers/gpio/com/gpio.cpp
Normal file
271
software design/components/ESP_IDF_FW_wrappers/gpio/com/gpio.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* @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<gpio_num_t>(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<gpio_num_t>(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<gpio_num_t>(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<gpio_num_t>(pin),
|
||||
reinterpret_cast<gpio_isr_t>(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<gpio_num_t>(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<gpio_num_t>(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<gpio_num_t>(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<gpio_num_t>(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;
|
||||
}
|
||||
}
|
||||
173
software design/components/ESP_IDF_FW_wrappers/gpio/com/gpio.hpp
Normal file
173
software design/components/ESP_IDF_FW_wrappers/gpio/com/gpio.hpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
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
|
||||
|
Can't render this file because it has a wrong number of fields in line 13.
|
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>GPIO_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
idf_component_register(
|
||||
SRCS "com/i2c.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES driver logger
|
||||
|
||||
)
|
||||
216
software design/components/ESP_IDF_FW_wrappers/i2c/README.md
Normal file
216
software design/components/ESP_IDF_FW_wrappers/i2c/README.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# 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
|
||||
273
software design/components/ESP_IDF_FW_wrappers/i2c/com/i2c.cpp
Normal file
273
software design/components/ESP_IDF_FW_wrappers/i2c/com/i2c.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
/**
|
||||
* @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<I2cPort>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<int32_t>(dataLen);
|
||||
}
|
||||
|
||||
int32_t I2c::read(I2cPort port, uint8_t deviceAddress, uint8_t* data, size_t dataLen, uint32_t timeoutMs)
|
||||
{
|
||||
uint8_t portIdx = static_cast<uint8_t>(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<int32_t>(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<uint8_t>(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<int32_t>(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<uint8_t>(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<uint8_t>(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<i2c_mode_t>(config.mode);
|
||||
i2cConfig.sda_io_num = static_cast<gpio_num_t>(config.sdaPin);
|
||||
i2cConfig.scl_io_num = static_cast<gpio_num_t>(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;
|
||||
}
|
||||
183
software design/components/ESP_IDF_FW_wrappers/i2c/com/i2c.hpp
Normal file
183
software design/components/ESP_IDF_FW_wrappers/i2c/com/i2c.hpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
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
|
||||
|
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>I2C_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/spi.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES esp_driver_spi esp_driver_gpio logger
|
||||
)
|
||||
279
software design/components/ESP_IDF_FW_wrappers/spi/README.md
Normal file
279
software design/components/ESP_IDF_FW_wrappers/spi/README.md
Normal file
@@ -0,0 +1,279 @@
|
||||
# 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
|
||||
282
software design/components/ESP_IDF_FW_wrappers/spi/com/spi.cpp
Normal file
282
software design/components/ESP_IDF_FW_wrappers/spi/com/spi.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
/**
|
||||
* @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 <cstring>
|
||||
|
||||
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<SpiHost>(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<uint8_t>(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<gpio_num_t>(config.misoPin), GPIO_PULLUP_ONLY);
|
||||
}
|
||||
if (config.mosiPin >= 0) {
|
||||
gpio_set_pull_mode(static_cast<gpio_num_t>(config.mosiPin), GPIO_PULLUP_ONLY);
|
||||
}
|
||||
if (config.sclkPin >= 0) {
|
||||
gpio_set_pull_mode(static_cast<gpio_num_t>(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<uint8_t>(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<uint8_t>(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<int32_t>(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<int32_t>(length);
|
||||
}
|
||||
|
||||
bool Spi::isInitialized(SpiHost host) const
|
||||
{
|
||||
uint8_t hostIdx = static_cast<uint8_t>(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<uint32_t>(mode);
|
||||
}
|
||||
212
software design/components/ESP_IDF_FW_wrappers/spi/com/spi.hpp
Normal file
212
software design/components/ESP_IDF_FW_wrappers/spi/com/spi.hpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
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
|
||||
|
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>SPI_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/uart.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES esp_driver_uart logger
|
||||
)
|
||||
222
software design/components/ESP_IDF_FW_wrappers/uart/README.md
Normal file
222
software design/components/ESP_IDF_FW_wrappers/uart/README.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# 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
|
||||
293
software design/components/ESP_IDF_FW_wrappers/uart/com/uart.cpp
Normal file
293
software design/components/ESP_IDF_FW_wrappers/uart/com/uart.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
/**
|
||||
* @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 <cstring>
|
||||
#include <inttypes.h>
|
||||
|
||||
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<UartPort>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<int32_t>(bytesAvailable);
|
||||
}
|
||||
|
||||
bool Uart::flushTx(UartPort port)
|
||||
{
|
||||
uint8_t portIdx = static_cast<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint32_t>(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<uint32_t>(baudrate), portIdx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Uart::isInitialized(UartPort port) const
|
||||
{
|
||||
uint8_t portIdx = static_cast<uint8_t>(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<int>(config.baudrate);
|
||||
uartConfig.data_bits = static_cast<uart_word_length_t>(config.dataBits);
|
||||
uartConfig.parity = static_cast<uart_parity_t>(config.parity);
|
||||
uartConfig.stop_bits = static_cast<uart_stop_bits_t>(config.stopBits);
|
||||
uartConfig.flow_ctrl = static_cast<uart_hw_flowcontrol_t>(config.flowControl);
|
||||
uartConfig.rx_flow_ctrl_thresh = 122;
|
||||
uartConfig.source_clk = UART_SCLK_DEFAULT;
|
||||
return uartConfig;
|
||||
}
|
||||
220
software design/components/ESP_IDF_FW_wrappers/uart/com/uart.hpp
Normal file
220
software design/components/ESP_IDF_FW_wrappers/uart/com/uart.hpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
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
|
||||
|
Can't render this file because it contains an unexpected character in line 27 and column 37.
|
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>UART_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/wifi.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES esp_wifi esp_netif nvs_flash logger
|
||||
)
|
||||
323
software design/components/ESP_IDF_FW_wrappers/wifi/README.md
Normal file
323
software design/components/ESP_IDF_FW_wrappers/wifi/README.md
Normal file
@@ -0,0 +1,323 @@
|
||||
# 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
|
||||
501
software design/components/ESP_IDF_FW_wrappers/wifi/com/wifi.cpp
Normal file
501
software design/components/ESP_IDF_FW_wrappers/wifi/com/wifi.cpp
Normal file
@@ -0,0 +1,501 @@
|
||||
/**
|
||||
* @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 <cstring>
|
||||
|
||||
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<WifiAuthMode>(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<wifi_auth_mode_t>(authMode);
|
||||
}
|
||||
|
||||
void Wifi::wifiEventHandler(void* arg, esp_event_base_t eventBase, int32_t eventId, void* eventData)
|
||||
{
|
||||
Wifi* wifi = static_cast<Wifi*>(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<Wifi*>(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
|
||||
306
software design/components/ESP_IDF_FW_wrappers/wifi/com/wifi.hpp
Normal file
306
software design/components/ESP_IDF_FW_wrappers/wifi/com/wifi.hpp
Normal file
@@ -0,0 +1,306 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
#include <cstring>
|
||||
#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
|
||||
@@ -0,0 +1,38 @@
|
||||
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
|
||||
|
Can't render this file because it has a wrong number of fields in line 26.
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>WIFI_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/data_pool.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES logger
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @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 <cstdint>
|
||||
|
||||
/**
|
||||
* @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
|
||||
@@ -0,0 +1,2 @@
|
||||
ID,Component,Level,Criticality,Message
|
||||
4900,DataPool,INFO,Low,DataPool initialized successfully
|
||||
|
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test_scenario>
|
||||
<!-- The configuration for the test environment. -->
|
||||
<!-- Available configurations: SIMULATE, HIL -->
|
||||
<config>SIMULATE</config>
|
||||
|
||||
<test_case>
|
||||
<test_case_id>DATA_POOL_INIT_TEST</test_case_id>
|
||||
<!-- The main command that executes the test itself. -->
|
||||
<test_exec>python components/application_layer/DP_stack/data_pool/test/data_pool_init_test.py</test_exec>
|
||||
</test_case>
|
||||
|
||||
|
||||
</test_scenario>
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @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"
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "com/persistence.cpp"
|
||||
INCLUDE_DIRS "com"
|
||||
REQUIRES logger
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user