mirror of
https://github.com/thelsing/knx.git
synced 2025-08-31 13:47:01 +02:00
Merge pull request #317 from Phil1pp/libretiny
Added support for LibreTiny IoT chips
This commit is contained in:
commit
f073d8fd0b
@ -1,6 +1,6 @@
|
||||
# knx
|
||||
|
||||
This projects provides a knx-device stack for Arduino (ESP8266, ESP32, SAMD21, RP2040, STM32), CC1310, ESP IDF and Linux. (more are quite easy to add)
|
||||
This projects provides a knx-device stack for Arduino (ESP8266, ESP32, SAMD21, RP2040, STM32), CC1310, ESP IDF, LibreTiny (BK7231, RTL8710 and LN882H) and Linux. (more are quite easy to add)
|
||||
It implements most of System-B specification and can be configured with ETS.
|
||||
The necessary knxprod-files can be generated with the [Kaenx-Creator](https://github.com/OpenKNX/Kaenx-Creator) tool.
|
||||
|
||||
|
@ -58,7 +58,11 @@ void setup()
|
||||
Serial.begin(115200);
|
||||
ArduinoPlatform::SerialDebug = &Serial;
|
||||
|
||||
#ifdef LIBRETINY
|
||||
srandom(millis());
|
||||
#else
|
||||
randomSeed(millis());
|
||||
#endif
|
||||
|
||||
#if MASK_VERSION != 0x07B0 && (defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32)
|
||||
WiFiManager wifiManager;
|
||||
|
@ -96,3 +96,17 @@ build_flags =
|
||||
-DKNX_FLASH_SIZE=4096
|
||||
-D PIO_FRAMEWORK_ARDUINO_ENABLE_RTTI
|
||||
-Wno-unknown-pragmas
|
||||
|
||||
;--- LibreTiny BK7231N ------------------------------------
|
||||
[env:BK7231N_ip]
|
||||
platform = libretiny
|
||||
board = cbu
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
knx
|
||||
|
||||
build_flags =
|
||||
-DMASK_VERSION=0x57B0
|
||||
-DKNX_NO_SPI
|
||||
-DKNX_FLASH_OFFSET=0x1DB000
|
||||
-Wno-unknown-pragmas
|
@ -168,4 +168,22 @@ build_flags =
|
||||
-DMASK_VERSION=0x07B0
|
||||
-DKNX_FLASH_SIZE=4096
|
||||
-D PIO_FRAMEWORK_ARDUINO_ENABLE_RTTI
|
||||
-Wno-unknown-pragmas
|
||||
|
||||
;--- LibreTiny BK7231N ------------------------------------
|
||||
[env:BK7231N_ip]
|
||||
platform = libretiny
|
||||
board = cbu
|
||||
framework = arduino
|
||||
; We consider that the this projects is opened within its project directory
|
||||
; while working with VS Code.
|
||||
lib_extra_dirs = ../../../
|
||||
|
||||
lib_deps =
|
||||
knx
|
||||
|
||||
build_flags =
|
||||
-DMASK_VERSION=0x57B0
|
||||
-DKNX_NO_SPI
|
||||
-DKNX_FLASH_OFFSET=0x1DB000
|
||||
-Wno-unknown-pragmas
|
@ -11,21 +11,13 @@
|
||||
#define htonl(x) ( (getbyte(x,0)<<24) | (getbyte(x,1)<<16) | (getbyte(x,2)<<8) | getbyte(x,3) )
|
||||
#define ntohs(x) htons(x)
|
||||
#define ntohl(x) htonl(x)
|
||||
#elif defined(LIBRETINY)
|
||||
#include <lwip/udp.h>
|
||||
#define htons(x) lwip_htons(x)
|
||||
#define htonl(x) lwip_htonl(x)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a < b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a > b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(x) ((x > 0) ? (x) : (-x))
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_STM32)
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_STM32) || defined(LIBRETINY)
|
||||
#include <Arduino.h>
|
||||
#elif defined(ARDUINO_ARCH_ESP8266)
|
||||
#include <Arduino.h>
|
||||
@ -85,6 +77,18 @@
|
||||
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a < b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a > b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(x) ((x > 0) ? (x) : (-x))
|
||||
#endif
|
||||
|
||||
#ifndef KNX_NO_PRINT
|
||||
void print(const char[]);
|
||||
void print(char);
|
||||
|
@ -21,7 +21,7 @@ enum ComFlag : uint8_t
|
||||
class GroupObject;
|
||||
|
||||
#ifndef HAS_FUNCTIONAL
|
||||
#if defined(__linux__) || defined(ARDUINO_ARCH_ESP32) || defined(ESP_PLATFORM) || defined(ARDUINO_ARCH_STM32) || defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_RP2040)
|
||||
#if defined(__linux__) || defined(ARDUINO_ARCH_ESP32) || defined(ESP_PLATFORM) || defined(ARDUINO_ARCH_STM32) || defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_RP2040) || defined(LIBRETINY)
|
||||
#define HAS_FUNCTIONAL 1
|
||||
#else
|
||||
#define HAS_FUNCTIONAL 0
|
||||
|
@ -8,7 +8,8 @@
|
||||
defined(ARDUINO_ARCH_ESP32) || \
|
||||
defined(ARDUINO_ARCH_ESP8266) || \
|
||||
defined(ARDUINO_ARCH_SAMD) || \
|
||||
defined(ARDUINO_ARCH_RP2040))
|
||||
defined(ARDUINO_ARCH_RP2040)) || \
|
||||
defined(LIBRETINY)
|
||||
|
||||
// Only ESP8266 and ESP32 have this define. For all other platforms this is just empty.
|
||||
#ifndef IRAM_ATTR
|
||||
@ -95,6 +96,18 @@ IRAM_ATTR void buttonEvent()
|
||||
#error "Mask version not supported on ARDUINO_ARCH_ESP32"
|
||||
#endif
|
||||
|
||||
#elif defined(LIBRETINY)
|
||||
// predefined global instance for TP or IP or TP/IP coupler
|
||||
#if MASK_VERSION == 0x07B0
|
||||
KnxFacade<LibretinyPlatform, Bau07B0> knx(buttonEvent);
|
||||
#elif MASK_VERSION == 0x57B0
|
||||
KnxFacade<LibretinyPlatform, Bau57B0> knx(buttonEvent);
|
||||
#elif MASK_VERSION == 0x091A
|
||||
KnxFacade<LibretinyPlatform, Bau091A> knx(buttonEvent);
|
||||
#else
|
||||
#error "Mask version not supported on LIBRETINY"
|
||||
#endif
|
||||
|
||||
#elif defined(ESP_PLATFORM)
|
||||
// predefined global instance for TP or IP or TP/IP coupler
|
||||
#if MASK_VERSION == 0x07B0
|
||||
|
@ -32,6 +32,8 @@
|
||||
#ifndef KNX_NO_AUTOMATIC_GLOBAL_INSTANCE
|
||||
void buttonUp();
|
||||
#endif
|
||||
#elif defined(LIBRETINY)
|
||||
#include "libretiny_platform.h"
|
||||
#elif defined(ESP_PLATFORM)
|
||||
#include "esp32_idf_platform.h"
|
||||
#ifndef KNX_NO_AUTOMATIC_GLOBAL_INSTANCE
|
||||
@ -265,7 +267,6 @@ template <class P, class B> class KnxFacade : private SaveRestore
|
||||
|
||||
void start()
|
||||
{
|
||||
|
||||
if (_ledPin >= 0)
|
||||
{
|
||||
#if defined(ESP_PLATFORM)
|
||||
@ -553,6 +554,17 @@ template <class P, class B> class KnxFacade : private SaveRestore
|
||||
#else
|
||||
#error "Mask version not supported on ARDUINO_ARCH_ESP32"
|
||||
#endif
|
||||
#elif defined(LIBRETINY)
|
||||
// predefined global instance for TP or IP or TP/IP coupler
|
||||
#if MASK_VERSION == 0x07B0
|
||||
extern KnxFacade<LibretinyPlatform, Bau07B0> knx;
|
||||
#elif MASK_VERSION == 0x57B0
|
||||
extern KnxFacade<LibretinyPlatform, Bau57B0> knx;
|
||||
#elif MASK_VERSION == 0x091A
|
||||
extern KnxFacade<LibretinyPlatform, Bau091A> knx;
|
||||
#else
|
||||
#error "Mask version not supported on LIBRETINY"
|
||||
#endif
|
||||
#elif defined(ESP_PLATFORM)
|
||||
// predefined global instance for TP or IP or TP/IP coupler
|
||||
#if MASK_VERSION == 0x07B0
|
||||
|
173
src/libretiny_platform.cpp
Normal file
173
src/libretiny_platform.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include "libretiny_platform.h"
|
||||
|
||||
#ifdef LIBRETINY
|
||||
#include <Arduino.h>
|
||||
#include "knx/bits.h"
|
||||
|
||||
#include <lwip/netif.h>
|
||||
|
||||
#ifndef KNX_SERIAL
|
||||
#define KNX_SERIAL Serial
|
||||
#endif
|
||||
|
||||
#ifndef KNX_FLASH_OFFSET
|
||||
#error "KNX_FLASH_OFFSET is not defined. E.g. 0x1DB000 for BK7231N"
|
||||
#elif (KNX_FLASH_OFFSET % 4096) != 0
|
||||
#error "KNX_FLASH_OFFSET must be a multiple of 4096"
|
||||
#endif
|
||||
|
||||
static uint8_t NVS_buffer[KNX_FLASH_SIZE];
|
||||
|
||||
LibretinyPlatform::LibretinyPlatform()
|
||||
#ifndef KNX_NO_DEFAULT_UART
|
||||
: ArduinoPlatform(&KNX_SERIAL)
|
||||
#endif
|
||||
{
|
||||
_memoryType = Flash;
|
||||
}
|
||||
|
||||
LibretinyPlatform::LibretinyPlatform( HardwareSerial* s) : ArduinoPlatform(s)
|
||||
{
|
||||
_memoryType = Flash;
|
||||
}
|
||||
|
||||
uint32_t LibretinyPlatform::currentIpAddress()
|
||||
{
|
||||
return WiFi.localIP();
|
||||
}
|
||||
|
||||
uint32_t LibretinyPlatform::currentSubnetMask()
|
||||
{
|
||||
return WiFi.subnetMask();
|
||||
}
|
||||
|
||||
uint32_t LibretinyPlatform::currentDefaultGateway()
|
||||
{
|
||||
return WiFi.gatewayIP();
|
||||
}
|
||||
|
||||
void LibretinyPlatform::macAddress(uint8_t * addr)
|
||||
{
|
||||
WiFi.macAddress(addr);
|
||||
}
|
||||
|
||||
uint32_t LibretinyPlatform::uniqueSerialNumber()
|
||||
{
|
||||
return lt_cpu_get_mac_id();
|
||||
}
|
||||
|
||||
void LibretinyPlatform::restart()
|
||||
{
|
||||
println("restart");
|
||||
lt_reboot();
|
||||
}
|
||||
|
||||
void LibretinyPlatform::setupMultiCast(uint32_t addr, uint16_t port)
|
||||
{
|
||||
//workaround for libretiny bug: NETIF_FLAG_IGMP is not set by default
|
||||
struct netif *netif;
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next)
|
||||
{
|
||||
netif->flags |= NETIF_FLAG_IGMP;
|
||||
}
|
||||
|
||||
IPAddress mcastaddr(htonl(addr));
|
||||
KNX_DEBUG_SERIAL.printf("setup multicast addr: %d.%d.%d.%d port: %d ip: %d.%d.%d.%d\n", mcastaddr[0], mcastaddr[1], mcastaddr[2], mcastaddr[3], port, WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
|
||||
uint8_t result = _udp.beginMulticast(mcastaddr, port);
|
||||
KNX_DEBUG_SERIAL.printf("multicast setup result %d\n", result);
|
||||
}
|
||||
|
||||
void LibretinyPlatform::closeMultiCast()
|
||||
{
|
||||
_udp.stop();
|
||||
}
|
||||
|
||||
bool LibretinyPlatform::sendBytesMultiCast(uint8_t * buffer, uint16_t len)
|
||||
{
|
||||
_udp.beginMulticastPacket();
|
||||
_udp.write(buffer, len);
|
||||
_udp.endPacket();
|
||||
return true;
|
||||
}
|
||||
|
||||
int LibretinyPlatform::readBytesMultiCast(uint8_t * buffer, uint16_t maxLen)
|
||||
{
|
||||
int len = _udp.parsePacket();
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
if (len > maxLen)
|
||||
{
|
||||
KNX_DEBUG_SERIAL.printf("udp buffer to small. was %d, needed %d\n", maxLen, len);
|
||||
fatalError();
|
||||
}
|
||||
|
||||
_udp.read(buffer, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
bool LibretinyPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
|
||||
{
|
||||
IPAddress ucastaddr(htonl(addr));
|
||||
println("sendBytesUniCast endPacket fail");
|
||||
|
||||
if(_udp.beginPacket(ucastaddr, port) == 1)
|
||||
{
|
||||
_udp.write(buffer, len);
|
||||
|
||||
if(_udp.endPacket() == 0)
|
||||
println("sendBytesUniCast endPacket fail");
|
||||
}
|
||||
else
|
||||
println("sendBytesUniCast beginPacket fail");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t LibretinyPlatform::flashEraseBlockSize()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
size_t LibretinyPlatform::flashPageSize()
|
||||
{
|
||||
return 256;
|
||||
}
|
||||
|
||||
uint8_t* LibretinyPlatform::userFlashStart()
|
||||
{
|
||||
lt_flash_read(KNX_FLASH_OFFSET, NVS_buffer, KNX_FLASH_SIZE);
|
||||
return NVS_buffer;
|
||||
}
|
||||
|
||||
size_t LibretinyPlatform::userFlashSizeEraseBlocks()
|
||||
{
|
||||
if(KNX_FLASH_SIZE <= 0)
|
||||
return 0;
|
||||
else
|
||||
return ( (KNX_FLASH_SIZE - 1) / (flashPageSize() * flashEraseBlockSize())) + 1;
|
||||
}
|
||||
|
||||
void LibretinyPlatform::flashErase(uint16_t eraseBlockNum)
|
||||
{
|
||||
// 16 pages x 256byte/page = 4096byte
|
||||
lt_flash_erase_block(KNX_FLASH_OFFSET + eraseBlockNum * flashPageSize() * flashEraseBlockSize());
|
||||
}
|
||||
|
||||
void LibretinyPlatform::flashWritePage(uint16_t pageNumber, uint8_t* data)
|
||||
{
|
||||
lt_flash_write(KNX_FLASH_OFFSET + pageNumber * flashPageSize(), data, flashPageSize());
|
||||
}
|
||||
|
||||
void LibretinyPlatform::writeBufferedEraseBlock()
|
||||
{
|
||||
if(_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty)
|
||||
{
|
||||
lt_flash_erase_block(KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize());
|
||||
lt_flash_write(KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize(), _eraseblockBuffer, flashPageSize() * flashEraseBlockSize());
|
||||
_bufferedEraseblockDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
53
src/libretiny_platform.h
Normal file
53
src/libretiny_platform.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifdef LIBRETINY
|
||||
#include "arduino_platform.h"
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <LwIPUdp.h>
|
||||
|
||||
class LibretinyPlatform : public ArduinoPlatform
|
||||
{
|
||||
public:
|
||||
LibretinyPlatform();
|
||||
LibretinyPlatform(HardwareSerial* s);
|
||||
|
||||
// ip stuff
|
||||
uint32_t currentIpAddress() override;
|
||||
uint32_t currentSubnetMask() override;
|
||||
uint32_t currentDefaultGateway() override;
|
||||
void macAddress(uint8_t* addr) override;
|
||||
|
||||
// unique serial number
|
||||
uint32_t uniqueSerialNumber() override;
|
||||
|
||||
// basic stuff
|
||||
void restart();
|
||||
|
||||
//multicast
|
||||
void setupMultiCast(uint32_t addr, uint16_t port) override;
|
||||
void closeMultiCast() override;
|
||||
bool sendBytesMultiCast(uint8_t* buffer, uint16_t len) override;
|
||||
int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen) override;
|
||||
|
||||
//unicast
|
||||
bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) override;
|
||||
|
||||
// size of one EraseBlock in pages
|
||||
virtual size_t flashEraseBlockSize();
|
||||
// size of one flash page in bytes
|
||||
virtual size_t flashPageSize();
|
||||
// start of user flash aligned to start of an erase block
|
||||
virtual uint8_t* userFlashStart();
|
||||
// size of the user flash in EraseBlocks
|
||||
virtual size_t userFlashSizeEraseBlocks();
|
||||
// relativ to userFlashStart
|
||||
virtual void flashErase(uint16_t eraseBlockNum);
|
||||
// write a single page to flash (pageNumber relative to userFashStart
|
||||
virtual void flashWritePage(uint16_t pageNumber, uint8_t* data);
|
||||
|
||||
// writes _eraseblockBuffer to flash - overrides Plattform::writeBufferedEraseBlock() for performance optimization only
|
||||
void writeBufferedEraseBlock();
|
||||
private:
|
||||
WiFiUDP _udp;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user