Skip to content

Commit

Permalink
🚧 feat(NFC) implement basic FSM handlers drafts
Browse files Browse the repository at this point in the history
  • Loading branch information
polesskiy-dev committed Oct 15, 2024
1 parent 72a765c commit 02b98dc
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ typedef enum {
GLOBAL_CMD_WRITE_SETTINGS = 0xC2, ///< Write settings to the device
GLOBAL_CMD_READ_SETTINGS = 0xC3, ///< Read settings from the device
GLOBAL_CMD_READ_LOG_CHUNK = 0xC4, ///< Read log chunk from the device
GLOBAL_CMD_MAX,
/**
* @brief Global Events in the system
*/
Expand All @@ -49,7 +50,7 @@ typedef enum {
GLOBAL_CMD_SET_WAKE_UP_PERIOD, ///< Set wake up period in seconds
GLOBAL_CMD_START_CONTINUOUS_SENSING, ///< Start continuous sensors measurement
GLOBAL_CMD_TURN_OFF, ///< Turn off to power saving mode
GLOBAL_NFC_MAILBOX_WRITE, ///< NFC mailbox write data event
GLOBAL_CMD_NFC_MAILBOX_WRITE, ///< NFC mailbox write data event
GLOBAL_ERROR,
GLOBAL_EVENTS_MAX,
/**
Expand All @@ -59,7 +60,8 @@ typedef enum {
INFO_LED_FLASH,
// NFC
NFC_GPO_INTERRUPT,
NFC_MAILBOX_HAS_NEW_MESSAGE,
NEW_MAILBOX_RF_CMD,
NFC_CRC_ERROR,
// ACCELEROMETER_SENSOR
// TODO: Add accelerometer events
// TEMPERATURE_HUMIDITY_SENSOR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ uint8_t FAT12_BootSector[FAT12_BOOT_SECTOR_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

// TODO add SETTINGS.DAT file before LOG.DAT
/* Root Directory Area - LBA 3 */

'L', 'O', 'G', ' ', ' ', ' ', ' ', // File name: "LOG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ extern "C" {
#define FAT12_SECTORS (9)
#define FAT12_BOOT_SECTOR_SIZE (FAT12_SECTOR_SIZE * FAT12_SECTORS)

#define SETTINGS_FILE_NAME "settings.bin"
#define SETTINGS_FILE_SIZE (0x1000) // 4KB - 1 erasable sector

#define INITIAL_LOG_START_ADDR (FAT12_BOOT_SECTOR_SIZE + SETTINGS_FILE_SIZE + 1)

#ifdef __cplusplus
}
#endif
Expand Down
7 changes: 6 additions & 1 deletion firmware/iot-risk-logger-stm32l4/app/drivers/sht3x/sht3x.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ SHT3x_IO_t SHT3x_IO = {
.crc8 = NULL
};

static const uint8_t crc8LookupTable[16 * 16] = {
/**
* CRC-8 lookup table,
* CRC-8/NRSC-5 Standard: 0x31
* Polynomial: x^8 + x^5 + x^4 + 1 (0x31)
*/
const uint8_t crc8LookupTable[16 * 16] = {
0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97,
0xb9, 0x88, 0xdb, 0xea, 0x7d, 0x4c, 0x1f, 0x2e,
0x43, 0x72, 0x21, 0x10, 0x87, 0xb6, 0xe5, 0xd4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ERROR: Error state\n\nGLOBAL_ERROR: Error message
[*] --> SLEEP : GLOBAL_CMD_INITIALIZE
SLEEP --> SLEEP : GLOBAL_TEMPERATURE_HUMIDITY_MEASUREMENTS_READY
SLEEP --> SLEEP : GLOBAL_LIGHT_MEASUREMENTS_READY
SLEEP --> SLEEP : GLOBAL_CMD_READ_SETTINGS
SLEEP --> WRITE : MEASUREMENTS_WRITE
WRITE --> SLEEP : GLOBAL_MEASUREMENTS_WRITE_SUCCESS
Expand Down
12 changes: 11 additions & 1 deletion firmware/iot-risk-logger-stm32l4/app/tasks/memory/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static osStatus_t handleMemoryFSM(MEMORY_Actor_t *this, message_t *message) {
uint32_t MEMORY_SeekFreeSpaceAddress(void) {
uint8_t readBuff[MEMORY_LOG_ENTRY_SIZE] = {0};
uint8_t emptyLogEntryTemplate[MEMORY_LOG_ENTRY_SIZE] = {0xFF};
const uint32_t startAddress = FAT12_BOOT_SECTOR_SIZE + 1;
const uint32_t startAddress = INITIAL_LOG_START_ADDR;
const uint8_t stepSize = MEMORY_LOG_ENTRY_SIZE;

uint32_t offset = 0;
Expand Down Expand Up @@ -265,6 +265,16 @@ static osStatus_t handleSleep(MEMORY_Actor_t *this, message_t *message) {
TO_STATE(this, MEMORY_WRITE_STATE);
return ioStatus;

case GLOBAL_CMD_READ_SETTINGS:
// wake up the chip
W25Q_WakeUp(&MEMORY_W25QHandle);

// read settings from the memory
// TODO implement settings read

TO_STATE(this, MEMORY_SLEEP_STATE);
return osOK;

default:
TO_STATE(this, MEMORY_SLEEP_STATE);
return osOK;
Expand Down
23 changes: 19 additions & 4 deletions firmware/iot-risk-logger-stm32l4/app/tasks/nfc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,29 @@ Communication is based by data exchange via *NFC Mailbox* which is 256 bytes buf
Useful payload for now is about 128 bytes. Due to I2C reading from NOR Flash and transferring data to NFC Mailbox, *double buffer* is used in MCU SRAM.

### Protocol Description
#### Request (Command) Mobile -> Device

| Name | Size, bytes | Description | Example |
|------------|------------|------------------------------------------------------------------------------------------------------------------|---------|
| CRC8 | 1 | Checksum | 0xAA |
| Command ID | 1 | Command to process, response duplicates it | 0xC1 |
| Payload size | 1 | Actual data size | 0x04 |
| CRC8 | 1 | Payload checksum | 0xAA |
| Payload | 0...253 | Actual data, for commands it could be address to read or settings<br/> for response it could be e,g chunk of log | 0xAA... |

#### Response Device -> Mobile
| Name | Size, bytes | Description | Example |
|------------------|------------|------------------------------------------------------------------------------------------------------------------|---------|
| CRC8 | 1 | Checksum | 0xAA |
| Response Code ID | 1 | Command to process, response duplicates it | 0xFF |
| Payload size | 1 | Actual data size | 0x04 |
| Payload | 0...253 | Actual data, for commands it could be address to read or settings<br/> for response it could be e,g chunk of log | 0xAA... |

#### Response Codes
| Code | Description |
|------|---------------------|
| 0x00 | ACK (OK) |
| 0xFF | NACK (Error -1) |
| 0xFE | NACK CRC (Error -2) |

### State Diagram

Expand All @@ -39,15 +54,15 @@ ERROR: Error state\n\nGLOBAL_ERROR: Error message
[*] --> STANDBY : GLOBAL_CMD_INITIALIZE
STANDBY --> MAILBOX_RECEIVE_CMD : GPO_INTERRUPT
MAILBOX_RECEIVE_CMD --> VALIDATE_MAILBOX : MAILBOX_READ
MAILBOX_RECEIVE_CMD --> VALIDATE_MAILBOX : NEW_MAILBOX_RF_CMD
VALIDATE_MAILBOX --> MAILBOX_WRITE_RESPONSE: CRC_ERROR
VALIDATE_MAILBOX --> MAILBOX_WRITE_RESPONSE: GLOBAL_CMD_XXX
note on link
Handles globally
CMDs are processed globally
end note
MAILBOX_WRITE_RESPONSE --> STANDBY: GLOBAL_NFC_MAILBOX_WRITE
MAILBOX_WRITE_RESPONSE --> STANDBY: GLOBAL_CMD_NFC_MAILBOX_WRITE
@enduml
```
Expand Down
122 changes: 95 additions & 27 deletions firmware/iot-risk-logger-stm32l4/app/tasks/nfc/nfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
static osStatus_t handleNFCFSM(NFC_Actor_t *this, message_t *message);
static osStatus_t handleInit(NFC_Actor_t *this, message_t *message);
static osStatus_t handleStandby(NFC_Actor_t *this, message_t *message);
static osStatus_t handleMailboxTransmit(NFC_Actor_t *this, message_t *message);
static osStatus_t handleMailboxReceiveCMD(NFC_Actor_t *this, message_t *message);
static osStatus_t handleMailboxValidate(NFC_Actor_t *this, message_t *message);
static osStatus_t handleMailboxWriteResponse(NFC_Actor_t *this, message_t *message);

extern actor_t* ACTORS_LIST_SystemRegistry[MAX_ACTORS];

Expand Down Expand Up @@ -59,8 +61,7 @@ void NFC_Task(void *argument) {
osStatus_t status = NFC_Actor.super.messageHandler((actor_t *) &NFC_Actor, &msg);

if (status != osOK) {
osMessageQueueId_t evManagerQueue = ACTORS_LIST_SystemRegistry[EV_MANAGER_ACTOR_ID]->osMessageQueueId;
osMessageQueuePut(evManagerQueue, &(message_t){GLOBAL_ERROR, .payload.value = NFC_ACTOR_ID}, 0, 0);
osMessageQueuePut(EV_MANAGER_Actor.super.osMessageQueueId, &(message_t){GLOBAL_ERROR, .payload.value = NFC_ACTOR_ID}, 0, 0);
TO_STATE(&NFC_Actor, NFC_STATE_ERROR);
}
}
Expand All @@ -73,27 +74,15 @@ static osStatus_t handleNFCFSM(NFC_Actor_t *this, message_t *message) {
return handleInit(this, message);
case NFC_STANDBY_STATE:
return handleStandby(this, message);
case NFC_MAILBOX_TRANSMIT_STATE:
return handleMailboxTransmit(this, message);
case NFC_MAILBOX_RECEIVE_CMD_STATE:
return handleMailboxReceiveCMD(this, message);
case NFC_VALIDATE_MAILBOX_STATE:
return handleMailboxValidate(this, message);
case NFC_MAILBOX_WRITE_RESPONSE_STATE:
return handleMailboxWriteResponse(this, message);
default:
return osOK;
}

// switch (message->event) {
// case NFC_GPO_INTERRUPT:
// NFC_HandleGPOInterrupt(&st25dv);
// return osOK;
// case NFC_MAILBOX_HAS_NEW_MESSAGE:
// fprintf(stdout, "Mailbox has new message\n");
// NFC_ReadMailboxTo(&st25dv, mailboxBuffer);
// // Print for debug purposes
// for (int i = 0; i < ST25DV_MAX_MAILBOX_LENGTH; i++) {
// fprintf(stdout, "0x%x ", mailboxBuffer[i]);
// }
// return osOK;
// default:
// return osError;
// }
}

static osStatus_t handleInit(NFC_Actor_t *this, message_t *message) {
Expand Down Expand Up @@ -131,25 +120,104 @@ static osStatus_t handleStandby(NFC_Actor_t *this, message_t *message) {
case NFC_GPO_INTERRUPT:
NFC_HandleGPOInterrupt(&this->st25dv);

TO_STATE(this, NFC_MAILBOX_TRANSMIT_STATE);
TO_STATE(this, NFC_MAILBOX_RECEIVE_CMD_STATE);
return osOK;
default:
return osOK;
}
}

static osStatus_t handleMailboxTransmit(NFC_Actor_t *this, message_t *message) {
static osStatus_t handleMailboxReceiveCMD(NFC_Actor_t *this, message_t *message) {
uint8_t *mailboxPayload = NULL;
uint8_t mailboxSize = 0;

switch (message->event) {
case NFC_MAILBOX_HAS_NEW_MESSAGE:
case NEW_MAILBOX_RF_CMD:
NFC_ReadMailboxTo(&this->st25dv, this->mailboxBuffer);

// Print for debug purposes
for (int i = 0; i < ST25DV_MAX_MAILBOX_LENGTH; i++) {
fprintf(stdout, "0x%x ", this->mailboxBuffer[i]);
// TODO validate mailbox CRC8 this->mailboxBuffer
bool isValidCRC8 = true;

if (isValidCRC8) {
// get CMD from read mailbox
event_t cmdEvent = this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_CMD_ADDR];
assert_param(cmdEvent >= GLOBAL_CMD_START_LOGGING && cmdEvent < GLOBAL_EVENTS_MAX);

#ifdef DEBUG
fprintf(stdout, "RF CMD: 0x%x\n", cmdEvent);
#endif

// dispatch received CMD to EV_MANAGER (globally)
mailboxPayload = this->mailboxBuffer + NFC_MAILBOX_PROTOCOL_PAYLOAD_ADDR;
mailboxSize = this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_ADDR];

osMessageQueuePut(EV_MANAGER_Actor.super.osMessageQueueId,
&(message_t){.event = cmdEvent, .payload.ptr = mailboxPayload, .payload_size = mailboxSize}, 0, 0);
}

if (!isValidCRC8) {
osMessageQueuePut(this->super.osMessageQueueId, &(message_t) {NFC_CRC_ERROR}, 0, 0);
}

TO_STATE(this, NFC_VALIDATE_MAILBOX_STATE);
return osOK;
default:
return osOK;
}
}

static osStatus_t handleMailboxValidate(NFC_Actor_t *this, message_t *message) {
if (NFC_CRC_ERROR == message->event) {
osMessageQueuePut(this->super.osMessageQueueId, &(message_t) {GLOBAL_CMD_NFC_MAILBOX_WRITE}, 0, 0);
// TODO: handle CRC error, write e.g. NACK to mailbox
// TODO: maybe put this message as a static?
this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_CRC8_ADDR] = 0xF4; // CRC-8/NRSC-5 Standard from [0xFE, 0x00]
this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_CMD_ADDR] = NFC_RESPONSE_NACK_CRC_ERROR;
this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_ADDR] = 0x00;

TO_STATE(this, NFC_MAILBOX_WRITE_RESPONSE_STATE);
}

// All Commands transmit NFC FSM to the write data to mailbox state
if (message->event >= GLOBAL_CMD_START_LOGGING && message->event < GLOBAL_EVENTS_MAX) {
/**
* @note No events are published here
* NFC module will wait for GLOBAL_CMD_NFC_MAILBOX_WRITE from Event Manager
* as a result of the command processing
*/
// TODO remove it, it's a temporary solution to send only ACK
osMessageQueuePut(this->super.osMessageQueueId, &(message_t) {GLOBAL_CMD_NFC_MAILBOX_WRITE}, 0, 0);

TO_STATE(this, NFC_MAILBOX_WRITE_RESPONSE_STATE);
}

return osOK;
}

static osStatus_t handleMailboxWriteResponse(NFC_Actor_t *this, message_t *message) {
osStatus_t ioStatus = osOK;
uint8_t *payloadData = NULL;

switch (message->event) {
case GLOBAL_CMD_NFC_MAILBOX_WRITE:
// TODO enhance protocol with ACK and ERROR CODES, Error codes could follow HTTP status codes

// TODO copy data from event to mailbox buf
// TODO check utilization f double buffer technique
payloadData = (uint8_t *) message->payload.ptr;
memcpy(this->mailboxBuffer, payloadData, message->payload_size);

// TODO move to a separate "protocol" module
// ST25DV_WriteMailboxData(&this->st25dv, this->mailboxBuffer, ST25DV_MAX_MAILBOX_LENGTH);

// TODO it's a temporary debug solution to send only ACK
this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_CRC8_ADDR] = 0x81; // CRC-8/NRSC-5 Standard from [0x00, 0x00]
this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_CMD_ADDR] = NFC_RESPONSE_ACK_OK;
this->mailboxBuffer[NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_ADDR] = 0x00;

ioStatus = ST25DV_WriteMailboxData(&this->st25dv, this->mailboxBuffer, NFC_MAILBOX_PROTOCOL_HEADER_SIZE);

TO_STATE(this, NFC_STANDBY_STATE);
return ioStatus;
}
}
24 changes: 23 additions & 1 deletion firmware/iot-risk-logger-stm32l4/app/tasks/nfc/nfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,32 @@ extern "C" {
#include "custom_bus.h"
#include "nfc_handlers.h"

/**
* NFC exchange protocol description
* | CRC8 | CMD | Payload Size | Payload |
*/
#define NFC_MAILBOX_PROTOCOL_CRC8_ADDR 0
#define NFC_MAILBOX_PROTOCOL_CRC8_SIZE 1
#define NFC_MAILBOX_PROTOCOL_CMD_ADDR (NFC_MAILBOX_PROTOCOL_CRC8_ADDR + NFC_MAILBOX_PROTOCOL_CRC8_SIZE)
#define NFC_MAILBOX_PROTOCOL_CMD_SIZE 1
#define NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_ADDR (NFC_MAILBOX_PROTOCOL_CMD_ADDR + NFC_MAILBOX_PROTOCOL_CMD_SIZE)
#define NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_SIZE 1
#define NFC_MAILBOX_PROTOCOL_PAYLOAD_ADDR (NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_ADDR + NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_SIZE)
#define NFC_MAILBOX_PROTOCOL_HEADER_SIZE (NFC_MAILBOX_PROTOCOL_CRC8_SIZE + NFC_MAILBOX_PROTOCOL_CMD_SIZE + NFC_MAILBOX_PROTOCOL_PAYLOAD_SIZE_SIZE)

/**
* Exchange protocol response codes
*/
#define NFC_RESPONSE_ACK_OK 0x00
#define NFC_RESPONSE_NACK_ERROR 0xFF
#define NFC_RESPONSE_NACK_CRC_ERROR 0xFE

typedef enum {
NFC_NO_STATE = 0,
NFC_STANDBY_STATE,
NFC_MAILBOX_TRANSMIT_STATE,
NFC_MAILBOX_RECEIVE_CMD_STATE,
NFC_VALIDATE_MAILBOX_STATE,
NFC_MAILBOX_WRITE_RESPONSE_STATE,
NFC_STATE_ERROR,
NFC_MAX_STATE
} NFC_State_t;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <assert.h>
#include "nfc_handlers.h"

int32_t NFC_ST25DVInit(ST25DV_Object_t *pObj) {
Expand Down Expand Up @@ -35,7 +36,7 @@ void NFC_HandleGPOInterrupt(ST25DV_Object_t *pObj) {
uint8_t ITStatus;
ST25DV_ReadITSTStatus_Dyn(pObj, &ITStatus);
if (ITStatus & ST25DV_ITSTS_DYN_RFPUTMSG_MASK) {
osMessageQueuePut(NFC_Actor.super.osMessageQueueId, &(message_t){NFC_MAILBOX_HAS_NEW_MESSAGE}, 0, 0);
osMessageQueuePut(NFC_Actor.super.osMessageQueueId, &(message_t){NEW_MAILBOX_RF_CMD}, 0, 0);

#ifdef DEBUG
fprintf(stdout, "NFC ITStatus: 0x%x\n", ITStatus);
Expand Down
Loading

0 comments on commit 02b98dc

Please sign in to comment.