diff --git a/.gitmodules b/.gitmodules index d48864f..a6d01a1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "src/BME68x-Sensor-API"] path = src/BME68x-Sensor-API url = https://github.com/BoschSensortec/BME68x-Sensor-API.git +[submodule "src/oled-driver"] + path = src/oled-driver + url = git@github.com:MG-5/oled-driver.git diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index b2b3cb9..5165f0a 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -11,15 +11,18 @@ "${workspaceFolder}/cubemx/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2", "${workspaceFolder}/cubemx/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3", "${workspaceFolder}/cubemx/Drivers/CMSIS/Device/ST/STM32L1xx/Include", - "${workspaceFolder}/cubemx/Drivers/CMSIS/Include" + "${workspaceFolder}/cubemx/Drivers/CMSIS/Include", + "${workspaceFolder}/src", + "${workspaceFolder}/src/oled-driver/include", + "${workspaceFolder}/src/oled-driver" ], "defines": [ - "STM32L1", - "STM32L152RC", + "DEBUG", "STM32L152xC", - "BME68X_DO_NOT_USE_FPU" + "BME68X_DO_NOT_USE_FPU", + "FW_USE_RTOS" ], - "compilerPath": "arm-none-eabi-gcc", + "compilerPath": "/usr/bin/arm-none-eabi-gcc", "cStandard": "c11", "cppStandard": "c++17" } diff --git a/Makefile b/Makefile index 703568f..a87a7df 100644 --- a/Makefile +++ b/Makefile @@ -2,17 +2,24 @@ TARGET := voc-sensor RTOS := freertos DEVICE := stm32l152rc -DEFS := BME68X_DO_NOT_USE_FPU +DEFS += BME68X_DO_NOT_USE_FPU +DEFS += FW_USE_RTOS -INCDIRS := \ -src \ -src/BME68x-Sensor-API +INCDIRS := \ +src/BME68x-Sensor-API \ +src/oled-driver/ \ +src/oled-driver/include \ +src \ -SOURCES := \ -src/bmeSPI.cxx \ -src/main.cxx \ -src/handlers.cxx \ -src/BME68x-Sensor-API/bme68x.c +SOURCES := \ +src/BME68x-Sensor-API/bme68x.c \ +src/oled-driver/fonts/mono.cxx \ +src/oled-driver/src/Display.cxx \ +src/oled-driver/src/Image.cxx \ +src/oled-driver/src/Renderer.cxx \ +src/bmeSPI.cxx \ +src/handlers.cxx \ +src/main.cxx \ # Actual build engine include core/mk/include.mk \ No newline at end of file diff --git a/core/src/abi.cpp b/core/src/abi.cpp index da433cb..30626c9 100644 --- a/core/src/abi.cpp +++ b/core/src/abi.cpp @@ -13,7 +13,13 @@ void *operator new(std::size_t size) #if FW_USE_RTOS return pvPortMalloc(size); #else - return reinterpret_cast(0xffffffff); +#ifdef DEBUG + __asm("bkpt"); +#else + while (1) + { + } +#endif #endif } @@ -26,11 +32,15 @@ void operator delete(void *ptr) { #if FW_USE_RTOS vPortFree(ptr); +#else +#ifdef DEBUG + __asm("bkpt"); #else while (1) { } #endif +#endif } void operator delete(void *ptr, unsigned int) @@ -110,7 +120,7 @@ extern "C" // some functions in cmath follow the compiler flag -fno-math-errno // but not so for std::pow... - void __errno() { - + void __errno() + { } } \ No newline at end of file diff --git a/cubemx/Core/Inc/FreeRTOSConfig.h b/cubemx/Core/Inc/FreeRTOSConfig.h index d96a167..fbf290f 100644 --- a/cubemx/Core/Inc/FreeRTOSConfig.h +++ b/cubemx/Core/Inc/FreeRTOSConfig.h @@ -60,7 +60,7 @@ #define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES ( 56 ) #define configMINIMAL_STACK_SIZE ((uint16_t)128) -#define configTOTAL_HEAP_SIZE ((size_t)3072) +#define configTOTAL_HEAP_SIZE ((size_t)6000) #define configMAX_TASK_NAME_LEN ( 16 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 @@ -68,8 +68,10 @@ #define configQUEUE_REGISTRY_SIZE 8 #define configCHECK_FOR_STACK_OVERFLOW 2 #define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 1 #define configUSE_COUNTING_SEMAPHORES 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 diff --git a/cubemx/Core/Inc/main.h b/cubemx/Core/Inc/main.h index 1ff0b1a..296d9ca 100644 --- a/cubemx/Core/Inc/main.h +++ b/cubemx/Core/Inc/main.h @@ -58,8 +58,14 @@ void Error_Handler(void); /* USER CODE END EFP */ /* Private defines -----------------------------------------------------------*/ -#define SPI_CS_Pin GPIO_PIN_12 -#define SPI_CS_GPIO_Port GPIOB +#define VocSensorCS_Pin GPIO_PIN_0 +#define VocSensorCS_GPIO_Port GPIOA +#define DisplayDC_Pin GPIO_PIN_10 +#define DisplayDC_GPIO_Port GPIOB +#define DisplayReset_Pin GPIO_PIN_11 +#define DisplayReset_GPIO_Port GPIOB +#define DisplayCS_Pin GPIO_PIN_12 +#define DisplayCS_GPIO_Port GPIOB /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ diff --git a/cubemx/Core/Src/freertos.c b/cubemx/Core/Src/freertos.c index 46bc6af..fcfa765 100644 --- a/cubemx/Core/Src/freertos.c +++ b/cubemx/Core/Src/freertos.c @@ -75,6 +75,7 @@ void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /* Hook prototypes */ void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName); +void vApplicationMallocFailedHook(void); /* USER CODE BEGIN 4 */ __weak void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName) @@ -85,6 +86,22 @@ __weak void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTask } /* USER CODE END 4 */ +/* USER CODE BEGIN 5 */ +__weak void vApplicationMallocFailedHook(void) +{ + /* vApplicationMallocFailedHook() will only be called if + configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook + function that will get called if a call to pvPortMalloc() fails. + pvPortMalloc() is called internally by the kernel whenever a task, queue, + timer or semaphore is created. It is also called by various parts of the + demo application. If heap_1.c or heap_2.c are used, then the size of the + heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in + FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used + to query the size of free heap space that remains (although it does not + provide information on how the remaining heap might be fragmented). */ +} +/* USER CODE END 5 */ + /** * @brief FreeRTOS initialization * @param None diff --git a/cubemx/Core/Src/gpio.c b/cubemx/Core/Src/gpio.c index ac0d7a1..9640da8 100644 --- a/cubemx/Core/Src/gpio.c +++ b/cubemx/Core/Src/gpio.c @@ -53,7 +53,10 @@ void MX_GPIO_Init(void) __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ - HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(VocSensorCS_GPIO_Port, VocSensorCS_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, DisplayDC_Pin|DisplayReset_Pin|DisplayCS_Pin, GPIO_PIN_RESET); /*Configure GPIO pins : PC13 PC14 PC15 PC0 PC1 PC2 PC3 PC4 @@ -73,34 +76,41 @@ void MX_GPIO_Init(void) GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - /*Configure GPIO pins : PA0 PA1 PA2 PA3 - PA4 PA5 PA6 PA7 - PA8 PA9 PA10 PA11 - PA12 PA15 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 - |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 - |GPIO_PIN_12|GPIO_PIN_15; + /*Configure GPIO pin : PtPin */ + GPIO_InitStruct.Pin = VocSensorCS_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(VocSensorCS_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pins : PA1 PA2 PA3 PA4 + PA5 PA6 PA7 PA8 + PA9 PA10 PA11 PA12 + PA15 */ + GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4 + |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8 + |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 + |GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - /*Configure GPIO pins : PB0 PB1 PB2 PB10 - PB11 PB3 PB4 PB5 - PB6 PB7 PB8 PB9 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 - |GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; + /*Configure GPIO pins : PB0 PB1 PB2 PB3 + PB4 PB5 PB6 PB7 + PB8 PB9 */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 + |GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - /*Configure GPIO pin : PtPin */ - GPIO_InitStruct.Pin = SPI_CS_Pin; + /*Configure GPIO pins : PBPin PBPin PBPin */ + GPIO_InitStruct.Pin = DisplayDC_Pin|DisplayReset_Pin|DisplayCS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(SPI_CS_GPIO_Port, &GPIO_InitStruct); + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pin : PD2 */ GPIO_InitStruct.Pin = GPIO_PIN_2; diff --git a/cubemx/voc-sensor.ioc b/cubemx/voc-sensor.ioc index cc9bd02..f87477d 100644 --- a/cubemx/voc-sensor.ioc +++ b/cubemx/voc-sensor.ioc @@ -22,9 +22,12 @@ Dma.SPI2_TX.1.Priority=DMA_PRIORITY_LOW Dma.SPI2_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority FREERTOS.FootprintOK=true FREERTOS.HEAP_NUMBER=1 -FREERTOS.IPParameters=Tasks01,configCHECK_FOR_STACK_OVERFLOW,FootprintOK,HEAP_NUMBER +FREERTOS.IPParameters=Tasks01,configCHECK_FOR_STACK_OVERFLOW,FootprintOK,HEAP_NUMBER,configRECORD_STACK_HIGH_ADDRESS,configUSE_MALLOC_FAILED_HOOK,configTOTAL_HEAP_SIZE FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;sensor,24,512,sensorTask,As external,NULL,Dynamic,NULL,NULL FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2 +FREERTOS.configRECORD_STACK_HIGH_ADDRESS=1 +FREERTOS.configTOTAL_HEAP_SIZE=6000 +FREERTOS.configUSE_MALLOC_FAILED_HOOK=1 File.Version=6 GPIO.groupedBy= KeepUserPlacement=false @@ -38,15 +41,18 @@ Mcu.IP5=SYS Mcu.IPNb=6 Mcu.Name=STM32L152RCTx Mcu.Package=LQFP64 -Mcu.Pin0=PB12 -Mcu.Pin1=PB13 -Mcu.Pin2=PB14 -Mcu.Pin3=PB15 -Mcu.Pin4=PA13 -Mcu.Pin5=PA14 -Mcu.Pin6=VP_FREERTOS_VS_CMSIS_V2 -Mcu.Pin7=VP_SYS_VS_tim2 -Mcu.PinsNb=8 +Mcu.Pin0=PA0-WKUP1 +Mcu.Pin1=PB10 +Mcu.Pin10=VP_SYS_VS_tim2 +Mcu.Pin2=PB11 +Mcu.Pin3=PB12 +Mcu.Pin4=PB13 +Mcu.Pin5=PB14 +Mcu.Pin6=PB15 +Mcu.Pin7=PA13 +Mcu.Pin8=PA14 +Mcu.Pin9=VP_FREERTOS_VS_CMSIS_V2 +Mcu.PinsNb=11 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32L152RCTx @@ -71,13 +77,21 @@ NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true NVIC.TimeBase=TIM2_IRQn NVIC.TimeBaseIP=TIM2 NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +PA0-WKUP1.GPIOParameters=GPIO_Label +PA0-WKUP1.GPIO_Label=VocSensorCS +PA0-WKUP1.Signal=GPIO_Output PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PB10.GPIOParameters=GPIO_Label +PB10.GPIO_Label=DisplayDC +PB10.Signal=GPIO_Output +PB11.GPIOParameters=GPIO_Label +PB11.GPIO_Label=DisplayReset +PB11.Signal=GPIO_Output PB12.GPIOParameters=GPIO_Label -PB12.GPIO_Label=SPI_CS -PB12.Locked=true +PB12.GPIO_Label=DisplayCS PB12.Signal=GPIO_Output PB13.Mode=Full_Duplex_Master PB13.Signal=SPI2_SCK diff --git a/src/SSD1306_SPI.hpp b/src/SSD1306_SPI.hpp new file mode 100644 index 0000000..9c2da9a --- /dev/null +++ b/src/SSD1306_SPI.hpp @@ -0,0 +1,88 @@ +#pragma once + +#include "main.h" +#include "semphr.h" +#include "spi.h" + +#include "oled-driver/SSD1306Interface.hpp" + +constexpr size_t OledWidth = 128; +constexpr size_t OledPages = 4; + +namespace +{ +constexpr auto DisplaySpiPeripherie = &hspi2; +} // namespace + +extern QueueHandle_t spiMutex; +extern void waitForSpiFinished(); + +//-------------------------------------------------------------------------------------------------- +//! SPI interface to a SSD1305/6 display controller. +class SSD1306_SPI : public SSD1306Interface +{ +public: + void writeCommand(uint8_t cmd) override + { + xSemaphoreTake(spiMutex, portMAX_DELAY); + + setCommandPin(); + setChipSelect(true); + HAL_SPI_Transmit_DMA(DisplaySpiPeripherie, &cmd, 1); + waitForSpiFinished(); + setChipSelect(false); + + xSemaphoreGive(spiMutex); + } + + //-------------------------------------------------------------------------------------------------- + void writeData(uint8_t data) override + { + xSemaphoreTake(spiMutex, portMAX_DELAY); + + setDataPin(); + setChipSelect(true); + HAL_SPI_Transmit_DMA(DisplaySpiPeripherie, &data, 1); + waitForSpiFinished(); + setChipSelect(false); + + xSemaphoreGive(spiMutex); + } + + //-------------------------------------------------------------------------------------------------- + void writeData(const uint8_t *data, unsigned int length) override + { + if (length > OledWidth * OledPages) + return; + + xSemaphoreTake(spiMutex, portMAX_DELAY); + + setDataPin(); + setChipSelect(true); + HAL_SPI_Transmit_DMA(DisplaySpiPeripherie, const_cast(data), length); + waitForSpiFinished(); + setChipSelect(false); + + xSemaphoreGive(spiMutex); + } + + //-------------------------------------------------------------------------------------------------- +private: + void setDataPin() + { + HAL_GPIO_WritePin(DisplayDC_GPIO_Port, DisplayDC_Pin, GPIO_PIN_SET); + } + + //-------------------------------------------------------------------------------------------------- + void setCommandPin() + { + HAL_GPIO_WritePin(DisplayDC_GPIO_Port, DisplayDC_Pin, GPIO_PIN_RESET); + } + + //-------------------------------------------------------------------------------------------------- + void setChipSelect(bool state) + { + HAL_GPIO_WritePin(DisplayCS_GPIO_Port, DisplayCS_Pin, + state ? GPIO_PIN_RESET : GPIO_PIN_SET); + } +}; diff --git a/src/bmeSPI.cxx b/src/bmeSPI.cxx index fdf7e9e..f223f64 100644 --- a/src/bmeSPI.cxx +++ b/src/bmeSPI.cxx @@ -1,11 +1,21 @@ #include "FreeRTOS.h" #include "gpio.h" #include "main.h" +#include "semphr.h" #include "spi.h" #include "task.h" + #include #include "BME68x-Sensor-API/bme68x.h" +#include "oled-driver/Renderer.hpp" + +extern QueueHandle_t spiMutex; +extern void waitForSpiFinished(); +extern Renderer renderer; + +constexpr auto MaximumChars = 22 * 4; +char buffer[MaximumChars]; constexpr auto SPI_DEVICE = &hspi2; uint8_t txBuffer[512]; @@ -29,17 +39,15 @@ uint16_t dur_prof[10] = {100, 100, 100, 100, 100, 100, 100, 100, 100, 100}; void setChipSelect(bool state) { - HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, state ? GPIO_PIN_RESET : GPIO_PIN_SET); -} - -void waitForSpiFinished() -{ - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + HAL_GPIO_WritePin(VocSensorCS_GPIO_Port, VocSensorCS_Pin, + state ? GPIO_PIN_RESET : GPIO_PIN_SET); } // SPI read function map BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *) { + xSemaphoreTake(spiMutex, portMAX_DELAY); + setChipSelect(true); HAL_SPI_Transmit_DMA(SPI_DEVICE, ®_addr, 1); waitForSpiFinished(); @@ -47,6 +55,8 @@ BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32 waitForSpiFinished(); setChipSelect(false); + xSemaphoreGive(spiMutex); + return 0; } @@ -60,11 +70,15 @@ BME68X_INTF_RET_TYPE bme68x_spi_write(uint8_t reg_addr, const uint8_t *reg_data, txBuffer[0] = reg_addr; std::memcpy(&txBuffer[1], reg_data, len); + xSemaphoreTake(spiMutex, portMAX_DELAY); + setChipSelect(true); HAL_SPI_Transmit_DMA(SPI_DEVICE, const_cast(txBuffer), len + 1); waitForSpiFinished(); setChipSelect(false); + xSemaphoreGive(spiMutex); + return 0; } @@ -153,10 +167,33 @@ void bmeRun() /* Check if res == BME68X_OK, report or handle if otherwise */ for (uint8_t i = 0; i < n_fields; i++) { - // printf("%u, %u, %d, %u, %u, %u, 0x%x, %d, %d\n", sampleCount, - // time_ms,(bmeData[i].temperature / 100), bmeData[i].pressure, (bmeData[i].humidity / - // 1000),bmeData[i].gas_resistance, - // bmeData[i].status,data[i].gas_index,data[i].meas_index); + renderer.clearAll(); + + snprintf(buffer, MaximumChars, + "%d°C, %luhPa, %lu%%\n%lukOhm, status: 0x%x\ngas_index: %d\nmeas_index: %d", + bmeData[i].temperature / 100, // + bmeData[i].pressure / 100, // + bmeData[i].humidity / 1000, // + bmeData[i].gas_resistance / 1000, // + bmeData[i].status, // + bmeData[i].gas_index, // + bmeData[i].meas_index); + + renderer.print({0, 0}, buffer); + renderer.render(); + /* + snprintf(buffer, MaximumChars, "sampleCount: %u\n, time_ms: %u\n \ + temperature; %d°C\n \ + pressure: %u\n \ + humidity: %u\n \ + gas_resistance: %u\n \ + // status: 0x%x\n \ + //gas_index: %d\n \ + meas_index: %d\n", + sampleCount, time_ms, (bmeData[i].temperature / 100), bmeData[i].pressure, + (bmeData[i].humidity / 1000), bmeData[i].gas_resistance, bmeData[i].status, + bmeData[i].gas_index, bmeData[i].meas_index); + */ } } diff --git a/src/handlers.cxx b/src/handlers.cxx index 4523dc8..3439494 100644 --- a/src/handlers.cxx +++ b/src/handlers.cxx @@ -37,11 +37,15 @@ extern "C" void prvGetRegistersFromStack(uint32_t *pulFaultStackAddress) (void)pc; (void)psr; - /* When the following line is hit, the variables contain the register values. */ - // HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); +/* When the following line is hit, the variables contain the register values. */ +// HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); +#ifdef DEBUG + __asm("bkpt"); +#else while (1) { } +#endif } extern "C" void hard_fault_handler(void) @@ -67,10 +71,13 @@ extern "C" void hard_fault_handler(void) extern "C" void vApplicationMallocFailedHook(void) { - // HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); +#ifdef DEBUG + __asm("bkpt"); +#else while (1) { } +#endif } extern "C" void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName) @@ -78,8 +85,11 @@ extern "C" void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCH (void)pxTask; (void)pcTaskName; - // HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); +#ifdef DEBUG + __asm("bkpt"); +#else while (1) { } +#endif } \ No newline at end of file diff --git a/src/main.cxx b/src/main.cxx index c9efbdd..ea4b4c9 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -1,33 +1,79 @@ #include "main.h" #include "FreeRTOS.h" +#include "semphr.h" #include "task.h" +#include "SSD1306_SPI.hpp" +#include "oled-driver/Display.hpp" +#include "oled-driver/Renderer.hpp" + extern TaskHandle_t sensorHandle; extern void bmeRun(); +// oled display +SSD1306_SPI ssdSpiInterface; +Display display(ssdSpiInterface); +Renderer renderer(128, 4, display); + +QueueHandle_t spiMutex = xSemaphoreCreateMutex(); +QueueHandle_t spiBinary = xSemaphoreCreateBinary(); + //-------------------------------------------------------------------------------------------------- -void notifySensorTask() +void initDisplay() +{ + HAL_GPIO_WritePin(DisplayReset_GPIO_Port, DisplayReset_Pin, GPIO_PIN_RESET); + vTaskDelay(pdMS_TO_TICKS(1)); + HAL_GPIO_WritePin(DisplayReset_GPIO_Port, DisplayReset_Pin, GPIO_PIN_SET); + vTaskDelay(pdMS_TO_TICKS(1)); + + display.setDisplayState(Display::DisplayState::Off); + display.setMultiplexRatio(OledPages * 8 - 1); + display.setComPinConfig(false, false); + display.setContrastControl(0xFF); + display.setDisplayClockDivide(0, 0x8); + display.setSegmentRemap(true); + display.setComOutputMode(Display::ComMode::Remap); + display.setPrechargingPeriod(1, 0xF); + display.setChargePump(true); + + display.setMemoryAddressingMode(Display::AddressingMode::Horizontal); + display.setPageAddress(0, OledPages - 1); // pages from 0 to 3 + display.setColumnAddress(0, OledWidth - 1); // columns from 0 to 127 + + display.setDisplayState(Display::DisplayState::On); +} + +//-------------------------------------------------------------------------------------------------- +void notifySpiIsFinished() { auto higherPriorityTaskWoken = pdFALSE; - vTaskNotifyGiveFromISR(sensorHandle, &higherPriorityTaskWoken); + xSemaphoreGiveFromISR(spiBinary, &higherPriorityTaskWoken); portYIELD_FROM_ISR(higherPriorityTaskWoken); } +//-------------------------------------------------------------------------------------------------- +void waitForSpiFinished() +{ + xSemaphoreTake(spiBinary, portMAX_DELAY); +} + //-------------------------------------------------------------------------------------------------- extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *) { - notifySensorTask(); + notifySpiIsFinished(); } //-------------------------------------------------------------------------------------------------- extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *) { - notifySensorTask(); + notifySpiIsFinished(); } //-------------------------------------------------------------------------------------------------- extern "C" void sensorTask(void *) { + initDisplay(); + bmeRun(); while (1) { diff --git a/src/oled-driver b/src/oled-driver new file mode 160000 index 0000000..a224095 --- /dev/null +++ b/src/oled-driver @@ -0,0 +1 @@ +Subproject commit a224095e81a4728faa1311f0d717eb54959c6430