From f252201b8733c55fcd6674c72b76d4b8e9895494 Mon Sep 17 00:00:00 2001 From: Fabien Proriol Date: Sat, 23 Nov 2019 16:53:43 +0100 Subject: [PATCH] Add stm32 platform This platform must be used with HAL and St CubeMX A full project is available on http://github.com/condo4/knx-pt100.git to understand how it work Yet, only STM32-L432KC is supported, but, it's easy to add other MCUs --- src/knx/bits.h | 39 ++- src/knx_facade.cpp | 3 + src/knx_facade.h | 5 + src/ring_buffer.c | 2 + src/ring_buffer.h | 18 ++ src/stm32_platform.cpp | 566 +++++++++++++++++++++++++++++++++++++++++ src/stm32_platform.h | 41 +++ 7 files changed, 673 insertions(+), 1 deletion(-) create mode 100644 src/ring_buffer.c create mode 100644 src/ring_buffer.h create mode 100644 src/stm32_platform.cpp create mode 100644 src/stm32_platform.h diff --git a/src/knx/bits.h b/src/knx/bits.h index 3e6a95e..5da4d5c 100644 --- a/src/knx/bits.h +++ b/src/knx/bits.h @@ -49,6 +49,43 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); #elif ARDUINO_ARCH_ESP32 #include #include +#elif ARCH_STM32 +#define DEC 10 +#define HEX 16 + +#define INPUT (0x0) +#define OUTPUT (0x1) +#define INPUT_PULLUP (0x2) +#define INPUT_PULLDOWN (0x3) + +#define LOW (0x0) +#define HIGH (0x1) +#define CHANGE 2 +#define FALLING 3 +#define RISING 4 + + + +#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) ) +#define ntohs(x) htons(x) +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#define lowByte(val) ((val)&255) +#define highByte(val) (((val) >> ((sizeof(val) - 1) << 3)) & 255) +#define bitRead(val, bitno) (((val) >> (bitno)) & 1) + +extern "C" { + void delay(uint32_t millis); + uint32_t millis(); +} +void pinMode(uint32_t dwPin, uint32_t dwMode); +void digitalWrite(uint32_t dwPin, uint32_t dwVal); +typedef void (*voidFuncPtr)(void); +void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); #endif void print(const char[]); @@ -84,4 +121,4 @@ uint8_t* pushInt(uint32_t i, uint8_t* data); uint8_t* pushByteArray(const uint8_t* src, uint32_t size, uint8_t* data); uint16_t getWord(uint8_t* data); uint32_t getInt(uint8_t* data); -void printHex(const char* suffix, const uint8_t *data, size_t length); \ No newline at end of file +void printHex(const char* suffix, const uint8_t *data, size_t length); diff --git a/src/knx_facade.cpp b/src/knx_facade.cpp index 45cdbcc..92e1633 100644 --- a/src/knx_facade.cpp +++ b/src/knx_facade.cpp @@ -25,6 +25,9 @@ #elif __linux__ // no predefined global instance #define ICACHE_RAM_ATTR +#elif ARCH_STM32 +#define ICACHE_RAM_ATTR +KnxFacade knx; #endif #ifndef __linux__ diff --git a/src/knx_facade.h b/src/knx_facade.h index c74f042..47a9472 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -11,6 +11,9 @@ #include "samd_platform.h" #include "knx/bau07B0.h" #include "knx/bau27B0.h" +#elif ARCH_STM32 +#include "stm32_platform.h" +#include "knx/bau07B0.h" #elif ARDUINO_ARCH_ESP8266 #include "esp_platform.h" #include "knx/bau57B0.h" @@ -331,6 +334,8 @@ template class KnxFacade : private SaveRestore #else #error "No medium type specified for Arduino_SAMD platform! Please set MEDIUM_TYPE! (TP:0, RF:2, IP:5)" #endif +#elif ARCH_STM32 +extern KnxFacade knx; #elif ARDUINO_ARCH_ESP8266 // predefined global instance for IP only extern KnxFacade knx; diff --git a/src/ring_buffer.c b/src/ring_buffer.c new file mode 100644 index 0000000..0080a2d --- /dev/null +++ b/src/ring_buffer.c @@ -0,0 +1,2 @@ +#include +#include "ring_buffer.h" diff --git a/src/ring_buffer.h b/src/ring_buffer.h new file mode 100644 index 0000000..bae8e87 --- /dev/null +++ b/src/ring_buffer.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + + +void init_static_ring_buffer(struct ring_buffer *buf, uint8_t *buffer, uint32_t maxlen); +void init_buffer(struct ring_buffer *buf, uint32_t maxlen); +void free_buffer(struct ring_buffer *buf); +int fifo_push(struct ring_buffer *buf, uint8_t data); +int fifo_pop(struct ring_buffer *buf, uint8_t *data); +uint32_t buffer_length(struct ring_buffer *buf); + +#ifdef __cplusplus +} +#endif diff --git a/src/stm32_platform.cpp b/src/stm32_platform.cpp new file mode 100644 index 0000000..9f937bd --- /dev/null +++ b/src/stm32_platform.cpp @@ -0,0 +1,566 @@ +#include "stm32_platform.h" +#include +#include +#include +#include + +#include + + +#ifdef STM32L432xx +#define USER_MEMORY_ADDR 0x0803F800 +#define USER_MEMORY_SIZE 0x800 +#define USER_MEMORY_PAGE 127 + +extern UART_HandleTypeDef huart1; +#define TPUART &huart1 +#endif + +// #define DEBUG_TPUSART_COMMUNICATION_RX +// #define DEBUG_TPUSART_COMMUNICATION_TX +#define DEBUG_MEMORY_SIZE 128 + +#define RX_BUFFER_LEN 64 +#define TX_BUFFER_LEN 64 + +static uint8_t RX_BUF[RX_BUFFER_LEN]; +static uint8_t TX_BUF[TX_BUFFER_LEN]; +static uint8_t __USER_MEMORY[USER_MEMORY_SIZE]; + +volatile static int tx_it_enable = 0; +unsigned char rx_byte; + +#include + +#define BUFFER_LEN 64 + +struct ring_buffer { + uint32_t _len; + uint32_t _maxlen; + uint8_t *_writer; + uint8_t *_reader; + uint8_t *_buffer; +}; + +struct ring_buffer rx_buffer; +struct ring_buffer tx_buffer; + + +void init_static_ring_buffer(struct ring_buffer *buf, uint8_t *buffer, uint32_t maxlen) +{ + buf->_buffer = buffer; + buf->_writer = buf->_buffer; + buf->_reader = buf->_buffer; + buf->_len = 0; + buf->_maxlen = maxlen; +} + +int fifo_push(struct ring_buffer *buf, uint8_t data) +{ + /* FIFO FULL */ + if(buf->_len >= buf->_maxlen) + return -1; + + *buf->_writer = data; + ++buf->_len; + ++buf->_writer; + + /* If end of buffer, restart to begin */ + if(buf->_writer > (buf->_buffer + buf->_maxlen)) + { + buf->_writer = buf->_buffer; + } + return 1; +} + +int fifo_pop(struct ring_buffer *buf, uint8_t *data) +{ + /* FIFO EMPTY */ + if(buf->_len == 0) + return -1; + + *data = *buf->_reader; + ++buf->_reader; + --buf->_len; + + /* If end of buffer, restart to begin */ + if(buf->_reader > (buf->_buffer + buf->_maxlen)) + { + buf->_reader = buf->_buffer; + } + return 1; +} + +uint32_t buffer_length(struct ring_buffer *buf) +{ + return buf->_len; +} + +void delay(uint32_t delay) +{ + uint32_t wake = HAL_GetTick() + delay; + while (wake > HAL_GetTick()); +} + +void tpuart_usart_setup(void) +{ + init_static_ring_buffer(&rx_buffer, RX_BUF, RX_BUFFER_LEN); + init_static_ring_buffer(&tx_buffer, TX_BUF, TX_BUFFER_LEN); + + if(HAL_UART_Receive_IT(TPUART, (unsigned char *)(&rx_byte), 1) != HAL_OK) + { + printf("!!! Error on tpuart_usart_setup, Can't HAL_UART_Receive_IT in start_tpuart_reception\n"); + } +} + +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ +#ifdef DEBUG_TPUSART_COMMUNICATION_RX + print('<'); +#endif + fifo_push(&rx_buffer, rx_byte); + if(HAL_UART_Receive_IT(TPUART, (unsigned char *)(&rx_byte), 1) != HAL_OK) + { + printf("!!! Error on start_next_telegram, Can't HAL_UART_Receive_IT in start_tpuart_reception\n"); + } +} + +void tpuart_send(uint8_t data) +{ +#ifdef DEBUG_TPUSART_COMMUNICATION_TX + print('>'); +#endif + HAL_UART_Transmit(TPUART, &data, 1, 100); +} + +uint32_t tpuart_rx_size() +{ + return buffer_length(&rx_buffer); +} + +uint32_t tpuart_tx_size() +{ + return buffer_length(&rx_buffer); +} + +uint8_t tpuart_get() +{ + uint8_t data = 0; + fifo_pop(&rx_buffer, &data); + return data; +} + + +static void flash_read_data(uint32_t start_address, uint16_t num_elements, uint8_t *output_data) +{ + uint16_t iter; + uint32_t *memory_ptr= (uint32_t*)start_address; + + for(iter=0; iter USER_MEMORY_SIZE) + fatalError(); + + return __USER_MEMORY; +} + +size_t Stm32Platform::readBytesUart(uint8_t *buffer, size_t length) +{ + return 0; +} + +size_t Stm32Platform::writeUart(const uint8_t *buffer, size_t size) +{ + size_t i = 0; + for(i = 0; i < size; i++) + { + tpuart_send(*(buffer + i)); + } + return size; +} + +void Stm32Platform::closeUart() +{ + +} + +void Stm32Platform::setupUart() +{ + tpuart_usart_setup(); +} + +int Stm32Platform::readBytes(uint8_t *buffer, uint16_t maxLen) +{ + return 0; +} + +bool Stm32Platform::sendBytes(uint8_t *buffer, uint16_t len) +{ + return false; +} + +void Stm32Platform::closeMultiCast() +{ + +} + +void Stm32Platform::setupMultiCast(uint32_t addr, uint16_t port) +{ + +} + +void Stm32Platform::fatalError() +{ + +} + +void Stm32Platform::restart() +{ + HAL_NVIC_SystemReset(); +} + +void Stm32Platform::macAddress(uint8_t *data) +{ + +} + +uint32_t Stm32Platform::currentDefaultGateway() +{ + return 0; +} + +uint32_t Stm32Platform::currentSubnetMask() +{ + return 0; +} + +int Stm32Platform::uartAvailable() +{ + return (tpuart_rx_size() > 0); +} + +size_t Stm32Platform::writeUart(const uint8_t data) +{ + tpuart_send(data); + return 1; +} + +int Stm32Platform::readUart() +{ + uint64_t m = millis() + 100; + + while((millis() < m) && (buffer_length(&rx_buffer) < 1)); + if(buffer_length(&rx_buffer) < 1) + { +#ifdef DEBUG_TPUSART_COMMUNICATION_RX + print('T'); +#endif + return 0; + } +#ifdef DEBUG_TPUSART_COMMUNICATION_RX + print('R'); +#endif + return tpuart_get(); +} + +void digitalWrite(uint32_t dwPin, uint32_t dwVal) +{ + if(dwPin == 1) + { + /* Prog led */ + if(dwVal == 0) + HAL_GPIO_WritePin(KNX_PROG_LED_GPIO_Port, KNX_PROG_LED_Pin, GPIO_PIN_SET); + else + HAL_GPIO_WritePin(KNX_PROG_LED_GPIO_Port, KNX_PROG_LED_Pin, GPIO_PIN_RESET); + } +} + +void pinMode(uint32_t dwPin, uint32_t dwMode) +{ +} + +typedef void (*voidFuncPtr)(void); +void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) +{ + +} + +void print(const char* s) +{ + printf("%s", s); +} +void print(char c) +{ + printf("%c", c); +} + +void print(unsigned char num) +{ + print(num, DEC); +} + +void print(unsigned char num, int base) +{ + if (base == HEX) + printf("%X", num); + else + printf("%d", num); +} + +void print(int num) +{ + print(num, DEC); +} + +void print(int num, int base) +{ + if (base == HEX) + printf("%X", num); + else + printf("%d", num); +} + +void print(unsigned int num) +{ + print(num, DEC); +} + +void print(unsigned int num, int base) +{ + if (base == HEX) + printf("%X", num); + else + printf("%d", num); +} + +void print(long num) +{ + print(num, DEC); +} + +void print(long num, int base) +{ + if (base == HEX) + printf("%lX", num); + else + printf("%ld", num); +} + +void print(unsigned long num) +{ + print(num, DEC); +} + +void print(unsigned long num, int base) +{ + if (base == HEX) + printf("%lX", num); + else + printf("%ld", num); +} + +void print(double num) +{ + printf("%f", num); +} + +void println(const char* s) +{ + printf("%s\n", s); +} +void println(char c) +{ + printf("%c\n", c); +} + +void println(unsigned char num) +{ + println(num, DEC); +} + +void println(unsigned char num, int base) +{ + if (base == HEX) + printf("%X\n", num); + else + printf("%d\n", num); +} + +void println(int num) +{ + println(num, DEC); +} + +void println(int num, int base) +{ + if (base == HEX) + printf("%X\n", num); + else + printf("%d\n", num); +} + +void println(unsigned int num) +{ + println(num, DEC); +} + +void println(unsigned int num, int base) +{ + if (base == HEX) + printf("%X\n", num); + else + printf("%d\n", num); +} + +void println(long num) +{ + println(num, DEC); +} + +void println(long num, int base) +{ + if (base == HEX) + printf("%lX\n", num); + else + printf("%ld\n", num); +} + +void println(unsigned long num) +{ + println(num, DEC); +} + +void println(unsigned long num, int base) +{ + if (base == HEX) + printf("%lX\n", num); + else + printf("%ld\n", num); +} + +void println(double num) +{ + printf("%f\n", num); +} + +void println(double num, int places) +{ + printf("%f\n", num); +} + +void println(void) +{ + printf("\n"); +} + +uint32_t Stm32Platform::currentIpAddress() +{ + return 0; +} + +void Stm32Platform::setupSpi() +{ + +} + +void Stm32Platform::closeSpi() +{ + +} + +int Stm32Platform::readWriteSpi (uint8_t *data, size_t len) +{ + return 0; +} diff --git a/src/stm32_platform.h b/src/stm32_platform.h new file mode 100644 index 0000000..cde89c1 --- /dev/null +++ b/src/stm32_platform.h @@ -0,0 +1,41 @@ +#include "knx/platform.h" + +#define LED_BUILTIN 1 + +class Stm32Platform : public Platform +{ + bool m_initialized = false; +public: + Stm32Platform(); + virtual ~Stm32Platform(); + + virtual uint32_t currentIpAddress() override; + virtual uint32_t currentSubnetMask() override; + virtual uint32_t currentDefaultGateway() override; + virtual void macAddress(uint8_t* data) override; + + virtual void restart() override; + virtual void fatalError() override; + + virtual void setupMultiCast(uint32_t addr, uint16_t port) override; + virtual void closeMultiCast() override; + virtual bool sendBytes(uint8_t* buffer, uint16_t len) override; + virtual int readBytes(uint8_t* buffer, uint16_t maxLen) override; + + virtual void setupUart() override; + virtual void closeUart() override; + virtual int uartAvailable() override; + virtual size_t writeUart(const uint8_t data) override; + virtual size_t writeUart(const uint8_t* buffer, size_t size) override; + virtual int readUart() override; + virtual size_t readBytesUart(uint8_t* buffer, size_t length) override; + + virtual uint8_t* getEepromBuffer(uint16_t size) override; + virtual void commitToEeprom() override; + + //spi + void setupSpi() override; + void closeSpi() override; + int readWriteSpi (uint8_t *data, size_t len) override; + +};