diff --git a/.vscode/launch.json b/.vscode/launch.json index 48487e4..0e7ddbb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,6 +34,21 @@ "rtos": "FreeRTOS", "swoConfig": { "cpuFrequency": 48000000, "swoFrequency": 875000, "enabled": true, "source": "socket", "decoders": [{"port": 0, "type": "console", "encoding": "ascii", "label": "Output"}]}, }, + { + "cwd": "${workspaceFolder}", + "executable": "${workspaceRoot}/zig-out/firmware/mqtt.elf", + "name": "MQTT App MacOS", + "request": "launch", + "type": "cortex-debug", + "runToEntryPoint": "ResetHandler", + "showDevDebugOutput": "none", + "servertype": "jlink", + "device": "EFM32GG390F1024", + "interface": "swd", + "svdFile": "${workspaceRoot}/src/chips/EFM32GG390F1024.svd", + "rtos": "FreeRTOS", + "swoConfig": { "cpuFrequency": 48000000, "swoFrequency": 875000, "enabled": true, "source": "socket", "decoders": [{"port": 0, "type": "console", "encoding": "ascii", "label": "Output"}]}, + }, { "cwd": "${workspaceRoot}", "executable": "${workspaceRoot}/zig-out/firmware/boot.elf", @@ -67,6 +82,22 @@ "svdFile": "${workspaceRoot}/src/chips/EFM32GG390F1024.svd", "rtos": "FreeRTOS", "swoConfig": { "cpuFrequency": 48000000, "swoFrequency": 875000, "enabled": true, "source": "socket", "decoders": [{"port": 0, "type": "console", "encoding": "ascii", "label": "Output"}]}, + } { + "cwd": "${workspaceRoot}", + "executable": "${workspaceRoot}/zig-out/firmware/mqtt.elf", + "name": "MQTT App WINDOWS", + "request": "launch", + "type": "cortex-debug", + "servertype": "jlink", + "serverpath": "C:\\Program Files\\SEGGER\\JLink\\JLinkGDBServerCL.exe", + "armToolchainPath": "C:\\Program Files (x86)\\Arm GNU Toolchain arm-none-eabi\\12.2 mpacbti-rel1\\bin", + "device": "EFM32GG390F1024", + "interface": "swd", + "runToEntryPoint": "ResetHandler" + "serialNumber": "", // add J-Link serial number if having multiple attached the same time. + "svdFile": "${workspaceRoot}/src/chips/EFM32GG390F1024.svd", + "rtos": "FreeRTOS", + "swoConfig": { "cpuFrequency": 48000000, "swoFrequency": 875000, "enabled": true, "source": "socket", "decoders": [{"port": 0, "type": "console", "encoding": "ascii", "label": "Output"}]}, } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index b33a39d..8148483 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -82,7 +82,14 @@ "__locale": "c", "string": "c", "string_view": "c", - "diskio.h": "c" + "diskio.h": "c", + "array": "c", + "span": "c", + "vector": "c", + "xstring": "c", + "xutility": "c", + "regex": "c", + "xiosbase": "c" }, "cmake.configureOnOpen": false, "cortex-debug.variableUseNaturalFormat": true diff --git a/csrc/board/inc/miso_spi.h b/csrc/board/inc/miso_spi.h index 20cd12e..f8da1ab 100644 --- a/csrc/board/inc/miso_spi.h +++ b/csrc/board/inc/miso_spi.h @@ -1,11 +1,11 @@ /** * @file miso_spi.h * @author Francisco - * @brief + * @brief * @date 2024-03-08 - * + * * @copyright Copyright (c) 2024 - * + * */ #ifndef __MISO_SPI_H__ @@ -13,37 +13,35 @@ #include "miso.h" -/** +/** * @brief Miso Generic SPI error */ -#define MISO_SPI_ERROR ((ssize_t)-127) +#define MISO_SPI_ERROR ((ssize_t)-127) /** * @brief Forward declaration of miso spi device - * + * */ -typedef struct miso_spi_dev_s * miso_spi_t; +typedef struct miso_spi_dev_s* miso_spi_t; /** * @brief Miso SPI send data * * @param dev Miso SPI device - * + * * @param data Data to send - * + * * @param size Size of data to send - * - * @return Number of bytes sent. Negative value on error + * + * @return Number of bytes sent. Negative value on error */ -ssize_t miso_spi_send(miso_spi_t dev, const void * data, size_t nBytes); +ssize_t miso_spi_send(miso_spi_t dev, const void* data, size_t nBytes); /** * @brief Miso SPI receive data - * - * + * + * */ -ssize_t miso_spi_receive(miso_spi_t dev, void * data, size_t nBytes); - - +ssize_t miso_spi_receive(miso_spi_t dev, void* data, size_t nBytes); -#endif // __MISO_SPI_H__ \ No newline at end of file +#endif // __MISO_SPI_H__ \ No newline at end of file diff --git a/csrc/board/src/board.c b/csrc/board/src/board.c index 6f7e0ee..652d5d9 100644 --- a/csrc/board/src/board.c +++ b/csrc/board/src/board.c @@ -116,6 +116,8 @@ void BOARD_Init(void) CMU_ClockEnable(cmuClock_GPIO, true); + CMU_OscillatorEnable(cmuOsc_ULFRCO, true, true); + /* ENABLE SWO */ sl_debug_swo_init(); diff --git a/csrc/board/src/board_CC3100.c b/csrc/board/src/board_CC3100.c index 84f1102..615da29 100644 --- a/csrc/board/src/board_CC3100.c +++ b/csrc/board/src/board_CC3100.c @@ -41,29 +41,34 @@ struct transfer_status_s }; static volatile P_EVENT_HANDLER interrupt_handler_callback = NULL; -static void *interrupt_handler_pValue = NULL; +static volatile void *interrupt_handler_pValue = NULL; + +extern void system_reset(void); static void cc3100_interrupt_callback(uint8_t intNo) { - (void)intNo; // Validate interrupt ? - - if (NULL != interrupt_handler_callback) + if ((uint8_t)WIFI_INT_PIN == intNo) { - interrupt_handler_callback(interrupt_handler_pValue); + if (NULL != interrupt_handler_callback) + { + interrupt_handler_callback(interrupt_handler_pValue); + } } } static void recieve_callback(struct SPIDRV_HandleData *handle, Ecode_t transferStatus, int itemsTransferred) { - (void)handle; // Validate handle ? - struct transfer_status_s transfer_status_information = {.transferStatus = transferStatus, - .itemsTransferred = itemsTransferred}; - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (NULL != rx_queue) + if (handle == &cc3100_usart) { - (void)xQueueSendFromISR(rx_queue, &transfer_status_information, &xHigherPriorityTaskWoken); + struct transfer_status_s transfer_status_information = {.transferStatus = transferStatus, + .itemsTransferred = itemsTransferred}; + + if (NULL != rx_queue) + { + (void)xQueueSendFromISR(rx_queue, &transfer_status_information, &xHigherPriorityTaskWoken); + } } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); @@ -71,15 +76,16 @@ static void recieve_callback(struct SPIDRV_HandleData *handle, Ecode_t transferS static void send_callback(struct SPIDRV_HandleData *handle, Ecode_t transferStatus, int itemsTransferred) { - (void)handle; // Validate handle ? - struct transfer_status_s transfer_status_information = {.transferStatus = transferStatus, - .itemsTransferred = itemsTransferred}; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - if (NULL != tx_queue) + if (handle == &cc3100_usart) { - (void)xQueueSendFromISR(tx_queue, &transfer_status_information, &xHigherPriorityTaskWoken); + struct transfer_status_s transfer_status_information = {.transferStatus = transferStatus, + .itemsTransferred = itemsTransferred}; + if (NULL != tx_queue) + { + (void)xQueueSendFromISR(tx_queue, &transfer_status_information, &xHigherPriorityTaskWoken); + } } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); @@ -170,11 +176,10 @@ void CC3100_DeviceDisable(void) int CC3100_IfOpen(const char *pIfName, unsigned long flags) { - (void)flags; int ret = -1; // Success: FD (positive integer) // Failure: -1 - if (strncmp(pIfName, CC3100_DEVICE_NAME, strlen(CC3100_DEVICE_NAME)) == 0) + if ((strncmp(pIfName, CC3100_DEVICE_NAME, strlen(CC3100_DEVICE_NAME)) == 0) && (flags == 0)) { if (ECODE_OK == SPIDRV_Init(&cc3100_usart, &cc3100_usart_init_data)) { @@ -213,13 +218,13 @@ int CC3100_IfRead(Fd_t Fd, uint8_t *pBuff, int Len) return -1; } - int retVal = -1; - struct transfer_status_s transfer_status = {ECODE_EMDRV_SPIDRV_PARAM_ERROR, 0}; - + int retVal = -1; cc3100_spi_select(); if (rx_queue != NULL) // Change to check if scheduler is active { + struct transfer_status_s transfer_status = {ECODE_EMDRV_SPIDRV_PARAM_ERROR, -1}; + (void)xQueueReset(rx_queue); Ecode_t ecode = SPIDRV_MReceive(&cc3100_usart, pBuff, Len, recieve_callback); @@ -233,11 +238,11 @@ int CC3100_IfRead(Fd_t Fd, uint8_t *pBuff, int Len) { ecode = ECODE_EMDRV_SPIDRV_TIMEOUT; } + } - if (ECODE_EMDRV_SPIDRV_OK == ecode) - { - retVal = transfer_status.itemsTransferred; - } + if (ECODE_EMDRV_SPIDRV_OK == ecode) + { + retVal = transfer_status.itemsTransferred; } } @@ -252,15 +257,15 @@ int CC3100_IfWrite(Fd_t Fd, const uint8_t *pBuff, int Len) return -1; } - int retVal = -1; - struct transfer_status_s transfer_status = {ECODE_EMDRV_SPIDRV_PARAM_ERROR, 0}; + int retVal = -1; cc3100_spi_select(); if (tx_queue != NULL) // Change to check if scheduler is active { - xQueueReset(tx_queue); + struct transfer_status_s transfer_status = {ECODE_EMDRV_SPIDRV_PARAM_ERROR, -1}; + xQueueReset(tx_queue); Ecode_t ecode = SPIDRV_MTransmit(&cc3100_usart, pBuff, Len, send_callback); if (ECODE_EMDRV_SPIDRV_OK == ecode) { @@ -294,8 +299,6 @@ void CC3100_MaskIntHdlr(void) { ; } void CC3100_UnmaskIntHdlr(void) { ; } -extern void system_reset(void); - /* General Event Handler */ void CC3100_GeneralEvtHdlr(SlDeviceEvent_t *slGeneralEvent) { diff --git a/csrc/board/src/board_bma280.c b/csrc/board/src/board_bma280.c index 269c3d2..c48a004 100644 --- a/csrc/board/src/board_bma280.c +++ b/csrc/board/src/board_bma280.c @@ -7,7 +7,6 @@ #include "board_i2c_sensors.h" struct bma2_dev board_bma280; - static uint32_t dummy_val = 0; static BMA2_INTF_RET_TYPE _bma280_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) @@ -15,17 +14,20 @@ static BMA2_INTF_RET_TYPE _bma280_read(uint8_t reg_addr, uint8_t *reg_data, uint (void)intf_ptr; BMA2_INTF_RET_TYPE ret = BMA2_E_COM_FAIL; - I2C_TransferSeq_TypeDef transfer; - transfer.addr = (BMA2_I2C_ADDR1 << 1); - transfer.buf[0].data = ®_addr; - transfer.buf[0].len = 1; - transfer.buf[1].data = reg_data; - transfer.buf[1].len = len; - transfer.flags = I2C_FLAG_WRITE_READ; - - if (i2cTransferDone == board_i2c0_transfer(&transfer)) + if (intf_ptr == &dummy_val) { - ret = BMA2_OK; + I2C_TransferSeq_TypeDef transfer; + transfer.addr = (BMA2_I2C_ADDR1 << 1); + transfer.buf[0].data = ®_addr; + transfer.buf[0].len = 1; + transfer.buf[1].data = reg_data; + transfer.buf[1].len = len; + transfer.flags = I2C_FLAG_WRITE_READ; + + if (i2cTransferDone == board_i2c0_transfer(&transfer)) + { + ret = BMA2_OK; + } } return ret; @@ -33,29 +35,39 @@ static BMA2_INTF_RET_TYPE _bma280_read(uint8_t reg_addr, uint8_t *reg_data, uint static BMA2_INTF_RET_TYPE _bma280_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) { - (void)intf_ptr; BMA2_INTF_RET_TYPE ret = BMA2_E_COM_FAIL; - I2C_TransferSeq_TypeDef transfer; - transfer.addr = (BMA2_I2C_ADDR1 << 1); - transfer.buf[0].data = ®_addr; - transfer.buf[0].len = 1; - transfer.buf[1].data = reg_data; - transfer.buf[1].len = len; - transfer.flags = I2C_FLAG_WRITE_WRITE; - - if (i2cTransferDone == board_i2c0_transfer(&transfer)) + if (intf_ptr == &dummy_val) { - ret = BMA2_OK; + I2C_TransferSeq_TypeDef transfer; + transfer.addr = (BMA2_I2C_ADDR1 << 1); + transfer.buf[0].data = ®_addr; + transfer.buf[0].len = 1; + transfer.buf[1].data = reg_data; + transfer.buf[1].len = len; + transfer.flags = I2C_FLAG_WRITE_WRITE; + + if (i2cTransferDone == board_i2c0_transfer(&transfer)) + { + ret = BMA2_OK; + } } - return ret; } static void _bma280_delay_us(uint32_t period, void *intf_ptr) { - (void)intf_ptr; - BOARD_usDelay(period); + if (intf_ptr == &dummy_val) + { + BOARD_usDelay(period); + } + else + { + while (1) + { + __NOP(); + } + } } void board_bma280_enable(void) diff --git a/csrc/board/src/board_bme280.c b/csrc/board/src/board_bme280.c index 07d2b48..d0efd4a 100644 --- a/csrc/board/src/board_bme280.c +++ b/csrc/board/src/board_bme280.c @@ -9,51 +9,62 @@ struct bme280_dev board_bme280; static uint32_t dummy_val = 0; -static void _bme280_delay_us(uint32_t period, void *intf_ptr) +static void bme280_delay_us(uint32_t period, void *intf_ptr) { - (void)intf_ptr; - BOARD_usDelay(period); + if (intf_ptr == &dummy_val) + { + BOARD_usDelay(period); + } + else + { + while (1) + { + __NOP(); + } + } } -static BME280_INTF_RET_TYPE _bme280_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +static BME280_INTF_RET_TYPE bme280_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) { - (void)intf_ptr; BME280_INTF_RET_TYPE ret = BME280_E_COMM_FAIL; - I2C_TransferSeq_TypeDef transfer; - transfer.addr = (BME280_I2C_ADDR_PRIM << 1); - transfer.buf[0].data = ®_addr; - transfer.buf[0].len = 1; - transfer.buf[1].data = reg_data; - transfer.buf[1].len = len; - transfer.flags = I2C_FLAG_WRITE_READ; - - if (i2cTransferDone == board_i2c0_transfer(&transfer)) + if (intf_ptr == &dummy_val) { - ret = BME280_INTF_RET_SUCCESS; + I2C_TransferSeq_TypeDef transfer; + transfer.addr = (BME280_I2C_ADDR_PRIM << 1); + transfer.buf[0].data = ®_addr; + transfer.buf[0].len = 1; + transfer.buf[1].data = reg_data; + transfer.buf[1].len = len; + transfer.flags = I2C_FLAG_WRITE_READ; + + if (i2cTransferDone == board_i2c0_transfer(&transfer)) + { + ret = BME280_INTF_RET_SUCCESS; + } } return ret; } -static BME280_INTF_RET_TYPE _bme280_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) +static BME280_INTF_RET_TYPE bme280_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) { - (void)intf_ptr; BME280_INTF_RET_TYPE ret = BME280_E_COMM_FAIL; - - I2C_TransferSeq_TypeDef transfer; - transfer.addr = (BME280_I2C_ADDR_PRIM << 1); - transfer.buf[0].data = ®_addr; - transfer.buf[0].len = 1; - transfer.buf[1].data = reg_data; - transfer.buf[1].len = len; - transfer.flags = I2C_FLAG_WRITE_WRITE; - - if (i2cTransferDone == board_i2c0_transfer(&transfer)) + if (intf_ptr == &dummy_val) { - ret = BME280_INTF_RET_SUCCESS; - } + I2C_TransferSeq_TypeDef transfer; + transfer.addr = (BME280_I2C_ADDR_PRIM << 1); + transfer.buf[0].data = ®_addr; + transfer.buf[0].len = 1; + transfer.buf[1].data = reg_data; + transfer.buf[1].len = len; + transfer.flags = I2C_FLAG_WRITE_WRITE; + if (i2cTransferDone == board_i2c0_transfer(&transfer)) + { + ret = BME280_INTF_RET_SUCCESS; + } + } return ret; } @@ -61,9 +72,9 @@ void board_bme280_enable(void) { board_bme280.intf_ptr = &dummy_val; board_bme280.intf = BME280_I2C_INTF; - board_bme280.delay_us = _bme280_delay_us; - board_bme280.read = _bme280_read; - board_bme280.write = _bme280_write; + board_bme280.delay_us = bme280_delay_us; + board_bme280.read = bme280_read; + board_bme280.write = bme280_write; GPIO_PinModeSet(VDD_BME280_PORT, VDD_BME280_PIN, VDD_BME280_MODE, 1); BOARD_msDelay(10); diff --git a/csrc/board/src/board_bmm150.c b/csrc/board/src/board_bmm150.c index 8cf0ca7..59890b8 100644 --- a/csrc/board/src/board_bmm150.c +++ b/csrc/board/src/board_bmm150.c @@ -12,26 +12,36 @@ uint32_t bmm150_intf_val = 0; static void _bmm150_delay_us(uint32_t period, void *intf_ptr) { - (void)intf_ptr; - BOARD_usDelay(period); + if (intf_ptr == &bmm150_intf_val) + { + BOARD_usDelay(period); + } + else + { + while (1) + { + __NOP(); + } + } } static BMM150_INTF_RET_TYPE _bmm150_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) { - (void)intf_ptr; BMM150_INTF_RET_TYPE ret = BMM150_E_COM_FAIL; - - I2C_TransferSeq_TypeDef transfer; - transfer.addr = (BMM150_DEFAULT_I2C_ADDRESS << 1); - transfer.buf[0].data = ®_addr; - transfer.buf[0].len = 1; - transfer.buf[1].data = reg_data; - transfer.buf[1].len = length; - transfer.flags = I2C_FLAG_WRITE_READ; - - if (i2cTransferDone == board_i2c0_transfer(&transfer)) + if (intf_ptr == &bmm150_intf_val) { - ret = BMM150_INTF_RET_SUCCESS; + I2C_TransferSeq_TypeDef transfer; + transfer.addr = (BMM150_DEFAULT_I2C_ADDRESS << 1); + transfer.buf[0].data = ®_addr; + transfer.buf[0].len = 1; + transfer.buf[1].data = reg_data; + transfer.buf[1].len = length; + transfer.flags = I2C_FLAG_WRITE_READ; + + if (i2cTransferDone == board_i2c0_transfer(&transfer)) + { + ret = BMM150_INTF_RET_SUCCESS; + } } return ret; @@ -42,19 +52,21 @@ static BMM150_INTF_RET_TYPE _bmm150_write(uint8_t reg_addr, const uint8_t *reg_d (void)intf_ptr; BMM150_INTF_RET_TYPE ret = BMM150_E_COM_FAIL; - I2C_TransferSeq_TypeDef transfer; - transfer.addr = (BMM150_DEFAULT_I2C_ADDRESS << 1); - transfer.buf[0].data = ®_addr; - transfer.buf[0].len = 1; - transfer.buf[1].data = reg_data; - transfer.buf[1].len = length; - transfer.flags = I2C_FLAG_WRITE_WRITE; - - if (i2cTransferDone == board_i2c0_transfer(&transfer)) + if (intf_ptr == &bmm150_intf_val) { - ret = BMM150_INTF_RET_SUCCESS; - } + I2C_TransferSeq_TypeDef transfer; + transfer.addr = (BMM150_DEFAULT_I2C_ADDRESS << 1); + transfer.buf[0].data = ®_addr; + transfer.buf[0].len = 1; + transfer.buf[1].data = reg_data; + transfer.buf[1].len = length; + transfer.flags = I2C_FLAG_WRITE_WRITE; + if (i2cTransferDone == board_i2c0_transfer(&transfer)) + { + ret = BMM150_INTF_RET_SUCCESS; + } + } return ret; } diff --git a/csrc/board/src/board_sd_card.c b/csrc/board/src/board_sd_card.c index 6d8ab1d..2ad84dd 100644 --- a/csrc/board/src/board_sd_card.c +++ b/csrc/board/src/board_sd_card.c @@ -26,6 +26,12 @@ static void card_detect_callback(uint8_t intNo); static SemaphoreHandle_t tx_semaphore = NULL; static SemaphoreHandle_t rx_semaphore = NULL; +struct transfer_status_s +{ + Ecode_t transferStatus; // status + int itemsTransferred; // items_transferred +}; + uint32_t BOARD_SD_CARD_IsInserted(void) { return (0 == GPIO_PinInGet(SD_DETECT_PORT, SD_DETECT_PIN)) ? (uint32_t)UINT32_C(1) : (uint32_t)UINT32_C(0); @@ -123,7 +129,10 @@ static void recieve_callback(struct SPIDRV_HandleData *handle, Ecode_t transferS BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (NULL != rx_semaphore) xQueueSendFromISR(rx_semaphore, &transferStatus, &xHigherPriorityTaskWoken); + if (handle == &sd_card_usart) + { + if (NULL != rx_semaphore) xQueueSendFromISR(rx_semaphore, &transferStatus, &xHigherPriorityTaskWoken); + } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } @@ -131,12 +140,14 @@ static void recieve_callback(struct SPIDRV_HandleData *handle, Ecode_t transferS /* tx callback for async tx */ static void send_callback(struct SPIDRV_HandleData *handle, Ecode_t transferStatus, int itemsTransferred) { - (void)handle; (void)itemsTransferred; BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (NULL != tx_semaphore) xQueueSendFromISR(tx_semaphore, &transferStatus, &xHigherPriorityTaskWoken); + if (handle == &sd_card_usart) + { + if (NULL != tx_semaphore) xQueueSendFromISR(tx_semaphore, &transferStatus, &xHigherPriorityTaskWoken); + } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } diff --git a/csrc/board/src/board_watchdog.c b/csrc/board/src/board_watchdog.c index 7e46b03..9a5dc68 100644 --- a/csrc/board/src/board_watchdog.c +++ b/csrc/board/src/board_watchdog.c @@ -13,9 +13,9 @@ void BOARD_Watchdog_Init(void) { WDOG_Init_TypeDef wdog_init = WDOG_INIT_DEFAULT; - wdog_init.clkSel = wdogClkSelLFXO; + wdog_init.clkSel = wdogClkSelULFRCO; wdog_init.debugRun = false; // When in debug mode, the watchdog is disabled. - wdog_init.perSel = wdogPeriod_256k; //(7s) + wdog_init.perSel = wdogPeriod_8k; //(8s) wdog_init.lock = false; wdog_init.enable = false; wdog_init.em2Run = false; diff --git a/src/config.zig b/src/config.zig index 1fb8790..38ef071 100644 --- a/src/config.zig +++ b/src/config.zig @@ -45,7 +45,7 @@ pub const rtos_prio_lwm2m = @intFromEnum(task_priorities.rtos_prio_above_normal) pub const rtos_stack_depth_lwm2m: u16 = if (enable_lwm2m) 2000 else min_task_stack_depth; // MQTT -pub const rtos_prio_mqtt = @intFromEnum(task_priorities.rtos_prio_normal); +pub const rtos_prio_mqtt = @intFromEnum(task_priorities.rtos_prio_above_normal); pub const rtos_stack_depth_mqtt: u16 = if (enable_mqtt) 1600 else min_task_stack_depth; pub const rtos_prio_user_task = @intFromEnum(task_priorities.rtos_prio_below_normal); diff --git a/src/freertos.zig b/src/freertos.zig index f9587e1..e4b6a23 100644 --- a/src/freertos.zig +++ b/src/freertos.zig @@ -158,6 +158,9 @@ pub fn StaticTask(comptime T: type, comptime stackSize: usize, comptime pcName: pub inline fn getHandle(self: *const @This()) TaskHandle_t { return self.task.getHandle(); } + pub inline fn getTickCount(self: *const @This()) TickType_t { + return self.task.getTickCount(); + } }; } @@ -256,6 +259,12 @@ pub const Task = struct { _ = self; c.vTaskDelay(xTicksToDelay); } + + /// Get the current tick time + pub inline fn getTickCount(self: *const @This()) TickType_t { + _ = self; + return c.xTaskGetTickCount(); + } }; pub fn StaticBinarySemaphore() type { diff --git a/src/mqtt.zig b/src/mqtt.zig index c1f9551..b7261f2 100644 --- a/src/mqtt.zig +++ b/src/mqtt.zig @@ -92,11 +92,12 @@ const fw_update_topic = "zig/fw"; const conf_update_topic = "zig/conf"; const reset_topic = "zig/reset"; -const connectionType = connection.Connection(mbedtls.TlsContext(@This(), simpleConnection.SimpleLinkConnection(.no_protocol), .psk)); +const connectionType = connection.Connection(mbedtls.TlsContext(@This(), simpleConnection.SimpleLinkConnection(.tls_ip4), .psk)); connection: connectionType, connectionCounter: usize, disconnectionCounter: usize, +pingCounter: usize, pingTimer: freertos.StaticTimer(@This(), "pingTimer", pingTimer), pubTimer: freertos.StaticTimer(@This(), "pubTimer", pubTimer), @@ -113,27 +114,31 @@ qosQueue: QueuedMessgeQueue, /// QoS2 rx queue qos2Queue: QueuedMessgeQueue, +/// Ping message queue +pingQueue: freertos.StaticQueue(freertos.TickType_t, 1), + var txBuffer: [256]u8 align(@alignOf(u32)) = undefined; var rxBuffer: [512]u8 align(@alignOf(u32)) = undefined; var workBuffer: [256]u8 align(@alignOf(u32)) = undefined; /// Init a MQTT String using slice. /// Has been tested in comptime -inline fn initMQTTString(data: []const u8) MQTTString { - return MQTTString{ .cstring = null, .lenstring = .{ .len = @intCast(data.len), .data = @constCast(data.ptr) } }; -} - -/// Init a MQTT String using a pointer and asuming a 0-terminated C-String -inline fn initMQTTCstring(data: [*:0]u8) MQTTString { - return MQTTString{ .cstring = @ptrCast(data), .lenstring = .{ .len = 0, .data = null } }; +inline fn initMQTTString(data: ?[]const u8) MQTTString { + if (data) |val| { + return MQTTString{ .cstring = null, .lenstring = .{ .len = @intCast(val.len), .data = @constCast(val.ptr) } }; + } else { + return MQTTString_initializer; + } } /// Get MQTT String as slice inline fn getMQTTString(data: MQTTString) []u8 { if (data.cstring) |cstring| { return cstring[0..c.strlen(cstring)]; - } else { + } else if ((data.lenstring.data != null) and (data.lenstring.len > 0)) { return data.lenstring.data[0..@intCast(data.lenstring.len)]; + } else { + return undefined; } } @@ -146,11 +151,13 @@ fn init() @This() { .pubTimer = undefined, .task = undefined, .state = .not_connected, - .packet = packet.init(0x5555), + .packet = packet.init(), .uri_string = undefined, .device_id = undefined, .qosQueue = QueuedMessgeQueue.init(freertos.allocator), .qos2Queue = QueuedMessgeQueue.init(freertos.allocator), + .pingCounter = 0, + .pingQueue = undefined, }; } @@ -176,7 +183,20 @@ fn processSendQueue(self: *@This()) !void { } /// Quality of Service -const QoS = enum(c_int) { qos0 = 0, qos1 = 1, qos2 = 2 }; +const QoS = enum(c_int) { + qos0 = 0, + qos1 = 1, + qos2 = 2, + + fn fromInt(x: c_int) !QoS { + return switch (x) { + 0 => .qos0, + 1 => .qos1, + 2 => .qos2, + else => mqtt_error.qos_not_supported, + }; + } +}; /// Queued message const QueuedMessage = struct { @@ -281,7 +301,7 @@ const packet = struct { payload: []u8, }; - pub fn init(comptime packetId: u16) @This() { + pub fn init() @This() { return @This(){ .transport = .{ .getfn = getFn, .sck = undefined, @@ -289,7 +309,7 @@ const packet = struct { .rem_len = undefined, .len = undefined, .state = undefined, - }, .packetIdState = packetId, .workBufferMutex = undefined, .txQueue = undefined }; + }, .packetIdState = 1, .workBufferMutex = undefined, .txQueue = undefined }; } pub fn create(self: *@This(), conn: *connectionType) void { @@ -300,7 +320,8 @@ const packet = struct { self.txQueue.create() catch unreachable; // Create message buffer } - /// Generate Packet ID + /// Generate Packet ID using pseudo random number generator + /// /// Uses XorShift Algorithm to generate the packet id fn generatePacketId(self: *@This()) u16 { if (self.packetIdState != 0) { @@ -333,7 +354,7 @@ const packet = struct { } /// Deserialize a publish packet from buffer and converts it into a `publish_response` - fn deserializePublish(self: *@This(), buffer: []u8) !publish_response { + fn deserializePublish(self: *@This(), buffer: []const u8) !publish_response { _ = self; var topicName = MQTTString_initializer; var payload: [*c]u8 = undefined; @@ -343,27 +364,22 @@ const packet = struct { var dup: u8 = undefined; var qos: c_int = undefined; - if (mqtt_ok != c.MQTTDeserialize_publish(&dup, &qos, &retained, &packetId, &topicName, &payload, &payloadLen, buffer.ptr, @intCast(buffer.len))) { + if (mqtt_ok != c.MQTTDeserialize_publish(&dup, &qos, &retained, &packetId, &topicName, &payload, &payloadLen, @constCast(buffer.ptr), @intCast(buffer.len))) { return mqtt_error.parse_failed; } - const retQos: QoS = switch (qos) { - 0 => .qos0, - 1 => .qos1, - 2 => .qos2, - else => return mqtt_error.qos_not_supported, - }; + const retQos = try QoS.fromInt(qos); return publish_response{ .packetId = packetId, .qos = retQos, .dup = (if (dup == 0) false else true), .retained = (if (retained == 0) false else true), .topic = getMQTTString(topicName), .payload = payload[0..@intCast(payloadLen)] }; } - fn deserializePuback(self: *@This(), buffer: []u8) !struct { packetId: u16, dup: bool } { + fn deserializePuback(self: *@This(), buffer: []const u8) !struct { packetId: u16, dup: bool } { _ = self; var packetId: u16 = undefined; var dup: u8 = undefined; var packetType: u8 = undefined; - if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @ptrCast(&buffer[0]), @intCast(buffer.len))) { + if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @constCast(buffer.ptr), @intCast(buffer.len))) { return mqtt_error.parse_failed; } if (packetType != c.PUBACK) { @@ -373,13 +389,13 @@ const packet = struct { } /// Deserialize a pubrel packet from buffer - fn deserializePubrel(self: *@This(), buffer: []u8) !struct { packetId: u16, dup: bool } { + fn deserializePubrel(self: *@This(), buffer: []const u8) !struct { packetId: u16, dup: bool } { _ = self; var packetId: u16 = undefined; var dup: u8 = undefined; var packetType: u8 = undefined; - if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @ptrCast(&buffer[0]), @intCast(buffer.len))) { + if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @constCast(buffer.ptr), @intCast(buffer.len))) { return mqtt_error.parse_failed; } if (packetType != c.PUBREL) { @@ -389,13 +405,13 @@ const packet = struct { } /// Deserialize a pubrec packet from buffer - fn deserializePubrec(self: *@This(), buffer: []u8) !u16 { + fn deserializePubrec(self: *@This(), buffer: []const u8) !u16 { _ = self; var packetId: u16 = undefined; var dup: u8 = undefined; var packetType: u8 = undefined; - if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @ptrCast(&buffer[0]), @intCast(buffer.len))) { + if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @constCast(buffer.ptr), @intCast(buffer.len))) { return mqtt_error.parse_failed; } if (packetType != c.PUBREC) { @@ -406,13 +422,13 @@ const packet = struct { } /// Deserialize a pubcomp packet from buffer - fn deserializePubcomp(self: *@This(), buffer: []u8) !u16 { + fn deserializePubcomp(self: *@This(), buffer: []const u8) !u16 { _ = self; var packetId: u16 = undefined; var dup: u8 = undefined; var packetType: u8 = undefined; - if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @ptrCast(&buffer[0]), @intCast(buffer.len))) { + if (mqtt_ok != c.MQTTDeserialize_ack(&packetType, &dup, &packetId, @constCast(buffer.ptr), @intCast(buffer.len))) { return mqtt_error.parse_failed; } if (packetType != c.PUBCOMP) { @@ -423,12 +439,12 @@ const packet = struct { } /// Deserialize a suback packet from buffer - fn deserializeSubAck(self: *@This(), buffer: []u8, qos: []QoS) !struct { packetId: u16, qos: []QoS } { + fn deserializeSubAck(self: *@This(), buffer: []const u8, qos: []QoS) !struct { packetId: u16, qos: []QoS } { _ = self; var packetId: u16 = undefined; var count: c_int = 0; - if (mqtt_ok != c.MQTTDeserialize_suback(&packetId, @intCast(qos.len), &count, @ptrCast(qos.ptr), @ptrCast(buffer.ptr), @intCast(buffer.len))) { + if (mqtt_ok != c.MQTTDeserialize_suback(&packetId, @intCast(qos.len), &count, @ptrCast(qos.ptr), @constCast(buffer.ptr), @intCast(buffer.len))) { return mqtt_error.parse_failed; } return .{ .packetId = packetId, .qos = qos[0..@as(usize, @intCast(count))] }; @@ -451,14 +467,8 @@ const packet = struct { var connectPacket = MQTTPacket_connectData_initializer; connectPacket.clientID = initMQTTString(clientID); - if (username) |un| { - connectPacket.username = initMQTTString(un); - } - - if (password) |pw| { - connectPacket.password = initMQTTString(pw); - } - + connectPacket.username = initMQTTString(username); + connectPacket.password = initMQTTString(password); connectPacket.keepAliveInterval = 400; _ = try self.workBufferMutex.take(null); @@ -571,6 +581,9 @@ fn loop(self: *@This(), uri: std.Uri) !void { defer self.disconnect() catch {}; while (true) { + const current_cycle_time = freertos.xTaskGetTickCount(); // Get current cycle time + _ = current_cycle_time; + // process the QoS1 tx queue while (self.qosQueue.prune()) |msg| { switch (msg.packetType) { @@ -595,7 +608,8 @@ fn loop(self: *@This(), uri: std.Uri) !void { try self.processSendQueue(); - if (self.connection.waitRx(1) catch false) { + // Think if I make this into a while + while (self.connection.waitRx(1) catch false) { var readRet = self.packet.read(&rxBuffer); switch (readRet) { .try_again => {}, @@ -648,7 +662,9 @@ fn loop(self: *@This(), uri: std.Uri) !void { } }, .pingresp => { - _ = c.printf("pingresp!\r\n"); + const ping_timestamp = self.pingQueue.recieve(0).?; + + _ = c.printf("pingresp! %d, %d\r\n", self.pingCounter, ping_timestamp); }, .connack => try self.packet.processConnAck(&rxBuffer), .connect, .subscribe, .disconnect, .unsubscribe, .pingreq => break, // Broker messages @@ -715,7 +731,7 @@ fn loop(self: *@This(), uri: std.Uri) !void { if (false == try self.qosQueue.acknowledge(resp, .pubrel)) { return mqtt_error.pubrel_packet_not_found; } else { - _ = c.printf("pubcomp received for packetId\r\n", resp); + _ = c.printf("pubcomp received for packetId %d\r\n", resp); } }, .err_msg => break, @@ -735,6 +751,8 @@ fn taskFunction(self: *@This()) noreturn { self.connectionCounter = 0; self.disconnectionCounter = 0; + self.pingCounter = 0; + self.pingQueue.create() catch unreachable; self.uri_string = c.config_get_mqtt_url(); self.device_id = c.config_get_mqtt_device_id(); @@ -745,6 +763,7 @@ fn taskFunction(self: *@This()) noreturn { self.loop(uri) catch |err| { if (err == connection.connection_error.create_error) { + self.pingQueue.reset(); self.task.delayTask(1000); } _ = c.printf("Disconnected... reconnect: %d. %d \r\n", self.connectionCounter, @intFromError(err)); @@ -761,6 +780,11 @@ fn dummyTaskFunction(self: *@This()) noreturn { } fn pingTimer(self: *@This()) void { + const curr_tick = self.task.getTickCount(); + + self.pingQueue.send(&curr_tick, 0) catch unreachable; + self.pingCounter += 1; + _ = self.packet.preparePingPacket() catch unreachable; } @@ -838,6 +862,7 @@ pub fn connect(self: *@This(), uri: std.Uri) !void { pub fn disconnect(self: *@This()) !void { self.pingTimer.stop(null) catch {}; + self.pubTimer.stop(null) catch {}; defer { self.connection.close() catch {}; self.disconnectionCounter += 1;