more firmware tweaks
diff --git a/32blit-stm32/CMakeLists.txt b/32blit-stm32/CMakeLists.txt index be85e23..a654e69 100644 --- a/32blit-stm32/CMakeLists.txt +++ b/32blit-stm32/CMakeLists.txt
@@ -74,6 +74,8 @@ Src/32blit.c Src/CDCLogging.c startup_stm32h750xx.s + Src/usb-cdc.cpp + Src/core-debug.cpp Src/CDCDataStream.cpp Src/CDCCommandStream.cpp Src/CDCCommandHandler.cpp
diff --git a/32blit-stm32/Inc/32blit.h b/32blit-stm32/Inc/32blit.h index 902601b..1d8895b 100644 --- a/32blit-stm32/Inc/32blit.h +++ b/32blit-stm32/Inc/32blit.h
@@ -41,5 +41,6 @@ void blit_menu_render(uint32_t time); void blit_menu(); + extern void blit_enable_ADC(); extern void blit_disable_ADC();
diff --git a/32blit-stm32/Inc/core-debug.hpp b/32blit-stm32/Inc/core-debug.hpp new file mode 100644 index 0000000..11677a9 --- /dev/null +++ b/32blit-stm32/Inc/core-debug.hpp
@@ -0,0 +1,11 @@ +#pragma once + +#include <string> +#include <vector> + +namespace debug { + + extern std::vector<std::string> messages; + extern void debug(const char *p); + extern void render(); +} \ No newline at end of file
diff --git a/32blit-stm32/Inc/usb-cdc.hpp b/32blit-stm32/Inc/usb-cdc.hpp new file mode 100644 index 0000000..b06d625 --- /dev/null +++ b/32blit-stm32/Inc/usb-cdc.hpp
@@ -0,0 +1,17 @@ +#pragma once + +#include <stdint.h> +#include <map> + +namespace cdc { + + typedef bool (*CommandHandler)(char *data, uint32_t length); + + extern std::map<std::string, CommandHandler> handlers; + + void reset_rx_buffer(); + void data_received(uint32_t length); + void parse_command(); + void register_command_handler(std::string command, CommandHandler handler); + +}
diff --git a/32blit-stm32/Src/32blit.c b/32blit-stm32/Src/32blit.c index 28acfa9..7cc2294 100644 --- a/32blit-stm32/Src/32blit.c +++ b/32blit-stm32/Src/32blit.c
@@ -3,7 +3,7 @@ #include "32blit.h" #include "main.h" - +#include "core-debug.hpp" #include "sound.hpp" #include "display.hpp" #include "gpio.hpp" @@ -84,6 +84,7 @@ void blit_tick() { if(display::needs_render) { blit::render(blit::now()); + debug::render(); display::enable_vblank_interrupt(); }
diff --git a/32blit-stm32/Src/core-debug.cpp b/32blit-stm32/Src/core-debug.cpp new file mode 100644 index 0000000..7501c92 --- /dev/null +++ b/32blit-stm32/Src/core-debug.cpp
@@ -0,0 +1,35 @@ + +#include "core-debug.hpp" + +#include "32blit.h" + +using namespace blit; + +namespace debug { + + std::vector<std::string> messages; + + void debug(const char *p) { + std::string message = p; + + if(messages.size() > 20) { + messages.erase(messages.begin()); + } + + messages.push_back(message); + } + + void render() { + if(messages.size() > 0) { + screen.pen = Pen(0, 0, 0, 200); + screen.rectangle(Rect(10, 10, 300, 220)); + screen.pen = Pen(255, 255, 255, 200); + uint8_t i = 0; + for(auto message : messages) { + screen.text(message, minimal_font, Point(12, 12 + i * 10)); + i++; + } + } + } + +} \ No newline at end of file
diff --git a/32blit-stm32/Src/main.c b/32blit-stm32/Src/main.c index 21b2d66..1c7c622 100644 --- a/32blit-stm32/Src/main.c +++ b/32blit-stm32/Src/main.c
@@ -31,6 +31,7 @@ #include "spi.h" #include "tim.h" #include "usb_device.h" +#include "core-debug.hpp" #include "gpio.hpp" #include "display.hpp" @@ -41,6 +42,7 @@ #include "32blit.h" #include "32blit.hpp" #include "graphics/color.hpp" +#include "usb-cdc.hpp" #include "CDCResetHandler.h" #include "CDCInfoHandler.h" #include "CDCCommandStream.h" @@ -171,9 +173,13 @@ blit_tick(); //HAL_Delay(1000); // handle CDC input - g_commandStream.Stream(); + //g_commandStream.Stream(); + cdc::parse_command(); uint32_t t_elapsed = blit::now() - t_start; + + + // uint32_t uTimeElapsed = (DWT->CYCCNT - uTimeStart)/uTicksPerUs; // printf("%lu, %lu\n\r", t_elapsed, uTimeElapsed); /* USER CODE END WHILE */
diff --git a/32blit-stm32/Src/usb-cdc.cpp b/32blit-stm32/Src/usb-cdc.cpp new file mode 100644 index 0000000..323b04c --- /dev/null +++ b/32blit-stm32/Src/usb-cdc.cpp
@@ -0,0 +1,78 @@ +#include "32blit.h" +#include "core-debug.hpp" +#include "usbd_cdc.h" +#include "usbd_core.h" +#include "usb-cdc.hpp" + +#include <cstring> +#include <string> + +extern USBD_HandleTypeDef hUsbDeviceHS; + +namespace cdc { + + std::map<std::string, CommandHandler> handlers; + + struct { + char data[64]; + uint32_t length = 0; + } rx_buffer; + + // register a function to handle a new USB serial command + void register_command_handler(std::string command, CommandHandler handler) { + handlers[command] = handler; + } + + void data_received(uint32_t length) { + rx_buffer.length = length; + } + + // stores the length of the current rx buffer and swaps to the other buffer if + // it is free for use returning a pointer to the data member (or null if not free) + void reset_rx_buffer() { + rx_buffer.length = 0; + + USBD_CDC_SetRxBuffer(&hUsbDeviceHS, rx_buffer.data); + USBD_CDC_ReceivePacket(&hUsbDeviceHS); + } + + // check for the incoming command identifier and matches it to the + // appropriate handler, then streams all incoming data directly to + // the handler until the command processing is complete + void parse_command() { + static CommandHandler handler = nullptr; + + if(rx_buffer.length > 0) { + // debug::debug(std::to_string(rx_buffer.length).c_str()); + uint32_t s = blit::now(); + if(!handler) { + // if no handler assigned yet then we're waiting for the command + // search through the handler list to see if we have a matching one + for(auto c : handlers) { + if(strcmp(c.first.c_str(), rx_buffer.data) == 0) { + // found the command so assign the handler and call it with the + // first packet of data + handler = c.second; + uint32_t command_length = strlen(rx_buffer.data) + 1; + + bool done = handler(rx_buffer.data + command_length, rx_buffer.length - command_length); + + if(done) { + handler = nullptr; + } + } + } + } else { + // the command handle must return true when it has finished processing + // the entire command (even if this is across multiple packets) + bool done = handler(rx_buffer.data, rx_buffer.length); + + if(done) { + handler = nullptr; + } + } + + reset_rx_buffer(); + } + } +} \ No newline at end of file
diff --git a/32blit-stm32/Src/usbd_cdc_if.c b/32blit-stm32/Src/usbd_cdc_if.c index 85aef3b..e7a8189 100644 --- a/32blit-stm32/Src/usbd_cdc_if.c +++ b/32blit-stm32/Src/usbd_cdc_if.c
@@ -19,6 +19,7 @@ */ /* USER CODE END Header */ #include "CDCCommandStream.h" +#include "usb-cdc.hpp" /* Includes ------------------------------------------------------------------*/ #include "usbd_cdc_if.h" @@ -160,7 +161,10 @@ /* USER CODE BEGIN 8 */ /* Set Application Buffers */ USBD_CDC_SetTxBuffer(&hUsbDeviceHS, UserTxBufferHS, 0); - USBD_CDC_SetRxBuffer(&hUsbDeviceHS, g_commandStream.GetFifoWriteBuffer()); + //USBD_CDC_SetRxBuffer(&hUsbDeviceHS, g_commandStream.GetFifoWriteBuffer()); + //USBD_CDC_SetRxBuffer(&hUsbDeviceHS, cdc::swap_buffers(0)); + + cdc::reset_rx_buffer(); return (USBD_OK); /* USER CODE END 8 */ } @@ -271,14 +275,21 @@ /* USER CODE BEGIN 11 */ // release the old write buffer for reading and set length - g_commandStream.ReleaseFifoWriteBuffer(*Len); +// g_commandStream.ReleaseFifoWriteBuffer(*Len); + + + cdc::data_received(*Len); + + //g_commandStream.ReleaseFifoWriteBuffer(*Len);^M + + // now supply a new rx buffer for reading into^M // If a new writebuffer is available, set RxBuffer and requext next USB packet - if(uint8_t *pBuffer = g_commandStream.GetFifoWriteBuffer()) +/* if(uint8_t *pBuffer = g_commandStream.GetFifoWriteBuffer()) { USBD_CDC_SetRxBuffer(&hUsbDeviceHS, pBuffer); USBD_CDC_ReceivePacket(&hUsbDeviceHS); - } + }*/ //// g_commandStream.AddToFifo(Buf, *Len); // if(*Len)
diff --git a/examples/flash b/examples/flash index 3d0cd97..aaaeee6 100644 --- a/examples/flash +++ b/examples/flash
@@ -60,7 +60,7 @@ serial_port.reset_output_buffer() -command = "32BLSAVE{0}\x00{1}\x00".format(file_name, file_size) +command = "SAVE\x00{0}\x00{1}\x00".format(file_name, file_size) serial_port.write(bytes(command, "ascii")) #serial_port.write(b"32BL")
diff --git a/firmware/flash-loader/flash-loader.cpp b/firmware/flash-loader/flash-loader.cpp index c3c51df..4903711 100644 --- a/firmware/flash-loader/flash-loader.cpp +++ b/firmware/flash-loader/flash-loader.cpp
@@ -2,10 +2,14 @@ #include "graphics/color.hpp" #include <cmath> #include "quadspi.h" +#include "usbd_def.h" +#include "usbd_cdc_if.h" #include "CDCCommandStream.h" +#include "usb-cdc.hpp" #include <cstring> #include <stdio.h> #include <stdlib.h> + using namespace blit; extern CDCCommandStream g_commandStream; @@ -17,8 +21,7 @@ FlashLoader flashLoader; -inline bool ends_with(std::string const &value, std::string const &ending) -{ +inline bool ends_with(std::string const &value, std::string const &ending) { if(ending.size() > value.size()) return false; return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); } @@ -34,7 +37,7 @@ } void select_file(const char *filename) { - for(auto i = 0; i < files.size(); i++) { + for(size_t i = 0; i < files.size(); i++) { if(files[i].name == filename) { persist.selected_menu_item = i; } @@ -43,18 +46,29 @@ Vec2 list_offset(5.0f, 0.0f); +bool usb_cdc_save_to_sd_card(char *data, uint32_t length); + +bool usb_cdc_reset(char *data, uint32_t length) { + NVIC_SystemReset(); + return true; +} + +bool usb_cdc_application_location(char *data, uint32_t length) { + while(USBD_BUSY == CDC_Transmit_HS((uint8_t *)"32BL_EXT", 8)) {}; + + HAL_Delay(250); + return true; +} + void init() { set_screen_mode(ScreenMode::hires); load_file_list(); - // register PROG - g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value, &flashLoader); - // register SAVE - g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value, &flashLoader); - // register LS - g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value, &flashLoader); + cdc::register_command_handler("RESET", usb_cdc_reset); + cdc::register_command_handler("INFO", usb_cdc_application_location); + cdc::register_command_handler("SAVE", usb_cdc_save_to_sd_card); } void background(uint32_t time_ms) { @@ -62,22 +76,7 @@ static Vec3 blobs[blob_count]; static bool first = true; -/* - for(int y = 0; y < 240; y++) { - screen.pen = Pen(y, 0, 0); - screen.rectangle(Rect(0, y, 80, 1)); - screen.pen = Pen(0, y, 0); - screen.rectangle(Rect(80, y, 80, 1)); - screen.pen = Pen(0, 0, y); - screen.rectangle(Rect(160, y, 80, 1)); - screen.pen = Pen(y, y, y); - screen.rectangle(Rect(240, y, 80, 1)); - } - screen.pen = Pen(0, 0, 0); - screen.rectangle(Rect(100, 100, 100, 100)); - return; -*/ for(uint16_t y = 0; y < 420; y++) { for(uint16_t x = 0; x < 320; x++) { screen.pen = Pen(x >> 1, y, 255 - (x >> 1)); @@ -181,8 +180,6 @@ } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool flash_from_sd_to_qspi_flash(const std::string &filename) @@ -240,128 +237,9 @@ } -/* -// RenderSaveFile() Render file save progress % -void FlashLoader::RenderSaveFile(uint32_t time) -{ - screen.pen = Pen(0,0,0); - screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - screen.pen = Pen(255, 255, 255); - char buffer[128]; - sprintf(buffer, "Saving %.2u%%", (uint16_t)m_fPercent); - screen.text(buffer, minimal_font, ROW(0)); -} - - -// RenderFlashCDC() Render flashing progress % -void FlashLoader::RenderFlashCDC(uint32_t time) -{ - screen.pen = Pen(0,0,0); - screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - screen.pen = Pen(255, 255, 255); - - char buffer[128]; - sprintf(buffer, "Flashing %.2u%%", (uint16_t)m_fPercent); - screen.text(buffer, minimal_font, ROW(0)); -} -*/ - -/* -void FlashLoader::Update(uint32_t time) -{ - if(m_state == stLS) - { - load_file_list(); - m_state = stFlashFile; - } -} -*/ - - - -////////////////////////////////////////////////////////////////////// -// Streaming Code -// The streaming code works with a simple state machine, -// current state is in m_parseState, the states parse index is -// in m_uParseState -////////////////////////////////////////////////////////////////////// - -// StreamInit() Initialise state machine -bool FlashLoader::StreamInit(CDCFourCC uCommand) -{ - //printf("streamInit()\n\r"); - m_fPercent = 0.0f; - bool bNeedStream = true; - switch(uCommand) - { - case CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value: - m_state = stFlashCDC; - m_parseState = stFilename; - m_uParseIndex = 0; - break; - - case CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value: - m_state = stSaveFile; - m_parseState = stFilename; - m_uParseIndex = 0; - break; - - case CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value: - m_state = stLS; - bNeedStream = false; - break; - - } - return bNeedStream; -} - - -// FlashData() Flash data to the QSPI flash -// Note: currently qspi_write_buffer only works for sizes of 256 max -/* -bool FlashLoader::FlashData(uint32_t uOffset, uint8_t *pBuffer, uint32_t uLen) -{ - bool bResult = false; - if(QSPI_OK == qspi_write_buffer(uOffset, pBuffer, uLen)) - { - if(QSPI_OK == qspi_read_buffer(uOffset, m_verifyBuffer, uLen)) - { - // compare buffers - bResult = true; - - for(uint32_t uB = 0; bResult && uB < uLen; uB++) - bResult = pBuffer[uB] == m_verifyBuffer[uB]; - } - } - return bResult; -} -*/ - -// SaveData() Saves date to file on SDCard -bool FlashLoader::SaveData(uint8_t *pBuffer, uint32_t uLen) -{ - UINT uWritten; - FRESULT res = f_write(&m_file, pBuffer, uLen, &uWritten); - - return !res && (uWritten == uLen); - -} - -void copy_from_usb_to_sd_card() { - -} - -// StreamData() Handle streamed data -// State machine has three states: -// stFilename : Parse filename -// stLength : Parse length, this is sent as an ascii string -// stData : The binary data (.bin file) - - // when a command is issued (e.g. "PROG" or "SAVE") then this function is called // whenever new data is received to allow the firmware to process it. -CDCCommandHandler::StreamResult FlashLoader::StreamData(CDCDataStream &stream) -{ +bool usb_cdc_save_to_sd_card(char *data, uint32_t length) { enum class StreamState { NONE, NAME, LENGTH, DATA }; static StreamState state = StreamState::NONE; @@ -382,10 +260,14 @@ // loop through all bytes in the input stream uint8_t byte; - while(stream.Get(byte)) { + while(length--) { + byte = *data++; *p++ = byte; switch(state) { + case StreamState::NONE: + break; + // sending filename case StreamState::NAME: if(byte == '\0') { @@ -402,9 +284,8 @@ bytes_total = atol(length_buffer); p = data_buffer; - if(f_open(&file, name_buffer, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) { - progress.show(std::to_string(srError), 1); - return srError; + if(f_open(&file, name_buffer, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) { + return true; } state = StreamState::DATA; @@ -421,7 +302,7 @@ if(bytes_read == bytes_total || p == (data_buffer + sizeof(data_buffer))) { UINT bytes_written; if(f_write(&file, data_buffer, p - data_buffer, &bytes_written) != FR_OK) { - return srError; + return true; } p = data_buffer; progress.update(bytes_read); @@ -434,175 +315,12 @@ progress.hide(); load_file_list(); select_file(name_buffer); - return srFinish; + return true; } break; } } - return srContinue; - - /* - CDCCommandHandler::StreamResult result = srContinue; - uint8_t byte; - while(dataStream.GetStreamLength() && result == srContinue) - { - switch (m_parseState) - { - case stFilename: - if(m_uParseIndex < MAX_FILENAME) - { - while(result == srContinue && m_parseState == stFilename && dataStream.Get(byte)) - { - m_sFilename[m_uParseIndex++] = byte; - if (byte == 0) - { - m_parseState = stLength; - m_uParseIndex = 0; - } - } - } - else - { - printf("Failed to read filename\n\r"); - result =srError; - } - break; - - - case stLength: - if(m_uParseIndex < MAX_FILELEN) - { - while(result == srContinue && m_parseState == stLength && dataStream.Get(byte)) - { - m_sFilelen[m_uParseIndex++] = byte; - if (byte == 0) - { - m_parseState = stData; - m_uParseIndex = 0; - char *pEndPtr; - m_uFilelen = strtoul(m_sFilelen, &pEndPtr, 10); - if(m_uFilelen) - { - // init file or flash - switch(m_state) - { - case stSaveFile: - { - FRESULT res = f_open(&m_file, m_sFilename, FA_CREATE_ALWAYS | FA_WRITE); - if(res) - { - printf("Failed to create file (%s)\n\r", m_sFilename); - result = srError; - } - } - break; - - case stFlashCDC: - qspi_chip_erase(); - break; - - default: - break; - } - } - else - { - printf("Failed to parse filelen\n\r"); - result =srError; - } - } - } - } - else - { - printf("Failed to read filelen\n\r"); - result =srError; - } - break; - - case stData: - while((result == srContinue) && (m_parseState == stData) && (m_uParseIndex <= m_uFilelen) && dataStream.Get(byte)) - { - uint32_t uByteOffset = m_uParseIndex % PAGE_SIZE; - m_buffer[uByteOffset] = byte; - - // check buffer needs writing - volatile uint32_t uWriteLen = 0; - bool bEOS = false; - if (m_uParseIndex == m_uFilelen-1) - { - uWriteLen = uByteOffset+1; - bEOS = true; - } - else - if(uByteOffset == PAGE_SIZE-1) - uWriteLen = PAGE_SIZE; - - if(uWriteLen) - { - switch(m_state) - { - case stSaveFile: - // save data - if(!SaveData(m_buffer, uWriteLen)) - { - printf("Failed to save to SDCard\n\r"); - result = srError; - } - - // end of stream close up - if(bEOS) - { - f_close(&m_file); - m_bFsInit = false; - m_state = stFlashFile; - if(result != srError) - result = srFinish; - } - break; - - case stFlashCDC: - { - // save data - volatile uint32_t uPage = (m_uParseIndex / PAGE_SIZE); - if(!FlashData(uPage*PAGE_SIZE, m_buffer, uWriteLen)) - { - printf("Failed to write to flash\n\r"); - result = srError; - } - - // end of stream close up - if(bEOS) - { - if(result != srError) - { - result = srFinish; - m_state = stSwitch; - } - else - m_state = stFlashFile; - } - } - break; - - default: - break; - } - } - - m_uParseIndex++; - m_uBytesHandled = m_uParseIndex; - m_fPercent = ((float)m_uParseIndex/(float)m_uFilelen)* 100.0f; - } - break; - } - } - - if(result==srError) - m_state = stFlashFile;*/ - - //return result; + return false; } -
diff --git a/firmware/flash-loader/flash-loader.hpp b/firmware/flash-loader/flash-loader.hpp index dbde002..c6cc00b 100644 --- a/firmware/flash-loader/flash-loader.hpp +++ b/firmware/flash-loader/flash-loader.hpp
@@ -64,8 +64,10 @@ class FlashLoader : public CDCCommandHandler { public: - virtual StreamResult StreamData(CDCDataStream &dataStream); - virtual bool StreamInit(CDCFourCC uCommand); + virtual StreamResult StreamData(CDCDataStream &dataStream) { +return srContinue; + } + virtual bool StreamInit(CDCFourCC uCommand) {} void Init(void);