aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-10-29 18:01:56 +0200
committerlonkaars <loek@pipeframe.xyz>2022-10-29 18:01:56 +0200
commit9e9ea9d07ed2a176d6f6e83b5b100da22d8fca50 (patch)
treea683bde4664dad75c3b5a1efbd4223a4ab3b40dd
parentead710db271795380207141f0add7278ba12ada0 (diff)
parentaae57dc32a843351fb2e17721afcd841bedec0a6 (diff)
Merge branch 'protocol' into dev
-rw-r--r--.gitignore1
-rw-r--r--.vscode/launch.json3
-rwxr-xr-xscripts/compiledb-full-path-mingw.sh2
-rwxr-xr-xscripts/dummy-server.py48
-rw-r--r--shared/protocol.c14
-rw-r--r--shared/protocol.h3
-rw-r--r--shared/util.c7
-rw-r--r--shared/util.h2
-rw-r--r--stm32f091/consts.h6
-rw-r--r--stm32f091/esp8266.c238
-rw-r--r--stm32f091/esp8266.h44
-rw-r--r--stm32f091/main.c11
-rw-r--r--stm32f091/makefile9
-rw-r--r--stm32f091/protocol.c21
-rw-r--r--stm32f091/readme.md4
-rw-r--r--stm32f091/server.c258
-rw-r--r--stm32f091/server.h90
-rw-r--r--stm32f091/setup.c97
-rw-r--r--stm32f091/setup.h2
-rw-r--r--stm32f091/todo.md28
-rw-r--r--stm32f091/util.h35
-rw-r--r--stm32f091/wifi.def.h2
22 files changed, 643 insertions, 282 deletions
diff --git a/.gitignore b/.gitignore
index 18c2616..90d7960 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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"