diff --git a/Core/Inc/NVmem.h b/Core/Inc/NVmem.h new file mode 100644 index 0000000..3af5312 --- /dev/null +++ b/Core/Inc/NVmem.h @@ -0,0 +1,29 @@ +/** +********************************************************************* +* +* @file NVmem.h +* @brief +* +* @date 2024-07-13 12:24:17 +* @author CT +* +* @details +* +************************************************************************* +**/ + +#ifndef _NVMEM_H_ +#define _NVMEM_H_ + +#include + +#define WRITE_TIMEOUT (6000u) // 6s +#define NVMEM_SIZE (2048u) // in bytes + +int32_t NVmem_init(void); +void NVmem_service(void); +int32_t NVmem_write(uint8_t* data, uint32_t addr, uint32_t len); +int32_t NVmem_write_immediate(uint8_t* data, uint32_t addr, uint32_t len); +int32_t NVmem_read(uint8_t* data, uint32_t addr, uint32_t len); + +#endif // _NVMEM_H_ \ No newline at end of file diff --git a/Core/Inc/cir_buf.h b/Core/Inc/cir_buf.h index 1858cfd..3c90015 100644 --- a/Core/Inc/cir_buf.h +++ b/Core/Inc/cir_buf.h @@ -16,6 +16,78 @@ #ifndef _CIR_BUF_H_ #define _CIR_BUF_H_ +#include +#include +#include + +/// Opaque circular buffer structure +typedef struct circular_buf_t circular_buf_t; + +/// Handle type, the way users interact with the API +typedef circular_buf_t* cbuf_handle_t; + +/// Pass in a storage buffer and size, returns a circular buffer handle +/// Requires: buffer is not NULL, size > 0 (size > 1 for the threadsafe +// version, because it holds size - 1 elements) +/// Ensures: me has been created and is returned in an empty state +cbuf_handle_t circular_buf_init(uint8_t* buffer, size_t size); + +/// Free a circular buffer structure +/// Requires: me is valid and created by circular_buf_init +/// Does not free data buffer; owner is responsible for that +void circular_buf_free(cbuf_handle_t me); + +/// Reset the circular buffer to empty, head == tail. Data not cleared +/// Requires: me is valid and created by circular_buf_init +void circular_buf_reset(cbuf_handle_t me); + +/// Put that continues to add data if the buffer is full +/// Old data is overwritten +/// Note: if you are using the threadsafe version, this API cannot be used, because +/// it modifies the tail pointer in some cases. Use circular_buf_try_put instead. +/// Requires: me is valid and created by circular_buf_init +void circular_buf_put(cbuf_handle_t me, uint8_t data); + +/// Put that rejects new data if the buffer is full +/// Note: if you are using the threadsafe version, *this* is the put you should use +/// Requires: me is valid and created by circular_buf_init +/// Returns 0 on success, -1 if buffer is full +int circular_buf_try_put(cbuf_handle_t me, uint8_t data); + +/// Retrieve a value from the buffer +/// Requires: me is valid and created by circular_buf_init +/// Returns 0 on success, -1 if the buffer is empty +int circular_buf_get(cbuf_handle_t me, uint8_t* data); + +/// Checks if the buffer is empty +/// Requires: me is valid and created by circular_buf_init +/// Returns true if the buffer is empty +bool circular_buf_empty(cbuf_handle_t me); + +/// Checks if the buffer is full +/// Requires: me is valid and created by circular_buf_init +/// Returns true if the buffer is full +bool circular_buf_full(cbuf_handle_t me); + +/// Check the capacity of the buffer +/// Requires: me is valid and created by circular_buf_init +/// Returns the maximum capacity of the buffer +size_t circular_buf_capacity(cbuf_handle_t me); + +/// Check the number of elements stored in the buffer +/// Requires: me is valid and created by circular_buf_init +/// Returns the current number of elements in the buffer +size_t circular_buf_size(cbuf_handle_t me); + +/// Look ahead at values stored in the circular buffer without removing the data +/// Requires: +/// - me is valid and created by circular_buf_init +/// - look_ahead_counter is less than or equal to the value returned by circular_buf_size() +/// Returns 0 if successful, -1 if data is not available +int circular_buf_peek(cbuf_handle_t me, uint8_t* data, unsigned int look_ahead_counter); + +// TODO: int circular_buf_get_range(circular_buf_t me, uint8_t *data, size_t len); +// TODO: int circular_buf_put_range(circular_buf_t me, uint8_t * data, size_t len); #endif /* _CIR_BUF_H_ */ \ No newline at end of file diff --git a/Core/Inc/console.h b/Core/Inc/console.h new file mode 100644 index 0000000..832c268 --- /dev/null +++ b/Core/Inc/console.h @@ -0,0 +1,25 @@ +/** +********************************************************************* +* +* @file console.h +* @brief +* +* @date 2024-04-14 19:12:40 +* @author CT +* +* @details +* +************************************************************************* +**/ + +#ifndef _CONSOLE_H_ +#define _CONSOLE_H_ + +#include "cir_buf.h" + +void console_init(void); +void console_service(void); +int console_push(uint8_t data); + + +#endif // _CONOSLE_H_ \ No newline at end of file diff --git a/Core/Inc/version.h b/Core/Inc/version.h new file mode 100644 index 0000000..bb412de --- /dev/null +++ b/Core/Inc/version.h @@ -0,0 +1,11 @@ +#ifndef _VERSION_H_ +#define _VERSION_H_ + +#define MAJOR_VERSION 0 +#define MINOR_VERSION 0 +#define PATCH_VERSION 1 + +#define VERSION_STR "0.0.1" + + +#endif // _VERSION_H_ \ No newline at end of file diff --git a/Core/Src/NVmem.c b/Core/Src/NVmem.c new file mode 100644 index 0000000..0496d3e --- /dev/null +++ b/Core/Src/NVmem.c @@ -0,0 +1,176 @@ +/** +********************************************************************* +* +* @file NVmem.c +* @brief +* +* @date 2024-07-13 12:24:17 +* @author CT +* +* @details Provides an interface for reading and writting to non-volatile memory +* Operates with a shadow buffer and write timeout to minimize writes to NV-memory +* +************************************************************************* +**/ + +#include + +#include "stm32g0xx_hal.h" + +#include "NVmem.h" + +// write timeout +static uint32_t m_last_write = 0; +// +static int32_t m_shadow_buf_synced = 0; +// +static uint8_t m_shadow_buf[NVMEM_SIZE] = {0}; +// non-volatile memory location +uint8_t __attribute__((section (".ConfigData"))) config_data[NVMEM_SIZE] __attribute__ ((aligned (2048))); + + +static int write_flash(void); + +int32_t NVmem_init(void) +{ + // copy flash to shadow buffer + for (uint32_t i = 0; i < NVMEM_SIZE; i++) + { + m_shadow_buf[i] = config_data[i]; + } + + return (0); +} + +void NVmem_service(void) +{ + // if the write timeout has expried and the shadow buffer has not been synced to NVmem + if (((HAL_GetTick() - m_last_write) >= WRITE_TIMEOUT) && (!m_shadow_buf_synced)) + { + // write shadow buffer to nvmem + write_flash(); + + // set synced flag + m_shadow_buf_synced = 1; + } +} + + +int32_t NVmem_write(uint8_t* data, uint32_t addr, uint32_t len) +{ + // bound check + if (addr + len >= NVMEM_SIZE) + return (-1); + + // write data to shadow buf + uint32_t data_index = 0; + for (uint32_t i = addr; i < len; i++) + { + m_shadow_buf[i] = data[data_index++]; + } + + // set sync flag to out of sync + m_shadow_buf_synced = 0; + + return (0); +} + + +int32_t NVmem_write_immediate(uint8_t* data, uint32_t addr, uint32_t len) +{ + int32_t ret = 0; + + // bound check + if (addr + len >= NVMEM_SIZE) + return (-1); + + // write data to shadow buf + uint32_t data_index = 0; + for (uint32_t i = addr; i < len; i++) + { + m_shadow_buf[i] = data[data_index++]; + } + + // write shadow buffer to nvmem + write_flash(); + + // set synced flag + m_shadow_buf_synced = 1; + + return (ret); +} + + +int32_t NVmem_read(uint8_t* data, uint32_t addr, uint32_t len) +{ + // bound check + if (addr + len >= NVMEM_SIZE) + return (-1); + + // copy data using provided pointer + uint32_t index = 0; + for (uint32_t i = addr; i < len; i++) + { + data[index++] = m_shadow_buf[i]; + } + + return (0); +} + +/* PRIVATE FUNCTIONS */ + +// Read from flash + + +// Write to flash +int write_flash(void) +{ + uint32_t page_error = 0; + HAL_StatusTypeDef status; + + HAL_FLASH_Unlock(); + + // Erase flash area + FLASH_EraseInitTypeDef erase_init_struct; + + erase_init_struct.TypeErase = FLASH_TYPEERASE_PAGES; + erase_init_struct.Banks = FLASH_BANK_1; + erase_init_struct.Page = (0x801F800 - FLASH_BASE) / FLASH_PAGE_SIZE; + erase_init_struct.NbPages = 1; + + status = HAL_FLASHEx_Erase(&erase_init_struct, &page_error); + + if (HAL_OK != status) + { + HAL_FLASH_Lock(); + return (-1); + } + + uint64_t buf; + + uint32_t len = NVMEM_SIZE; + uint32_t prog_addr = 0x801F800; + uint32_t index = 0; + + while (len >= 8) + { + buf = (uint64_t)m_shadow_buf[index]; + buf |= ((uint64_t)m_shadow_buf[index + 1] << 8); + buf |= ((uint64_t)m_shadow_buf[index + 2] << 16); + buf |= ((uint64_t)m_shadow_buf[index + 3] << 24); + buf |= ((uint64_t)m_shadow_buf[index + 4] << 32); + buf |= ((uint64_t)m_shadow_buf[index + 5] << 40); + buf |= ((uint64_t)m_shadow_buf[index + 6] << 48); + buf |= ((uint64_t)m_shadow_buf[index + 7] << 56); + + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, prog_addr, buf); + + index += 8; + prog_addr += 8; + len -= 8; + } + + HAL_FLASH_Lock(); + + return ((int)status); +} \ No newline at end of file diff --git a/Core/Src/cir_buf.c b/Core/Src/cir_buf.c index ccfaeaa..c30b38c 100644 --- a/Core/Src/cir_buf.c +++ b/Core/Src/cir_buf.c @@ -13,6 +13,178 @@ ************************************************************************* **/ +#include #include +#include +#include -#include "cir_buf.h" \ No newline at end of file +#include "cir_buf.h" + +// The definition of our circular buffer structure is hidden from the user +struct circular_buf_t +{ + uint8_t* buffer; + size_t head; + size_t tail; + size_t max; // of the buffer + bool full; +}; + +/* PRIVATE FUNCTIONS */ +static inline size_t advance_headtail_value(size_t value, size_t max) +{ + return (value + 1) % max; +} + +static void advance_head_pointer(cbuf_handle_t me) +{ + assert(me); + + if(circular_buf_full(me)) + { + me->tail = advance_headtail_value(me->tail, me->max); + } + + me->head = advance_headtail_value(me->head, me->max); + me->full = (me->head == me->tail); +} + +/* API FUNCTIONS */ + +cbuf_handle_t circular_buf_init(uint8_t* buffer, size_t size) +{ + assert(buffer && size); + + cbuf_handle_t cbuf = malloc(sizeof(circular_buf_t)); + assert(cbuf); + + cbuf->buffer = buffer; + cbuf->max = size; + circular_buf_reset(cbuf); + + assert(circular_buf_empty(cbuf)); + + return cbuf; +} + +void circular_buf_free(cbuf_handle_t me) +{ + assert(me); + free(me); +} + +void circular_buf_reset(cbuf_handle_t me) +{ + assert(me); + + me->head = 0; + me->tail = 0; + me->full = false; +} + +size_t circular_buf_size(cbuf_handle_t me) +{ + assert(me); + + size_t size = me->max; + + if(!circular_buf_full(me)) + { + if(me->head >= me->tail) + { + size = (me->head - me->tail); + } + else + { + size = (me->max + me->head - me->tail); + } + } + + return size; +} + +size_t circular_buf_capacity(cbuf_handle_t me) +{ + assert(me); + + return me->max; +} + +void circular_buf_put(cbuf_handle_t me, uint8_t data) +{ + assert(me && me->buffer); + + me->buffer[me->head] = data; + + advance_head_pointer(me); +} + +int circular_buf_try_put(cbuf_handle_t me, uint8_t data) +{ + int r = -1; + + assert(me && me->buffer); + + if(!circular_buf_full(me)) + { + me->buffer[me->head] = data; + advance_head_pointer(me); + r = 0; + } + + return r; +} + +int circular_buf_get(cbuf_handle_t me, uint8_t* data) +{ + assert(me && data && me->buffer); + + int r = -1; + + if(!circular_buf_empty(me)) + { + *data = me->buffer[me->tail]; + me->tail = advance_headtail_value(me->tail, me->max); + me->full = false; + r = 0; + } + + return r; +} + +bool circular_buf_empty(cbuf_handle_t me) +{ + assert(me); + + return (!circular_buf_full(me) && (me->head == me->tail)); +} + +bool circular_buf_full(cbuf_handle_t me) +{ + assert(me); + + return me->full; +} + +int circular_buf_peek(cbuf_handle_t me, uint8_t* data, unsigned int look_ahead_counter) +{ + int r = -1; + size_t pos; + + assert(me && data && me->buffer); + + // We can't look beyond the current buffer size + if(circular_buf_empty(me) || look_ahead_counter > circular_buf_size(me)) + { + return r; + } + + pos = me->tail; + for(unsigned int i = 0; i < look_ahead_counter; i++) + { + data[i] = me->buffer[pos]; + pos = advance_headtail_value(pos, me->max); + } + + return 0; +} \ No newline at end of file diff --git a/Core/Src/console.c b/Core/Src/console.c new file mode 100644 index 0000000..80ffd9f --- /dev/null +++ b/Core/Src/console.c @@ -0,0 +1,444 @@ +/** +********************************************************************* +* +* @file console.c +* @brief +* +* @date 2024-04-14 19:12:40 +* @author CT +* +* @details +* +************************************************************************* +**/ + +/* + Operational Concept: + Sending enter displays the current menu + Simple 1 char command interface +*/ +#include +#include + +#include "console.h" +#include "NVmem.h" +#include "version.h" + +#include "usbd_cdc_if.h" + + +#define CONSOLE_BUF_SIZE (256u) + + +typedef struct config_data +{ + int32_t val_1; + int32_t val_2; + int32_t val_3; +} config_data_t; + +typedef union config_data_u +{ + config_data_t config; + uint8_t data[12]; +} config_data_u_t; + +static cbuf_handle_t m_console_input; +static cbuf_handle_t m_console_output; +static uint8_t m_console_input_buf[CONSOLE_BUF_SIZE] = {0}; +static uint8_t m_console_output_buf[CONSOLE_BUF_SIZE] = {0}; +static uint8_t tx_buf[CONSOLE_BUF_SIZE]; +static uint8_t m_command_buf[16] = {0}; +static uint8_t m_command_len = 0; +static bool m_command_ready = false; +static bool m_echo_console = false; + +// static int32_t submenu_value_one = 0; +// static int32_t submenu_value_two = 0; +// static int32_t submenu_value_three = 0; +config_data_u_t configuration_data; + +enum console_menu_state{main_menu, submenu_1, submenu_2, submenu_3, save_menu, version_menu}; +enum console_menu_state console_menu = main_menu; + + +static void process_incoming(void); +static void process_outgoing(void); +static void process_command(void); +static int console_send(uint8_t* buf, uint32_t len); +static void menu_state_machine(void); +static int parse_input(int32_t* data); +static int32_t read_line(uint8_t data); + +static void print_main_menu(void); +static void print_submenu_one(void); +static void print_submenu_two(void); +static void print_submenu_three(void); +static void print_saved_menu(int32_t val); + + +static void set_console_reset(void); +static void set_console_red(void); +static void set_console_green(void); +static void reset_console(void); + + +/* PUBLIC FUNCTIONS */ + +void console_init(void) +{ + m_console_input = circular_buf_init(m_console_input_buf, CONSOLE_BUF_SIZE); + m_console_output = circular_buf_init(m_console_output_buf, CONSOLE_BUF_SIZE); + + // for this demonstratior, load example values from nvmem + NVmem_read(configuration_data.data, 0, 12); +} + + +void console_service(void) +{ + // if there is received data waiting + process_incoming(); + + // if there is data waiting to be transmitted + process_outgoing(); + + // Process command + process_command(); +} + + +/// @brief Attempts to push one byte into the console input buffer +/// @param data byte to be pushed to input +/// @return 0 on success, -1 on failure +int console_push(uint8_t data) +{ + int ret = 0; + + ret = circular_buf_try_put(m_console_input, data); + + return (ret); +} + + +/* PRIVATE FUNCTIONS */ + +void process_incoming(void) +{ + if (!circular_buf_empty(m_console_input)) + { + uint8_t data; + while (!circular_buf_empty(m_console_input)) + { + circular_buf_get(m_console_input, &data); + m_command_ready = read_line(data); + + if (m_echo_console) + { + circular_buf_try_put(m_console_output, data); + } + } + } +} + + +void process_outgoing(void) +{ + if(!circular_buf_empty(m_console_output)) + { + size_t tx_len = circular_buf_size(m_console_output); + for (uint32_t i = 0; i < tx_len; i++) + { + circular_buf_get(m_console_output, &tx_buf[i]); + } + // Note: directly interacts with interface + CDC_Transmit_FS(tx_buf, tx_len); + } +} + + +void process_command(void) +{ + if(m_command_ready) + { + m_command_ready = false; + // for(uint32_t i = 0; i < m_command_len; i++) + // { + // circular_buf_put(m_console_output, m_command_buf[i]); + // } + menu_state_machine(); + } +} + + +int console_send(uint8_t* buf, uint32_t len) +{ + int ret = 0; + + for (uint32_t i = 0; i < len; i++) + { + ret |= circular_buf_try_put(m_console_output, buf[i]); + } + + return (ret); +} + + +/// @brief Reads in a line terminated by \\n +/// @param data +/// @return 1 if EOL found, 0 otherwise +int32_t read_line(uint8_t data) +{ + int32_t ret = 0; + static uint8_t m_command_buf_index = 0; + + // if EOL, return on and set length + if((data == '\n') || (data == '\r')) + { + m_command_buf[m_command_buf_index++] = '\n'; + // set length of command for use within rest of module + m_command_len = m_command_buf_index; + // reset index + m_command_buf_index = 0; + + ret = 1; + } + else if (data == 0x1B) // ESCAPE + { + m_command_len = 1; + m_command_buf[0] = 0x1B; + // reset index + m_command_buf_index = 0; + ret = 1; + } + else + { + if (m_command_buf_index < 16) + { + m_command_buf[m_command_buf_index++] = data; + } + else + { + m_command_buf_index = 0; + } + } + + return (ret); +} + + +// Called when a complete line has been received +void menu_state_machine(void) +{ + int32_t success = 0; + + switch (console_menu) + { + case main_menu: + if (m_command_buf[0] == '1') + { + print_submenu_one(); + console_menu = submenu_1; + } + else if (m_command_buf[0] == '2') + { + print_submenu_two(); + console_menu = submenu_2; + } + else if (m_command_buf[0] == '3') + { + print_submenu_three(); + console_menu = submenu_3; + } + else if (m_command_buf[0] == 'S') + { + success = NVmem_write_immediate(configuration_data.data, 0, 12); + print_saved_menu(success); + // need to call service because we are blocking all normal execution here + process_outgoing(); + + // Delay for user to read result + HAL_Delay(3000); + + console_menu = main_menu; + print_main_menu(); + } + else// if (m_command_buf[0] == '\n') + { + print_main_menu(); + } + break; + case submenu_1: + if (m_command_buf[0] == 0x1B) // ESCAPE + { + console_menu = main_menu; + print_main_menu(); + } + else + { + // Take input and immediately return to main menu + parse_input(&configuration_data.config.val_1); + console_menu = main_menu; + print_main_menu(); + } + break; + + case submenu_2: + if (m_command_buf[0] == 0x1B) // ESCAPE + { + console_menu = main_menu; + print_main_menu(); + } + else + { + parse_input(&configuration_data.config.val_2); + console_menu = main_menu; + print_main_menu(); + } + break; + + case submenu_3: + if (m_command_buf[0] == 0x1B) // ESCAPE + { + console_menu = main_menu; + print_main_menu(); + } + else + { + parse_input(&configuration_data.config.val_3); + console_menu = main_menu; + print_main_menu(); + } + break; + + case save_menu: + + break; + + default: + break; + } +} + + +/// @brief Parses line for integer +/// @param data parsed out integer +/// @return 1 on success, otherwise fail...kinda +int parse_input(int32_t* data) +{ + // *data = atoi((char*)m_command_buf); + int ret = sscanf((char*)m_command_buf, "%ld", data); + + return (ret); +} + +// Also acts as initialization for state +void print_main_menu(void) +{ + char buf[128]; + + m_echo_console = true; + + reset_console(); + set_console_red(); + + uint32_t len = snprintf(buf, 128, "Main Menu:\r\n[1]Option 1: \"%li\"\r\n[2]Option 2: \"%li\"\r\n[3]Option 3: \"%li\"\r\n[S]ave\r\nVersion: %s\r\nEnter Selection: ", + configuration_data.config.val_1, configuration_data.config.val_2, configuration_data.config.val_3, VERSION_STR); + console_send((uint8_t*)buf, len); +} + +void print_submenu_one(void) +{ + char buf[128]; + + m_echo_console = true; + + reset_console(); + set_console_reset(); + + uint32_t len = snprintf(buf, 128, "Submenu 1:\r\n"); + console_send((uint8_t*)buf, len); +} + + +void print_submenu_two(void) +{ + char buf[128]; + + m_echo_console = true; + + reset_console(); + set_console_reset(); + + uint32_t len = snprintf(buf, 128, "Submenu 2:\r\n"); + console_send((uint8_t*)buf, len); +} + + +void print_submenu_three(void) +{ + char buf[128]; + + m_echo_console = true; + + reset_console(); + set_console_reset(); + + uint32_t len = snprintf(buf, 128, "Submenu 3:\r\n"); + console_send((uint8_t*)buf, len); +} + + +void print_saved_menu(int32_t val) +{ + char buf[128]; + uint32_t len; + + reset_console(); + set_console_green(); + + if (0 == val) + { + len = snprintf(buf, 128, "SAVED!!1!"); + } + else + { + len = snprintf(buf, 128, "SAVE FAILED!"); + } + + console_send((uint8_t*)buf, len); +} + + + +void set_console_reset(void) +{ + char buf[16] = {0}; + uint32_t len = snprintf(buf, 16, "\x1b[1;0m"); + console_send((uint8_t*)buf, len); +} + + +void set_console_red(void) +{ + char buf[16] = {0}; + uint32_t len = snprintf(buf, 16, "\x1b[1;31m"); + console_send((uint8_t*)buf, len); +} + + +void set_console_green(void) +{ + char buf[16] = {0}; + uint32_t len = snprintf(buf, 16, "\x1b[1;32m"); + console_send((uint8_t*)buf, len); +} + + +void reset_console(void) +{ + char buf[16] = {0}; + + uint32_t len = snprintf(buf, 16, "\x1b[2J\x1b[H"); + console_send((uint8_t*)buf, len); +} \ No newline at end of file diff --git a/Core/Src/main.c b/Core/Src/main.c index ad37a39..4536ed3 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -30,9 +30,11 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "console.h" #include "usbd_cdc_if.h" #include "sht_40.h" #include "IS66.h" +#include "NVmem.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -53,7 +55,7 @@ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ -char buf[256] = {0}; + /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -116,6 +118,12 @@ int main(void) // Turn on SD Card power, active low HAL_GPIO_WritePin(SD_PWR_EN_GPIO_Port, SD_PWR_EN_Pin, GPIO_PIN_RESET); + NVmem_init(); + // uint8_t buf[4] = {0xEF, 0xBE, 0xAD, 0xDE}; + // NVmem_write(buf, 0, 4); + + console_init(); + static uint32_t prev_tick = 0; if (HAL_OK == sht40_init(&hi2c1)) @@ -137,12 +145,22 @@ int main(void) prev_tick = tick; HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); - sht40_read(); - temp = sht40_get_temp_C(); - rh = sht40_get_rh(); - len = snprintf(buf, 128, "Temp: %03.2fC\tRH: %02.1f\r\n", temp, rh); - CDC_Transmit_FS((uint8_t *)buf, len); + // sht40_read(); + // temp = sht40_get_temp_C(); + // float temp_f = sht40_get_temp_F(); + // rh = sht40_get_rh(); + // len = snprintf(buf, 128, "Temp: %03.2fC\t %03.2fF\r\n", temp, temp_f); + // len += snprintf((buf + len), (128 - len), "RH: %02.1f\r\n", rh); + // // CDC_Transmit_FS((uint8_t *)buf, len); + // for (uint32_t i = 0; i < len; i++) + // { + // console_push(buf[i]); + // } } + + NVmem_service(); + console_service(); + /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ diff --git a/STM32G0B1KBUX_FLASH.ld b/STM32G0B1KBUX_FLASH.ld index 4e23274..7b96ac6 100644 --- a/STM32G0B1KBUX_FLASH.ld +++ b/STM32G0B1KBUX_FLASH.ld @@ -62,12 +62,19 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 144K -FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 126K +CONFIG (r) : ORIGIN = 0x801F800, LENGTH = 2K } /* Define output sections */ SECTIONS { + /* Application NV configuration data */ + .ConfigData (NOLOAD) : + { + KEEP(*(.ConfigData)) + } >CONFIG + /* The startup code goes first into FLASH */ .isr_vector : { @@ -134,7 +141,7 @@ SECTIONS _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : + .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ @@ -145,7 +152,7 @@ SECTIONS _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH - + /* Uninitialized data section */ . = ALIGN(4); .bss : @@ -173,7 +180,7 @@ SECTIONS . = ALIGN(8); } >RAM - + /* Remove information from the standard libraries */ /DISCARD/ : diff --git a/USB_Device/App/usbd_cdc_if.c b/USB_Device/App/usbd_cdc_if.c index c154da1..151a6c3 100644 --- a/USB_Device/App/usbd_cdc_if.c +++ b/USB_Device/App/usbd_cdc_if.c @@ -22,7 +22,7 @@ #include "usbd_cdc_if.h" /* USER CODE BEGIN INCLUDE */ - +#include "console.h" /* USER CODE END INCLUDE */ /* Private typedef -----------------------------------------------------------*/ @@ -263,8 +263,11 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) /* USER CODE BEGIN 6 */ USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hUsbDeviceFS); - // TODO add USB received handler here + for (uint32_t i = 0; i < *Len; i++) + { + console_push(Buf[i]); + } return (USBD_OK); /* USER CODE END 6 */ } diff --git a/cmake/stm32cubemx/CMakeLists.txt b/cmake/stm32cubemx/CMakeLists.txt index 005170b..5bd4dd3 100644 --- a/cmake/stm32cubemx/CMakeLists.txt +++ b/cmake/stm32cubemx/CMakeLists.txt @@ -88,9 +88,11 @@ target_sources(stm32cubemx INTERFACE ../../Core/Src/sysmem.c ../../Core/Src/syscalls.c ../../startup_stm32g0b1xx.s + ../../Core/Src/console.c ../../Core/Src/cir_buf.c ../../Core/Src/data_table.c ../../Core/Src/IS66.c + ../../Core/Src/NVmem.c ../../Core/Src/sht_40.c ../../Core/Src/testmode.c )