diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | .vscode/launch.json | 3 | ||||
-rwxr-xr-x | scripts/compiledb-full-path-mingw.sh | 2 | ||||
-rwxr-xr-x | scripts/dummy-server.py | 48 | ||||
-rw-r--r-- | shared/protocol.c | 14 | ||||
-rw-r--r-- | shared/protocol.h | 3 | ||||
-rw-r--r-- | shared/util.c | 7 | ||||
-rw-r--r-- | shared/util.h | 2 | ||||
-rw-r--r-- | stm32f091/consts.h | 6 | ||||
-rw-r--r-- | stm32f091/esp8266.c | 238 | ||||
-rw-r--r-- | stm32f091/esp8266.h | 44 | ||||
-rw-r--r-- | stm32f091/main.c | 11 | ||||
-rw-r--r-- | stm32f091/makefile | 9 | ||||
-rw-r--r-- | stm32f091/protocol.c | 21 | ||||
-rw-r--r-- | stm32f091/readme.md | 4 | ||||
-rw-r--r-- | stm32f091/server.c | 258 | ||||
-rw-r--r-- | stm32f091/server.h | 90 | ||||
-rw-r--r-- | stm32f091/setup.c | 97 | ||||
-rw-r--r-- | stm32f091/setup.h | 2 | ||||
-rw-r--r-- | stm32f091/todo.md | 28 | ||||
-rw-r--r-- | stm32f091/util.h | 35 | ||||
-rw-r--r-- | stm32f091/wifi.def.h | 2 |
22 files changed, 643 insertions, 282 deletions
@@ -18,4 +18,5 @@ shared/main .qmake.stash .vscode/.cortex-debug.registers.state.json copyright +temp/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 9c586dc..b104e0f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -31,9 +31,8 @@ "executable": "${workspaceFolder}/stm32f091/main.elf", "request": "launch", "type": "cortex-debug", - "runToEntryPoint": "main", "servertype": "stlink", - "preLaunchTask": "stm32/build", + "preLaunchTask": "stm32/flash", "linux": { "stlinkPath": "/usr/bin/st-util" }, diff --git a/scripts/compiledb-full-path-mingw.sh b/scripts/compiledb-full-path-mingw.sh index 8f95756..be45ca7 100755 --- a/scripts/compiledb-full-path-mingw.sh +++ b/scripts/compiledb-full-path-mingw.sh @@ -10,4 +10,4 @@ fixpath () { fixpath arm-none-eabi-gcc fixpath arm-none-eabi-objcopy -sed "s#\"/c/#\"C:/#g" -i "$COMPILEDB_FILE" +sed 's#"/\(.\)/#"\U\1:/#g' -i "$COMPILEDB_FILE"
\ No newline at end of file diff --git a/scripts/dummy-server.py b/scripts/dummy-server.py new file mode 100755 index 0000000..9350cab --- /dev/null +++ b/scripts/dummy-server.py @@ -0,0 +1,48 @@ +#!/bin/python3 + +""" +this is a garbage python script that opens a tcp socket on localhost:33 for +connecting with the qt client +""" + +import socketserver +from random import randint + +def hexpad(n, pad): + return hex(n)[2:].zfill(pad) + +def bs(str): + return bytes(str, 'utf-8') + +def r(max): + return randint(0, max) + +class DummyServer(socketserver.BaseRequestHandler): + def error(self): + self.request.sendall(bs("error\n")) + + def ok(self, rows): + response = "id,temperature,humidity,atmospheric_pressure\n" + line_len = len("xxxx,xx,xx,xx\n") + retstr = f"ok,{hex(len(response) + rows * line_len)[2:]}\n" + retstr += response + for row in range(rows): + retstr += f"{hexpad(row, 4)},{hexpad(r(0xff), 2)},{hexpad(r(0xff), 2)},{hexpad(r(0xff), 2)}\n" + self.request.sendall(bs(retstr)) + + def handle(self): + self.data = self.request.recv(1024).strip() + if len(self.data) > 40: return self.error() + if not self.data.startswith(bs('last-records')): return self.error() + self.data = self.data.replace(bs('last-records'), bs('')) + try: + self.ok(int(self.data)) + except ValueError: + self.error() + +if __name__ == "__main__": + socketserver.TCPServer.allow_reuse_address = True + with socketserver.TCPServer(("localhost", 33), DummyServer) as server: + server.serve_forever() + + diff --git a/shared/protocol.c b/shared/protocol.c index c6e5ddd..8887070 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -3,6 +3,7 @@ #include <string.h> #include "protocol.h" +#include "util.h" #define WS_CMD_MAP(parsed_cmd, name, code) \ if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; @@ -98,10 +99,11 @@ ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc() { void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); - for (unsigned int i = 0; i < state->arg_len; i++) + unsigned int args = WS_MIN(state->arg_len, WS_PROTOCOL_CMD_MAX_ARGUMENTS); + for (unsigned int i = 0; i < args; i++) state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); - state->target->argc = state->arg_len; + state->target->argc = args; unsigned int head = 0; for (unsigned int i = 0; i < state->arg_len; i++) { @@ -135,3 +137,11 @@ void ws_protocol_req_cmd_free(ws_s_protocol_parsed_req_cmd* cmd) { free(cmd); return; } + +unsigned short ws_protocol_get_header_size(ws_s_protocol_res* response) { + unsigned short size = 2; // comma and trailing newline + if (response->success == WS_PROTOCOL_CMD_RETURN_OK) size += 2; // ok + if (response->success == WS_PROTOCOL_CMD_RETURN_ERROR) size += 5; // error + size += ws_log16(response->msg->bytes) + 1; // amount of characters for message size (hex) + return size; +}
\ No newline at end of file diff --git a/shared/protocol.h b/shared/protocol.h index fbe29d6..5bcb114 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -5,7 +5,7 @@ #include "bin.h" -#define WS_PROTOCOL_CMD_MAX_ARGUMENTS (1) +#define WS_PROTOCOL_CMD_MAX_ARGUMENTS (2) #define WS_PROTOCOL_CMD_BUFFER_LEN (40) #define WS_PROTOCOL_CMD_AMOUNT (1) @@ -148,3 +148,4 @@ static ws_protocol_res_handler_t* g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMO [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records, }; +unsigned short ws_protocol_get_header_size(ws_s_protocol_res* response);
\ No newline at end of file diff --git a/shared/util.c b/shared/util.c new file mode 100644 index 0000000..ea972b0 --- /dev/null +++ b/shared/util.c @@ -0,0 +1,7 @@ +#include "util.h" + +unsigned int ws_log16(unsigned int x) { + unsigned int l = 0; + while (x >>= 4) ++l; // bitshift right by 4 until x == 0 + return l; +}
\ No newline at end of file diff --git a/shared/util.h b/shared/util.h index f39ff34..94a3dfe 100644 --- a/shared/util.h +++ b/shared/util.h @@ -2,3 +2,5 @@ #define WS_MIN(a, b) (((a) < (b)) ? (a) : (b)) #define WS_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +unsigned int ws_log16(unsigned int x); diff --git a/stm32f091/consts.h b/stm32f091/consts.h index 349ff21..3d2ef5a 100644 --- a/stm32f091/consts.h +++ b/stm32f091/consts.h @@ -3,6 +3,10 @@ #include "wifi.h" #define WS_SERVER_PORT "80" +#define WS_SERVER_MAX_CHANNELS 4 + +#define WS_DMA_RX_BUFFER_SIZE 100 +#define WS_DMA_TX_BUFFER_SIZE 1024 #define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9 #define WS_PINOUT_I2C_SDA_PORT GPIOB @@ -19,3 +23,5 @@ #define WS_PINOUT_USART2_TX_PIN GPIO_PIN_2 #define WS_PINOUT_USART2_TX_PORT GPIOA +// print esp communication over usb serial (green for tx, red for rx) +#define WS_DBG_PRINT_ESP_OVER_USART2 diff --git a/stm32f091/esp8266.c b/stm32f091/esp8266.c index 4fdf7e6..74ec347 100644 --- a/stm32f091/esp8266.c +++ b/stm32f091/esp8266.c @@ -2,210 +2,88 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stm32f0xx.h> #include "esp8266.h" #include "setup.h" #include "consts.h" +#include "server.h" +#include "util.h" -void ws_esp8266_ATsendCommand(uint8_t* data){ - char dataChar[20]; - uint8_t Tx_send[]="AT+CIPSEND=0,"; - - itoa(strlen((char*)data),dataChar,10); - strcat((char*)Tx_send,dataChar); - strcat((char*)Tx_send,"\r\n"); - HAL_UART_Transmit(&huart1, Tx_send, strlen((char*)Tx_send),1000); - HAL_Delay(2000); - HAL_UART_Transmit(&huart1, data, strlen((char*)data),1000); - HAL_Delay(1000); - HAL_UART_Transmit(&huart2, data, strlen((char*)data),1000); - HAL_Delay(5000); -} -int ws_esp8266_checkOK(uint8_t *receiveData,int length){ - char *ret=""; - // char *ret1=""; - HAL_UART_Transmit(&huart2, receiveData,length,1000); - ret = strstr((char*)receiveData,"OK"); - // ret = strstr((char*)receiveData,"change"); - // memset(receiveData,0,30); - if((ret[0]='O') && (ret[1]=='K')){ - //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); - return 1; - - } -// else if((ret1[0]='c') && (ret1[1]=='h')){ -// //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); -// return 1; -// -// } - else{ - return 0; - } - +// macro for concise sending of multiple commands +#define ws_esp8266_send_seq(cmd) { \ + uint8_t _cmd[] = cmd; \ + ws_server_send(_cmd, sizeof(_cmd)); \ } -int ws_esp8266_receivingMsg(uint8_t *receiveData,int length){ - char *ret=""; - HAL_UART_Transmit(&huart2, receiveData,length,1000); - ret = strstr((char*)receiveData,"+IPD"); - // memset(receiveData,0,30); - - if((ret[0]='+') && (ret[1]=='I')){ - //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); - return 1; - - } - else{ - return 0; - } -} -int ws_esp8266_unlink(uint8_t *receiveData,int length){ - char *ret=""; - HAL_UART_Transmit(&huart2, receiveData,length,1000); - ret = strstr((char*)receiveData,"UNLINK"); - // memset(receiveData,0,30); - if((ret[0]='U') && (ret[1]=='N')){ - //HAL_UART_Transmit(&huart2, (uint8_t*)ret, sizeof(ret), 100); - return 1; +uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; +unsigned int g_ws_esp8266_dma_rx_head = 0; +unsigned int g_ws_esp8266_dma_rx_tail = 0; +uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; - } - else{ - return 0; - } +void DMA1_Ch1_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_rx); } +void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_tx); } +void USART1_IRQHandler(void) { + if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) { + __HAL_UART_CLEAR_IDLEFLAG(&huart1); + // https://stackoverflow.com/questions/71039052/hal-uartex-rxeventcallback-circular-dma-what-address-is-the-data + g_ws_esp8266_dma_rx_head = huart1.RxXferSize - huart1.hdmarx->Instance->CNDTR; + ws_esp8266_incoming_data_chunk(); + } + HAL_UART_IRQHandler(&huart1); } -void ws_esp8266_StartEsp(){ - uint8_t Tx_AT[]="AT\r\n"; - uint8_t Rx_buffer[10]={0}; - for(int i=0;i<3;i++){ - // HAL_UART_Transmit(&huart2, hier,sizeof(hier),100); - HAL_UART_Transmit(&huart1, Tx_AT,strlen((char*)Tx_AT), 100); - HAL_UART_Receive(&huart1, Rx_buffer, 10, 100); - - - HAL_UART_Transmit(&huart2, Rx_buffer,10,100); - HAL_Delay(5000); - //memset(Rx_buffer,0,sizeof(Rx_buffer)); +void ws_esp8266_incoming_data_chunk() { + if (g_ws_esp8266_dma_rx_head == g_ws_esp8266_dma_rx_tail) return; // no new data + if (g_ws_esp8266_dma_rx_head > g_ws_esp8266_dma_rx_tail) { + // read from tail until head + ws_server_req_incoming(&g_ws_esp8266_dma_rx_buffer[g_ws_esp8266_dma_rx_tail], + g_ws_esp8266_dma_rx_head - g_ws_esp8266_dma_rx_tail); + } else /* if (g_ws_esp8266_dma_rx_head < g_ws_esp8266_dma_rx_tail) */ { + // read from tail until end of buffer + ws_server_req_incoming(&g_ws_esp8266_dma_rx_buffer[g_ws_esp8266_dma_rx_tail], + WS_DMA_RX_BUFFER_SIZE - g_ws_esp8266_dma_rx_tail); + // read from buffer begin until head + ws_server_req_incoming(&g_ws_esp8266_dma_rx_buffer[0], // yes i know this looks dumb + g_ws_esp8266_dma_rx_head); } - + // finish read by shifting tail forward + g_ws_esp8266_dma_rx_tail = g_ws_esp8266_dma_rx_head; } -void ws_esp8266_disconnect(){ - int ret; - uint8_t Tx_disconnect[]="AT+CWQAP\r\n";uint8_t buffer[17]={0}; - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_disconnect,strlen((char*)Tx_disconnect), 100); - HAL_UART_Receive(&huart1, buffer, 17, 100); - HAL_Delay(2000); - if(ws_esp8266_checkOK(buffer,17)==1){ - ret=1; - } +void ws_esp8266_send(uint8_t* data, size_t size) { + size_t limited_size = WS_MIN(size, WS_DMA_TX_BUFFER_SIZE - 1); + memcpy(g_ws_esp8266_dma_tx_buffer, data, limited_size); + g_ws_esp8266_dma_tx_buffer[limited_size] = 0x00; - } +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); + HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer), 100); +#endif - HAL_Delay(5000); + HAL_UART_Transmit_DMA(&huart1, g_ws_esp8266_dma_tx_buffer, strlen((char*) g_ws_esp8266_dma_tx_buffer)); + __HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE); } -void ws_esp8266_mode(){ - int ret; - uint8_t buffer1[20]={0}; uint8_t Tx_mode[]="AT+CWMODE=1\r\n"; - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_mode,strlen((char*)Tx_mode), 100); - HAL_UART_Receive(&huart1, buffer1, 20, 100); - HAL_Delay(1000); - - if(ws_esp8266_checkOK(buffer1,20)==1){ - ret=1; - - } - - } - - HAL_Delay(1000); +void ws_esp8266_connect() { + ws_esp8266_send_seq("AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"); } -void ws_esp8266_connect(){ - uint8_t Tx_network[]="AT+CWJAP=\"" WS_ESP8266_WLAN_SSID "\",\"" WS_ESP8266_WLAN_PASSWD "\"\r\n"; - - - HAL_UART_Transmit(&huart1, Tx_network,strlen((char*)Tx_network),1000); - HAL_Delay(10000); -// HAL_UART_Transmit(&huart1, Tx_network,sizeof(Tx_network),1000); -// HAL_Delay(10000); - - - - -} -void ws_esp8266_serveraan(){ - int ret; - uint8_t buffer1[30]={0}; uint8_t Tx_server[]="AT+CIPSERVER=1," WS_SERVER_PORT "\r\n"; - - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_server,strlen((char*)Tx_server), 100); - HAL_UART_Receive(&huart1, buffer1, 30, 100); - HAL_Delay(2000); - - if(ws_esp8266_checkOK(buffer1,30)==1){ - ret=1; - - } - - } - - HAL_Delay(1000); +void ws_esp8266_ap_client_mode() { + ws_esp8266_send_seq("AT+CWMODE=1\r\n"); } -void ws_esp8266_serveruit(){ - //int ret; - //uint8_t buffer1[27]={0}; - uint8_t Tx_server[]="AT+CIPSERVER=0\r\n"; -// -// while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_server,strlen((char*)Tx_server), 100); -// HAL_UART_Receive(&huart1, buffer1, 27, 100); - HAL_Delay(3000); - -// if(unlink(buffer1,27)==1){ -// ret=1; -// -// } -// -// } - HAL_Delay(1000); +void ws_esp8266_start_tcp_server() { + ws_esp8266_send_seq("AT+CIPSERVER=0\r\n"); // stop tcp server (if running) + ws_esp8266_send_seq("AT+CIPMUX=1\r\n"); // enable multiplexing (allow multiple connections) + ws_esp8266_send_seq("AT+CIPSERVER=1," WS_SERVER_PORT "\r\n"); // start tcp server } -void ws_esp8266_mux(){ - int ret; - uint8_t buffer2[20]={0}; uint8_t Tx_mux[]="AT+CIPMUX=1\r\n"; - while(ret!=1){ - - HAL_UART_Transmit(&huart1, Tx_mux,strlen((char*)Tx_mux), 100); - HAL_UART_Receive(&huart1, buffer2, 20, 100); - HAL_Delay(2000); - - if(ws_esp8266_checkOK(buffer2,20)==1){ - ret=1; - - } - - } - - HAL_Delay(5000); +void ws_esp8266_set_mac() { + ws_esp8266_send_seq("AT+CIPSTAMAC=\"" WS_ESP8266_WLAN_MAC "\"\r\n"); } -void ws_esp8266_close(){ - - uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n"; - - - HAL_UART_Transmit(&huart1, Tx_close,strlen((char*)Tx_close), 100); - - HAL_Delay(3000); +void ws_esp8266_set_ip() { + ws_esp8266_send_seq("AT+CIPSTA=\"" WS_ESP8266_WLAN_IP "\"\r\n"); } - diff --git a/stm32f091/esp8266.h b/stm32f091/esp8266.h index c09a557..94a7356 100644 --- a/stm32f091/esp8266.h +++ b/stm32f091/esp8266.h @@ -1,16 +1,38 @@ #pragma once +#include <stm32f0xx_hal.h> +#include <stdlib.h> #include <stdint.h> +#include <stdbool.h> -void ws_esp8266_ATsendCommand(uint8_t* data); -int ws_esp8266_checkOK(uint8_t *receiveData,int length); -int ws_esp8266_receivingMsg(uint8_t *receiveData,int length); -int ws_esp8266_unlink(uint8_t *receiveData,int length); -void ws_esp8266_StartEsp(); -void ws_esp8266_disconnect(); -void ws_esp8266_mode(); +#include "consts.h" + +/** @brief DMA rx buffer */ +extern uint8_t g_ws_esp8266_dma_rx_buffer[WS_DMA_RX_BUFFER_SIZE]; +/** @brief null-terminated tx buffer string */ +extern uint8_t g_ws_esp8266_dma_tx_buffer[WS_DMA_TX_BUFFER_SIZE]; + +/** @brief DMA1 channel 2-3 & DMA2 channel 1-2 interrupt handler */ +void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void); +/** @brief DMA1 channel 1 interrupt handler */ +void DMA1_Ch1_IRQHandler(void); +/** @brief USART1 interrupt handler */ +void USART1_IRQHandler(void); + +/** @brief send data to esp over uart with dma */ +void ws_esp8266_send(uint8_t* data, size_t size); + +/** @brief line idle, handle new data on dma buffer */ +void ws_esp8266_incoming_data_chunk(); + +/** @brief connect to access point using wifi.h credentials */ void ws_esp8266_connect(); -void ws_esp8266_serveraan(); -void ws_esp8266_serveruit(); -void ws_esp8266_mux(); -void ws_esp8266_close(); +/** @brief set esp to access point client mode (connect to AP, not become one) */ +void ws_esp8266_ap_client_mode(); +/** @brief initialize and configure the tcp server */ +void ws_esp8266_start_tcp_server(); + +/** @brief set mac address of the esp client */ +void ws_esp8266_set_mac(); +/** @brief set static ip address of the esp client */ +void ws_esp8266_set_ip(); diff --git a/stm32f091/main.c b/stm32f091/main.c index 7cb0718..67c0a8d 100644 --- a/stm32f091/main.c +++ b/stm32f091/main.c @@ -5,18 +5,9 @@ #include "main.h" #include "setup.h" #include "sensor.h" -#include "backlog.h" int main() { ws_io_setup(); - HAL_GPIO_Init(GPIOA, &(GPIO_InitTypeDef) { - .Pin = GPIO_PIN_5, - .Mode = GPIO_MODE_OUTPUT_PP, - .Pull = GPIO_NOPULL - }); - - ws_backlog_alloc(24 * 60); - - xTaskCreate(ws_sensor_read_task, "sensor", 128, NULL, 1, NULL); + xTaskCreate(ws_sensor_read_task, "sensor", 64, NULL, 1, NULL); vTaskStartScheduler(); } diff --git a/stm32f091/makefile b/stm32f091/makefile index 20424c3..dd03761 100644 --- a/stm32f091/makefile +++ b/stm32f091/makefile @@ -4,6 +4,7 @@ OC = arm-none-eabi-objcopy RM = rm -f TARGET = main +HOST=$(strip $(shell uname -o)) include ../shared/shared.mk @@ -13,7 +14,6 @@ SHARED_FLAGS += -Wall SHARED_FLAGS += -Wextra # SHARED_FLAGS += -Wno-register SHARED_FLAGS += -Wa,--defsym,CALL_ARM_SYSTEM_INIT=1 -# SHARED_FLAGS += -I/usr/arm-none-eabi/include/ SHARED_FLAGS += -I./lib/STM32-base-STM32Cube/HAL/STM32F0xx/inc SHARED_FLAGS += -I./lib/STM32-base-STM32Cube/HAL/STM32F0xx/inc/Legacy SHARED_FLAGS += -I./lib/STM32-base-STM32Cube/CMSIS/ARM/inc @@ -22,7 +22,10 @@ SHARED_FLAGS += -I./lib/STM32-base/startup SHARED_FLAGS += -I./lib/FreeRTOS-Kernel/include SHARED_FLAGS += -I./lib/FreeRTOS-Kernel/portable/GCC/ARM_CM0/ SHARED_FLAGS += -I. -SHARED_FLAGS += -O1 +ifeq ($(HOST),GNU/Linux) +SHARED_FLAGS += -I/usr/arm-none-eabi/include/ +endif +# SHARED_FLAGS += -O1 SHARED_FLAGS += -ffunction-sections SHARED_FLAGS += -fdata-sections SHARED_FLAGS += -Wl,--gc-sections @@ -89,7 +92,7 @@ $(TARGET).elf: $(OBJS) $(LD) $(LFLAGS) $^ -o $@ flash: $(TARGET).bin - st-flash write $(TARGET).bin 0x08000000 + st-flash --reset write $(TARGET).bin 0x08000000 compile_commands: clean compiledb make -n diff --git a/stm32f091/protocol.c b/stm32f091/protocol.c index 589ee5d..ca46b3b 100644 --- a/stm32f091/protocol.c +++ b/stm32f091/protocol.c @@ -3,31 +3,36 @@ #include "../shared/protocol.h" #include "backlog.h" #include "util.h" +#include "server.h" +#include "esp8266.h" void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { static unsigned int record_amount = 0; const char* response_header = "id,temperature,humidity,atmospheric_pressure\n"; - const size_t response_line_size = sizeof("xxxx,xx,xx,xx\n"); + const unsigned int response_line_len = strlen("xxxx,xx,xx,xx\n"); if (!send) { response->success = WS_PROTOCOL_CMD_RETURN_OK; - if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; - record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); response->csh = true; response->msg = ws_bin_s_alloc(0); - response->msg->bytes = strlen(response_header) + response_line_size * record_amount; + response->msg->bytes = 0; + if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + else { + record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); + response->msg->bytes = strlen(response_header) + response_line_len * record_amount; + } } else { + if (response->success == WS_PROTOCOL_CMD_RETURN_ERROR) return; ws_protocol_send_data(response_header, strlen(response_header)); - char line[response_line_size + 1]; // +1 for null terminator -> sprintf + char line[response_line_len + 1]; // + 1 for string terminator for (unsigned int i = 0; i < record_amount; i++) { ws_s_backlog_record* record = ws_backlog_get_last_record(i); sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); - ws_protocol_send_data(line, response_line_size); + ws_protocol_send_data(line, response_line_len); } } } void ws_protocol_send_data(const char* data, unsigned int length) { - //TODO: implement on esp data channels - HAL_UART_Transmit(&huart2, (uint8_t*) data, length, HAL_MAX_DELAY); + ws_server_buffer_send_append((uint8_t*) data, length); } diff --git a/stm32f091/readme.md b/stm32f091/readme.md index 97492d5..d2758b5 100644 --- a/stm32f091/readme.md +++ b/stm32f091/readme.md @@ -4,4 +4,8 @@ - make sure to initialize the git submodules - all warnings from source files in the lib/ subfolder are hidden - copy wifi.def.h to wifi.h and edit the network credentials +- the initialization code is broken in some way which means that a soft reset + is required for the uart dma to work, either (a) press the reset button on + the development board after plugging in, or (b) run `st-flash reset` after + plugging in. diff --git a/stm32f091/server.c b/stm32f091/server.c index 4840527..112d23a 100644 --- a/stm32f091/server.c +++ b/stm32f091/server.c @@ -3,55 +3,225 @@ #include <stdlib.h> #include <string.h> -#include "setup.h" -#include "server.h" +#include "../shared/protocol.h" #include "esp8266.h" +#include "server.h" +#include "setup.h" +#include "consts.h" +#include "util.h" + +ws_s_server_parser g_ws_server_parser = { + .last_response = WS_SERVER_RC_NONE, + .mode = WS_SERVER_LM_IDLE, + + .current_channel = 0, + .channel_data_length = 0, + .channel_data_counter = 0, + .channel_listen_mode = WS_SERVER_CL_CHANNEL_ID, + + .rc = { 0 }, +}; + +static ws_s_protocol_req_parser_state* g_ws_protocol_parsers[WS_SERVER_MAX_CHANNELS] = {0}; +static unsigned int g_ws_esp8266_dma_tx_buffer_head = 0; +static unsigned int g_ws_esp8266_dma_tx_buffer_tail = 0; +static unsigned int g_ws_esp8266_dma_tx_buffer_cs = 0; // chunk size + +void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore) { + if (ignore) return; + if (channel >= WS_SERVER_MAX_CHANNELS) return; + + if (g_ws_protocol_parsers[channel] == NULL) { + g_ws_protocol_parsers[channel] = ws_protocol_req_parser_alloc(); + } -void ws_server_demo() { - uint8_t ok[]= "ok\r\n"; - uint8_t hier[]= "hier\r\n"; - //disconnect();//connect();// - - ws_esp8266_StartEsp(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_close(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_serveruit(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_mux(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - ws_esp8266_mode(); - HAL_UART_Transmit(&huart2, hier,sizeof(hier),1000); - - ws_esp8266_serveraan(); - HAL_UART_Transmit(&huart2, ok,sizeof(ok),1000); - uint8_t receive[24]={0}; - uint8_t sendToQTData[]="gelukt"; - uint8_t test[]="test"; - //int ret; - //ATsendCommand(sendToQTData); - while (1) - { - - if(receive[0]=='\0') - { - HAL_UART_Receive_IT(&huart1, receive, 24); + ws_protocol_parse_req_byte(g_ws_protocol_parsers[channel], byte); +} + +void ws_server_req_finish(unsigned int channel, bool ignore) { + if (ignore) return; + if (channel >= WS_SERVER_MAX_CHANNELS) return; + + if (g_ws_protocol_parsers[channel] != NULL) { + ws_protocol_req_parser_free(g_ws_protocol_parsers[channel]); + g_ws_protocol_parsers[channel] = NULL; + } +} + +static bool ws_server_is_response(char data, uint8_t* counter, const char* cmd, unsigned short cmd_len) { + if (data == cmd[*counter]) *counter += 1; + else *counter = 0; + if (*counter == cmd_len) return true; + return false; +} + +// TODO: next_few_bytes_are assumes that the complete search string is in the +// buffer, so won't work for buffer cutoffs +#define next_few_bytes_are(code) (((i + sizeof(code) - 2) < size) && (strncmp((char*)&data[i], code, sizeof(code) - 1) == 0)) +void ws_server_req_incoming(uint8_t* data, size_t size) { +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_RX); + HAL_UART_Transmit(&huart2, data, size, 100); +#endif + + for (unsigned int i = 0; i < size; i++) { + uint8_t byte = data[i]; + + switch (g_ws_server_parser.mode) { + case WS_SERVER_LM_CMD_ECHO: { + if (byte == '\n') g_ws_server_parser.mode = WS_SERVER_LM_STATUS_CODE; + break; + } + case WS_SERVER_LM_STATUS_CODE: { + bool code_got = false; + if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_ok, "OK", 2)) { + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_OK; + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_error, "ERROR", 5)) { + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_ERR; + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_fail, "FAIL", 4)) { + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_ERR; + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.s_busy, "busy p...", 9)) { + code_got = true; + g_ws_server_parser.last_response = WS_SERVER_RC_BUSY; + } + if (code_got) g_ws_server_parser.mode = WS_SERVER_LM_IDLE; + break; } - else - { - HAL_UART_Transmit(&huart2, test,strlen((char*)test),1000); - HAL_Delay(5000); - - // if(receivingMsg(receive, 24)==1) - // { - // ret=1; - ws_esp8266_ATsendCommand(sendToQTData); - ws_esp8266_close(); - memset(receive,0,24); - //} + case WS_SERVER_LM_IDLE: { + if (ws_server_is_response(byte, &g_ws_server_parser.rc.i_ipd, "+IPD,", 5)) { + g_ws_server_parser.mode = WS_SERVER_LM_IPD_LISTENING; + } else if (ws_server_is_response(byte, &g_ws_server_parser.rc.i_prompt, ">", 1)) { + // ^^^ this is ">" on official espressif firmware, "> " on ai-thinker firmware + g_ws_server_parser.mode = WS_SERVER_LM_CIPSEND_LISTENING; + ws_server_buffer_send_chunk(); + } + break; } + case WS_SERVER_LM_IPD_LISTENING: { + switch (g_ws_server_parser.channel_listen_mode) { + case WS_SERVER_CL_CHANNEL_ID: { + if (byte == ',') { + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_LENGTH; + break; + } + g_ws_server_parser.current_channel *= 10; + g_ws_server_parser.current_channel += byte - '0'; // ascii to int + break; + } + case WS_SERVER_CL_DATA_LENGTH: { + if (byte == ':') { + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_DATA_READ; + if (g_ws_server_parser.channel_data_length > WS_PROTOCOL_CMD_BUFFER_LEN) + g_ws_server_parser.channel_data_ignore = true; + break; + } + g_ws_server_parser.channel_data_length *= 10; + g_ws_server_parser.channel_data_length += byte - '0'; // ascii to int + break; + } + case WS_SERVER_CL_DATA_READ: { + ws_server_req_parse_byte(g_ws_server_parser.current_channel, byte, g_ws_server_parser.channel_data_ignore); + g_ws_server_parser.channel_data_counter++; + if (g_ws_server_parser.channel_data_counter == g_ws_server_parser.channel_data_length) { + g_ws_server_parser.current_channel = 0; + g_ws_server_parser.channel_data_counter = 0; + g_ws_server_parser.channel_data_length = 0; + g_ws_server_parser.channel_listen_mode = WS_SERVER_CL_CHANNEL_ID; + ws_server_req_finish(g_ws_server_parser.current_channel, g_ws_server_parser.channel_data_ignore); + g_ws_server_parser.mode = WS_SERVER_LM_IDLE; + ws_server_buffer_request_chunk_send(); + } + break; + } + default: {} + } + break; + } + case WS_SERVER_LM_CIPSEND_LISTENING: { + if (ws_server_is_response(byte, &g_ws_server_parser.rc.l_send_ok, "SEND OK", 7) || ws_server_is_response(byte, &g_ws_server_parser.rc.l_error, "ERROR", 5)) { + ws_server_buffer_request_chunk_send(); + } + break; + } + default: {} + } + } +} + +/** @brief get amount of bytes in g_ws_esp8266_dma_tx_buffer until \n */ +static unsigned int ws_server_next_line_length() { + for (unsigned int i = g_ws_esp8266_dma_tx_buffer_tail; i <= g_ws_esp8266_dma_tx_buffer_head; i++) + if (g_ws_esp8266_dma_tx_buffer[i] == '\n') return i - g_ws_esp8266_dma_tx_buffer_tail + 1; + return g_ws_esp8266_dma_tx_buffer_head - g_ws_esp8266_dma_tx_buffer_tail; +} +void ws_server_send(uint8_t* data, size_t size) { + g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; + ws_esp8266_send(data, size); + while (g_ws_server_parser.mode != WS_SERVER_LM_IDLE) {}; +} +void ws_server_buffer_send_append(uint8_t* data, size_t size) { + // TODO: buffer overrun protection + // while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); // make sure buffer isn't used + strncpy((char*) &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_head], (char*) data, size); // append string + g_ws_esp8266_dma_tx_buffer_head += size; // shift head +} - } +void ws_server_buffer_request_chunk_send() { + g_ws_esp8266_dma_tx_buffer_cs = ws_server_next_line_length(); + + char* cmd = NULL; + size_t len; + + if (g_ws_esp8266_dma_tx_buffer_cs > 0) { + len = asiprintf(&cmd, "AT+CIPSEND=%d,%d\r\n", g_ws_server_parser.current_channel, g_ws_esp8266_dma_tx_buffer_cs); + } else { + len = asiprintf(&cmd, "AT+CIPCLOSE=%d\r\n", g_ws_server_parser.current_channel); + } + free(cmd); + + g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; + +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); + HAL_UART_Transmit(&huart2, (uint8_t*) cmd, len, 100); +#endif + HAL_UART_Transmit(&huart1, (uint8_t*) cmd, len, 100); +} + +void ws_server_buffer_send_chunk() { +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); + HAL_UART_Transmit(&huart2, &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_tail], g_ws_esp8266_dma_tx_buffer_cs, 100); +#endif + HAL_UART_Transmit(&huart1, &g_ws_esp8266_dma_tx_buffer[g_ws_esp8266_dma_tx_buffer_tail], g_ws_esp8266_dma_tx_buffer_cs, 100); + g_ws_esp8266_dma_tx_buffer_tail += g_ws_esp8266_dma_tx_buffer_cs; + + if (g_ws_esp8266_dma_tx_buffer_head == g_ws_esp8266_dma_tx_buffer_tail) { + g_ws_esp8266_dma_tx_buffer_head = g_ws_esp8266_dma_tx_buffer_tail = 0; + } + +// #ifdef WS_DBG_PRINT_ESP_OVER_USART2 +// ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_TX); +// HAL_UART_Transmit(&huart2, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_head, 100); +// #endif +// +// HAL_UART_Transmit(&huart1, g_ws_esp8266_dma_tx_buffer, g_ws_esp8266_dma_tx_buffer_head, 100); +// g_ws_esp8266_dma_tx_buffer_head = 0; +// +// HAL_UART_Transmit(&huart1, (uint8_t*) "+++", 3, 100); +} + +// TODO: refactor this +void ws_server_req_respond_end(unsigned int channel) { + char* cmd = NULL; + size_t len = asiprintf(&cmd, "AT+CIPCLOSE=%d\r\n", channel); + g_ws_server_parser.mode = WS_SERVER_LM_CMD_ECHO; + ws_esp8266_send((uint8_t*) cmd, len); + while (!__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)); + free(cmd); } diff --git a/stm32f091/server.h b/stm32f091/server.h index e134079..07c49d9 100644 --- a/stm32f091/server.h +++ b/stm32f091/server.h @@ -2,11 +2,53 @@ #include <stdlib.h> #include <stdint.h> +#include <stdbool.h> -// void ws_server_demo(); -// -// /** FreeRTOS task that listens for incoming requests from the esp */ -// void ws_server_listen_task(); +typedef enum { + WS_SERVER_LM_CMD_ECHO, /** @brief listen for echo of sent command */ + WS_SERVER_LM_STATUS_CODE, /** @brief listen for busy, ERROR or OK */ + WS_SERVER_LM_IDLE, /** @brief listen for incoming +IPD commands */ + WS_SERVER_LM_IPD_LISTENING, /** @brief +IPD received, now reading data */ + WS_SERVER_LM_CIPSEND_LISTENING, /** @brief AT+CIPSEND sent, now reading data */ +} ws_e_server_listen_mode; + +typedef enum { + WS_SERVER_CL_CHANNEL_ID, /** @brief listen channel id */ + WS_SERVER_CL_DATA_LENGTH, /** @brief listen for data byte length */ + WS_SERVER_CL_DATA_READ, /** @brief listen for data and pipe to ws_protocol_parse_req_byte */ +} ws_e_channel_listen_mode; + +typedef enum { + WS_SERVER_RC_NONE = -1, + WS_SERVER_RC_BUSY, + WS_SERVER_RC_ERR, + WS_SERVER_RC_OK, +} ws_e_server_response_code; + +typedef struct { + uint8_t s_ok; /** @brief status code OK */ + uint8_t s_error; /** @brief status code OK */ + uint8_t s_fail; /** @brief status code OK */ + uint8_t s_busy; /** @brief status code OK */ + uint8_t i_ipd; /** @brief idle +IPD, */ + uint8_t i_prompt; /** @brief idle > */ + uint8_t l_send_ok; /** @brief ipd listen SEND OK */ + uint8_t l_error; /** @brief ipd listen ERROR */ +} ws_s_server_parser_response_counter; + +typedef struct { + ws_e_server_listen_mode mode; + ws_e_server_response_code last_response; + unsigned int current_channel; + unsigned int channel_data_length; + unsigned int channel_data_counter; + ws_e_channel_listen_mode channel_listen_mode; + bool channel_data_ignore; + ws_s_server_parser_response_counter rc; +} ws_s_server_parser; + +/** @brief global server parser struct */ +extern ws_s_server_parser g_ws_server_parser; /** * @brief +IPD incoming request handler @@ -20,10 +62,38 @@ */ void ws_server_req_incoming(uint8_t* data, size_t size); -// TODO: server req incoming implementation -// -// example +IPD command: -// +IPD,0,15:last-records 5\n -// -// TODO: protocol req response parser +// /** @brief send AT response header for incoming request on specific channel */ +// void ws_server_req_respond_start(unsigned int channel); +// /** @brief send AT tcp close on specific channel */ +// void ws_server_req_respond_end(unsigned int channel); + +/** @brief send data to esp, waiting until server returns to idle mode */ +void ws_server_send(uint8_t* data, size_t size); + +/** + * @brief parse byte from channel + * + * automatically creates parser struct and passes data onto protocol parser + * functions + * + * @param channel request channel + * @param byte data byte + * @param ignore ignore mode + */ +void ws_server_req_parse_byte(unsigned int channel, uint8_t byte, bool ignore); + +/** + * @brief close connection + * + * deallocates any parser struct that were automatically created in + * ws_server_req_parse_byte + * + * @param channel request channel + * @param ignore ignore mode + */ +void ws_server_req_finish(unsigned int channel, bool ignore); + +void ws_server_buffer_send_append(uint8_t* data, size_t size); +void ws_server_buffer_request_chunk_send(); +void ws_server_buffer_send_chunk(); diff --git a/stm32f091/setup.c b/stm32f091/setup.c index fec2b7c..ef00a29 100644 --- a/stm32f091/setup.c +++ b/stm32f091/setup.c @@ -5,7 +5,11 @@ #include <FreeRTOS.h> #include <task.h> +#include "esp8266.h" #include "setup.h" +#include "backlog.h" +#include "server.h" +#include "util.h" I2C_HandleTypeDef hi2c1 = { .Instance = I2C1, @@ -20,16 +24,14 @@ I2C_HandleTypeDef hi2c1 = { }; UART_HandleTypeDef huart1 = { - .Instance = USART1, - .Init.BaudRate = 115200, - .Init.WordLength = UART_WORDLENGTH_8B, - .Init.StopBits = UART_STOPBITS_1, - .Init.Parity = UART_PARITY_NONE, - .Init.Mode = UART_MODE_TX_RX, - .Init.HwFlowCtl = UART_HWCONTROL_NONE, - .Init.OverSampling = UART_OVERSAMPLING_16, - .Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE, - .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT, + .Instance = USART1, + .Init.BaudRate = 115200, + .Init.WordLength = UART_WORDLENGTH_8B, + .Init.StopBits = UART_STOPBITS_1, + .Init.Parity = UART_PARITY_NONE, + .Init.Mode = UART_MODE_TX_RX, + .Init.HwFlowCtl = UART_HWCONTROL_NONE, + .Init.OverSampling = UART_OVERSAMPLING_16, }; UART_HandleTypeDef huart2 = { @@ -45,10 +47,33 @@ UART_HandleTypeDef huart2 = { .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT, }; +DMA_HandleTypeDef hdma_usart1_rx = { + .Instance = DMA1_Channel1, + .Init.Direction = DMA_PERIPH_TO_MEMORY, + .Init.PeriphInc = DMA_PINC_DISABLE, + .Init.MemInc = DMA_MINC_ENABLE, + .Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE, + .Init.MemDataAlignment = DMA_MDATAALIGN_BYTE, + .Init.Mode = DMA_CIRCULAR, + .Init.Priority = DMA_PRIORITY_LOW, +}; + +DMA_HandleTypeDef hdma_usart1_tx = { + .Instance = DMA1_Channel2, + .Init.Direction = DMA_MEMORY_TO_PERIPH, + .Init.PeriphInc = DMA_PINC_DISABLE, + .Init.MemInc = DMA_MINC_ENABLE, + .Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE, + .Init.MemDataAlignment = DMA_MDATAALIGN_BYTE, + .Init.Mode = DMA_NORMAL, + .Init.Priority = DMA_PRIORITY_LOW, +}; + static void ws_io_clock_setup(); static void ws_io_i2c_setup(); static void ws_io_usart1_setup(); static void ws_io_usart2_setup(); +static void ws_io_dma_setup(); static void ws_setup_error_handler(); void ws_io_setup() { @@ -56,8 +81,36 @@ void ws_io_setup() { ws_io_clock_setup(); ws_io_i2c_setup(); + ws_io_dma_setup(); ws_io_usart1_setup(); ws_io_usart2_setup(); + ws_io_dma_setup(); + + HAL_GPIO_Init(GPIOA, &(GPIO_InitTypeDef) { + .Pin = GPIO_PIN_5, + .Mode = GPIO_MODE_OUTPUT_PP, + .Pull = GPIO_NOPULL + }); + + // TODO: remove debug size + ws_backlog_alloc(24 * 60); + // ws_backlog_alloc(10); + +#ifdef WS_DBG_PRINT_ESP_OVER_USART2 + ws_dbg_set_usart2_tty_color(WS_DBG_TTY_COLOR_DBGMSG); + const char restart_str[] = "\r\n--- stm restart ---\r\n"; + HAL_UART_Transmit(&huart2, (uint8_t*) restart_str, strlen(restart_str), 100); +#endif + + ws_esp8266_ap_client_mode(); +#ifdef WS_ESP8266_WLAN_MAC + ws_esp8266_set_mac(); +#endif +#ifdef WS_ESP8266_WLAN_IP + ws_esp8266_set_ip(); +#endif + do ws_esp8266_connect(); while (g_ws_server_parser.last_response == WS_SERVER_RC_ERR); + ws_esp8266_start_tcp_server(); } static void ws_io_clock_setup() { @@ -97,11 +150,27 @@ static void ws_io_i2c_setup() { static void ws_io_usart1_setup() { if (HAL_UART_Init(&huart1) != HAL_OK) return ws_setup_error_handler(); + + HAL_UART_Receive_DMA(&huart1, g_ws_esp8266_dma_rx_buffer, WS_DMA_RX_BUFFER_SIZE); + __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); + + __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // enable receive intterupts + __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // enable idle line detection } static void ws_io_usart2_setup() { if (HAL_UART_Init(&huart2) != HAL_OK) return ws_setup_error_handler(); +} + +static void ws_io_dma_setup() { + __HAL_RCC_DMA1_CLK_ENABLE(); + + // interrupt priorities + HAL_NVIC_SetPriority(DMA1_Ch1_IRQn, 3, 0); + HAL_NVIC_EnableIRQ(DMA1_Ch1_IRQn); + HAL_NVIC_SetPriority(DMA1_Ch2_3_DMA2_Ch1_2_IRQn, 3, 0); + HAL_NVIC_EnableIRQ(DMA1_Ch2_3_DMA2_Ch1_2_IRQn); } void HAL_MspInit() { @@ -136,6 +205,14 @@ void HAL_UART_MspInit(UART_HandleTypeDef *huart) { .Alternate = GPIO_AF1_USART1, }); + // DMA setup + if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) return ws_setup_error_handler(); + __HAL_DMA1_REMAP(HAL_DMA1_CH1_USART1_RX); + __HAL_LINKDMA(huart, hdmarx, hdma_usart1_rx); + if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) return ws_setup_error_handler(); + __HAL_DMA1_REMAP(HAL_DMA1_CH2_USART1_TX); + __HAL_LINKDMA(huart, hdmatx, hdma_usart1_tx); + // USART1 interrupt Init HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); diff --git a/stm32f091/setup.h b/stm32f091/setup.h index 04fa177..d459635 100644 --- a/stm32f091/setup.h +++ b/stm32f091/setup.h @@ -9,6 +9,8 @@ extern I2C_HandleTypeDef hi2c1; extern UART_HandleTypeDef huart1; extern UART_HandleTypeDef huart2; +extern DMA_HandleTypeDef hdma_usart1_rx; +extern DMA_HandleTypeDef hdma_usart1_tx; void ws_io_setup(); diff --git a/stm32f091/todo.md b/stm32f091/todo.md new file mode 100644 index 0000000..1d42bf8 --- /dev/null +++ b/stm32f091/todo.md @@ -0,0 +1,28 @@ +# things that have to get fixed before monday + +- [ ] more documentation in header files (for both client and stm code) +- [ ] design/architecture document +- [x] more tests in the test document +- [ ] handle errors from `AT+CIPSEND`, these look like this: + ``` + > AT0,CONNECT + + > +IPD,0,15:last-records 5<0a> + < AT+CIPSEND=0,125 + > AT+CIPSEND=0,125 + + > ERROR + ``` + +## `// TODO:`'s + +- [ ] `sensor.c:24: return (uint8_t) temp_c; //TODO: convert with range -> util.h` +- [ ] `sensor.c:36: return (uint8_t) humidity; //TODO: convert with range -> util.h` +- [ ] `sensor.c:51: return (uint8_t) val; // TODO: convert with range` +- [ ] `server.c:47:// TODO: next_few_bytes_are assumes that the complete search string is in the` +- [ ] `server.c:146: // TODO: buffer overrun protection` +- [ ] `server.c:152:// TODO: refactor this` +- [ ] `server.c:165:// TODO: refactor this` +- [ ] `server.c:174:// TODO: refactor this` +- [ ] `setup.c:95: // TODO: remove debug size` +- [ ] `setup.c:187: .Pin = GPIO_PIN_8|GPIO_PIN_9, //TODO: use #defines in setup.h` diff --git a/stm32f091/util.h b/stm32f091/util.h index 92f093f..11bee6f 100644 --- a/stm32f091/util.h +++ b/stm32f091/util.h @@ -8,9 +8,44 @@ #include "setup.h" #include "../shared/util.h" +#define WS_DBG_TTY_COLOR_BLK 0x0 +#define WS_DBG_TTY_COLOR_RED 0x1 +#define WS_DBG_TTY_COLOR_GRN 0x2 +#define WS_DBG_TTY_COLOR_YLW 0x3 +#define WS_DBG_TTY_COLOR_BLU 0x4 +#define WS_DBG_TTY_COLOR_VLT 0x5 +#define WS_DBG_TTY_COLOR_CYN 0x6 +#define WS_DBG_TTY_COLOR_WHI 0x7 +#define WS_DBG_TTY_COLOR_BR_BLK 0x8 +#define WS_DBG_TTY_COLOR_BR_RED 0x9 +#define WS_DBG_TTY_COLOR_BR_GRN 0xa +#define WS_DBG_TTY_COLOR_BR_YLW 0xb +#define WS_DBG_TTY_COLOR_BR_BLU 0xc +#define WS_DBG_TTY_COLOR_BR_VLT 0xd +#define WS_DBG_TTY_COLOR_BR_CYN 0xe +#define WS_DBG_TTY_COLOR_BR_WHI 0xf + +// serial debug color scheme +#define WS_DBG_TTY_COLOR_DBGMSG WS_DBG_TTY_COLOR_BR_BLK +#define WS_DBG_TTY_COLOR_TX WS_DBG_TTY_COLOR_GRN +#define WS_DBG_TTY_COLOR_RX WS_DBG_TTY_COLOR_RED + +#define debugger asm("nop") + +// unused +// #define WS_DBG_TTY_COLOR_CMD_ECHO WS_DBG_TTY_COLOR_BLK +// #define WS_DBG_TTY_COLOR_STATUS_CODE WS_DBG_TTY_COLOR_YLW +// #define WS_DBG_TTY_COLOR_IDLE WS_DBG_TTY_COLOR_VLT +// #define WS_DBG_TTY_COLOR_IPD_LISTENING WS_DBG_TTY_COLOR_GRN +// #define WS_DBG_TTY_COLOR_CIPSEND_LISTENING WS_DBG_TTY_COLOR_RED + #define ws_usb_printf(fmt, ...) { \ char temp[255]; \ snprintf(temp, 255, fmt, ##__VA_ARGS__); \ HAL_UART_Transmit(&huart2, (uint8_t*) temp, sizeof(char) * strlen(temp), HAL_MAX_DELAY); \ } +#define ws_dbg_set_usart2_tty_color(color) { \ + uint8_t sgr[] = { 0x1b, 0x5b, 0x33 + (color > 7 ? 6 : 0), 0x30 + (color & 0b111), 0x6d }; \ + HAL_UART_Transmit(&huart2, sgr, sizeof(sgr), 100); \ +} diff --git a/stm32f091/wifi.def.h b/stm32f091/wifi.def.h index f0748d2..61e1706 100644 --- a/stm32f091/wifi.def.h +++ b/stm32f091/wifi.def.h @@ -2,4 +2,6 @@ #define WS_ESP8266_WLAN_SSID "Test" #define WS_ESP8266_WLAN_PASSWD "12345678" +// #define WS_ESP8266_WLAN_MAC "f2:9b:89:47:c4:f3" +// #define WS_ESP8266_WLAN_IP "192.168.2.69" |