aboutsummaryrefslogtreecommitdiff
path: root/stm32f091
diff options
context:
space:
mode:
Diffstat (limited to 'stm32f091')
-rw-r--r--stm32f091/backlog.c36
-rw-r--r--stm32f091/backlog.h4
-rw-r--r--stm32f091/consts.h27
-rw-r--r--stm32f091/esp8266.c240
-rw-r--r--stm32f091/esp8266.h44
-rw-r--r--stm32f091/main.c12
-rw-r--r--stm32f091/makefile17
-rw-r--r--stm32f091/protocol.c41
-rw-r--r--stm32f091/readme.md11
-rw-r--r--stm32f091/sensor.c6
-rw-r--r--stm32f091/server.c255
-rw-r--r--stm32f091/server.h99
-rw-r--r--stm32f091/setup.c97
-rw-r--r--stm32f091/setup.h17
-rw-r--r--stm32f091/util.h51
-rw-r--r--stm32f091/wifi.def.h7
16 files changed, 673 insertions, 291 deletions
diff --git a/stm32f091/backlog.c b/stm32f091/backlog.c
index 3f21924..662fc75 100644
--- a/stm32f091/backlog.c
+++ b/stm32f091/backlog.c
@@ -2,33 +2,41 @@
#include "backlog.h"
-ws_s_backlog_database* WS_G_BACKLOG_DATABASE = NULL;
+ws_s_backlog_database* g_ws_backlog_database = NULL;
void ws_backlog_alloc(uint16_t record_amt) {
- WS_G_BACKLOG_DATABASE = malloc(sizeof(ws_s_backlog_database) + sizeof(ws_s_backlog_record) * record_amt);
- WS_G_BACKLOG_DATABASE->buffer_size = record_amt;
- WS_G_BACKLOG_DATABASE->buffer_start = 0;
- WS_G_BACKLOG_DATABASE->buffer_end = 0;
+ g_ws_backlog_database = malloc(sizeof(ws_s_backlog_database) + sizeof(ws_s_backlog_record) * record_amt);
+ g_ws_backlog_database->buffer_size = record_amt;
+ g_ws_backlog_database->buffer_start = 0;
+ g_ws_backlog_database->buffer_end = 0;
}
void ws_backlog_add_record(ws_s_backlog_record record) {
static uint16_t id = 0;
- WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].id = id++;
- WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].sens_atm_pressure = record.sens_atm_pressure;
- WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].sens_humidity = record.sens_humidity;
- WS_G_BACKLOG_DATABASE->records[WS_G_BACKLOG_DATABASE->buffer_end].sens_temperature = record.sens_temperature;
+ g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].id = id++;
+ g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_atm_pressure = record.sens_atm_pressure;
+ g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_humidity = record.sens_humidity;
+ g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_temperature = record.sens_temperature;
// shift buffer start/end
- WS_G_BACKLOG_DATABASE->buffer_end = (WS_G_BACKLOG_DATABASE->buffer_end + 1) % WS_G_BACKLOG_DATABASE->buffer_size;
- if (WS_G_BACKLOG_DATABASE->buffer_end == WS_G_BACKLOG_DATABASE->buffer_start)
- WS_G_BACKLOG_DATABASE->buffer_start = (WS_G_BACKLOG_DATABASE->buffer_start + 1) % WS_G_BACKLOG_DATABASE->buffer_size;
+ g_ws_backlog_database->buffer_end = (g_ws_backlog_database->buffer_end + 1) % g_ws_backlog_database->buffer_size;
+ if (g_ws_backlog_database->buffer_end == g_ws_backlog_database->buffer_start)
+ g_ws_backlog_database->buffer_start = (g_ws_backlog_database->buffer_start + 1) % g_ws_backlog_database->buffer_size;
}
ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index) {
- return &WS_G_BACKLOG_DATABASE->records[record_index];
+ return &g_ws_backlog_database->records[record_index];
}
ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset) {
- return ws_backlog_get_record((WS_G_BACKLOG_DATABASE->buffer_end - record_offset - 1) % WS_G_BACKLOG_DATABASE->buffer_size);
+ return ws_backlog_get_record((g_ws_backlog_database->buffer_end - record_offset - 1) % g_ws_backlog_database->buffer_size);
+}
+
+uint16_t ws_backlog_get_record_count() {
+ // add buffer_size to the result of the modulo operation if it's result is negative
+ // (only works when buffer_size is less than 2^15)
+ // this is a consequence of the way in which c handles negative numbers in modulo operations
+ int16_t mod = (g_ws_backlog_database->buffer_end - g_ws_backlog_database->buffer_start) % g_ws_backlog_database->buffer_size;
+ return mod < 0 ? mod + g_ws_backlog_database->buffer_size : mod;
}
diff --git a/stm32f091/backlog.h b/stm32f091/backlog.h
index 465b3c0..c8ea019 100644
--- a/stm32f091/backlog.h
+++ b/stm32f091/backlog.h
@@ -30,7 +30,7 @@ typedef struct {
#pragma pack(pop)
/** @brief global record backlog database pointer */
-extern ws_s_backlog_database* WS_G_BACKLOG_DATABASE;
+extern ws_s_backlog_database* g_ws_backlog_database;
/**
* @brief add record to database
@@ -55,3 +55,5 @@ ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index);
/** @brief get pointer to last record with offset `record_offset` from the database */
ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset);
+/** @brief return amount of valid records in database */
+uint16_t ws_backlog_get_record_count();
diff --git a/stm32f091/consts.h b/stm32f091/consts.h
new file mode 100644
index 0000000..3d2ef5a
--- /dev/null
+++ b/stm32f091/consts.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#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
+#define WS_PINOUT_I2C_SCL_PIN GPIO_PIN_8
+#define WS_PINOUT_I2C_SCL_PORT GPIOB
+
+#define WS_PINOUT_USART1_RX_PIN GPIO_PIN_10
+#define WS_PINOUT_USART1_RX_PORT GPIOA
+#define WS_PINOUT_USART1_TX_PIN GPIO_PIN_9
+#define WS_PINOUT_USART1_TX_PORT GPIOA
+
+#define WS_PINOUT_USART2_RX_PIN GPIO_PIN_3
+#define WS_PINOUT_USART2_RX_PORT GPIOA
+#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 6f12191..74ec347 100644
--- a/stm32f091/esp8266.c
+++ b/stm32f091/esp8266.c
@@ -2,208 +2,88 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stm32f0xx.h>
#include "esp8266.h"
#include "setup.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;
- }
-
+#include "consts.h"
+#include "server.h"
+#include "util.h"
+
+// 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;
- }
+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];
-}
-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;
-
- }
- 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_IT(&huart1, Tx_AT,strlen((char*)Tx_AT));
- HAL_UART_Receive_IT(&huart1, Rx_buffer, 10);
-
-
- 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_IT(&huart1, Tx_disconnect,strlen((char*)Tx_disconnect));
- HAL_UART_Receive_IT(&huart1, buffer, 17);
- 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_IT(&huart1, Tx_mode,strlen((char*)Tx_mode));
- HAL_UART_Receive_IT(&huart1, buffer1, 20);
- 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=\"Test\",\"12345678\"\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_ap_client_mode() {
+ ws_esp8266_send_seq("AT+CWMODE=1\r\n");
}
-void ws_esp8266_serveraan(){
- int ret;
- uint8_t buffer1[30]={0}; uint8_t Tx_server[]="AT+CIPSERVER=1,80\r\n";
-
- while(ret!=1){
-
- HAL_UART_Transmit_IT(&huart1, Tx_server,strlen((char*)Tx_server));
- HAL_UART_Receive_IT(&huart1, buffer1, 30);
- HAL_Delay(2000);
-
- if(ws_esp8266_checkOK(buffer1,30)==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_serveruit(){
- int ret;
- uint8_t buffer1[27]={0}; uint8_t Tx_server[]="AT+CIPSERVER=0\r\n";
-//
-// while(ret!=1){
-
- HAL_UART_Transmit_IT(&huart1, Tx_server,strlen((char*)Tx_server));
-// HAL_UART_Receive_IT(&huart1, buffer1, 27);
- HAL_Delay(3000);
-
-// if(unlink(buffer1,27)==1){
-// ret=1;
-//
-// }
-//
-// }
- HAL_Delay(1000);
+void ws_esp8266_set_mac() {
+ ws_esp8266_send_seq("AT+CIPSTAMAC=\"" WS_ESP8266_WLAN_MAC "\"\r\n");
}
-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_IT(&huart1, Tx_mux,strlen((char*)Tx_mux));
- HAL_UART_Receive_IT(&huart1, buffer2, 20);
- HAL_Delay(2000);
-
- if(ws_esp8266_checkOK(buffer2,20)==1){
- ret=1;
-
- }
-
- }
-
- HAL_Delay(5000);
-}
-void ws_esp8266_close(){
-
- uint8_t Tx_close[]="AT+CIPCLOSE=0\r\n";
-
-
- HAL_UART_Transmit_IT(&huart1, Tx_close,strlen((char*)Tx_close));
-
- 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 9235f1b..67c0a8d 100644
--- a/stm32f091/main.c
+++ b/stm32f091/main.c
@@ -5,19 +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);
- ws_sensor_read();
-
- 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 5a185de..dd03761 100644
--- a/stm32f091/makefile
+++ b/stm32f091/makefile
@@ -4,6 +4,9 @@ OC = arm-none-eabi-objcopy
RM = rm -f
TARGET = main
+HOST=$(strip $(shell uname -o))
+
+include ../shared/shared.mk
SHARED_FLAGS += -g
SHARED_FLAGS += -DSTM32F091xC
@@ -11,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
@@ -20,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
@@ -74,14 +79,20 @@ $(TARGET).bin: $(TARGET).elf
%.o: %.s
$(CC) -c $(AFLAGS) $< -o $@
+lib/%.o: lib/%.c
+ $(CC) -c $(CFLAGS) -w $< -o $@
+
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
+%-stm.o: %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
$(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
new file mode 100644
index 0000000..f4be08f
--- /dev/null
+++ b/stm32f091/protocol.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+#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 int record_amount = 0;
+ static unsigned int record_offset = 0;
+ const char* response_header = "id,temperature,humidity,atmospheric_pressure\n";
+ const unsigned int response_line_len = strlen("xxxx,xx,xx,xx\n");
+
+ if (!send) {
+ response->success = WS_PROTOCOL_CMD_RETURN_OK;
+ response->csh = true;
+ response->msg = ws_bin_s_alloc(0);
+ response->msg->bytes = 0;
+ if (sscanf(parsed_cmd->argv[1], "%x", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR;
+ if (sscanf(parsed_cmd->argv[2], "%x", &record_offset) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR;
+ else {
+ record_amount = WS_MIN(record_amount + record_offset, ws_backlog_get_record_count());
+ record_amount = WS_MAX(0, record_amount - record_offset);
+ 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_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 + record_offset);
+ 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_len);
+ }
+ }
+}
+
+void ws_protocol_send_data(const char* data, unsigned int length) {
+ ws_server_buffer_send_append((uint8_t*) data, length);
+}
diff --git a/stm32f091/readme.md b/stm32f091/readme.md
new file mode 100644
index 0000000..d2758b5
--- /dev/null
+++ b/stm32f091/readme.md
@@ -0,0 +1,11 @@
+# stm32 firmware subdirectory
+
+- uses make
+- 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/sensor.c b/stm32f091/sensor.c
index bc3cfd3..1c94e2a 100644
--- a/stm32f091/sensor.c
+++ b/stm32f091/sensor.c
@@ -58,6 +58,12 @@ void ws_sensor_read() {
.sens_humidity = ws_sensor_humidity()
};
ws_backlog_add_record(record);
+
+ // < DEBUG PROTOCOL PARSING CODE >
+ // ws_s_protocol_req_parser_state* parser = ws_protocol_req_parser_alloc();
+ // const char* request = "last-records 5\n";
+ // ws_protocol_parse_req_bytes(parser, (char*) request, strlen(request));
+ // ws_protocol_req_parser_free(parser);
}
void ws_sensor_read_task() {
diff --git a/stm32f091/server.c b/stm32f091/server.c
index e289245..d69ef1e 100644
--- a/stm32f091/server.c
+++ b/stm32f091/server.c
@@ -3,55 +3,222 @@
#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;
+}
+
+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 6a3501d..07c49d9 100644
--- a/stm32f091/server.h
+++ b/stm32f091/server.h
@@ -1,6 +1,99 @@
#pragma once
-void ws_server_demo();
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
-/** 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
+ *
+ * this function takes chunks of data from the esp8266 and parses +IPD
+ * commands. when a valid +IPD command is detected, it gets forwarded to
+ * ws_protocol_parse_req_byte.
+ *
+ * @param data pointer to data array
+ * @param size amount of bytes allowed to be read from `data`
+ */
+void ws_server_req_incoming(uint8_t* data, size_t size);
+
+// /** @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 8ca3720..d459635 100644
--- a/stm32f091/setup.h
+++ b/stm32f091/setup.h
@@ -4,24 +4,13 @@
#include <stm32f0xx_hal_i2c.h>
#include <stm32f0xx_hal_uart.h>
-#define WS_PINOUT_I2C_SDA_PIN GPIO_PIN_9
-#define WS_PINOUT_I2C_SDA_PORT GPIOB
-#define WS_PINOUT_I2C_SCL_PIN GPIO_PIN_8
-#define WS_PINOUT_I2C_SCL_PORT GPIOB
-
-#define WS_PINOUT_USART1_RX_PIN GPIO_PIN_10
-#define WS_PINOUT_USART1_RX_PORT GPIOA
-#define WS_PINOUT_USART1_TX_PIN GPIO_PIN_9
-#define WS_PINOUT_USART1_TX_PORT GPIOA
-
-#define WS_PINOUT_USART2_RX_PIN GPIO_PIN_3
-#define WS_PINOUT_USART2_RX_PORT GPIOA
-#define WS_PINOUT_USART2_TX_PIN GPIO_PIN_2
-#define WS_PINOUT_USART2_TX_PORT GPIOA
+#include "consts.h"
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/util.h b/stm32f091/util.h
new file mode 100644
index 0000000..11bee6f
--- /dev/null
+++ b/stm32f091/util.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stm32f0xx_hal.h>
+#include <string.h>
+
+#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
new file mode 100644
index 0000000..61e1706
--- /dev/null
+++ b/stm32f091/wifi.def.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#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"
+