[lightning-ln882h] Add support for Lightning LN882H family (#312)
* fix mbedtls bad pointer in function call (prototype mismatch) * fix issue with weak families functions implemented in static library, it will never be linked. fixed by redefining prototypes inside families * [ln882x] add support for lightning ln882x & ln882h families * add i2c (wire) support * add analog (adc) support * add watchdog support * [ln882x] changed default uart 0/1 pins; added board wl2s * [ln882x] fix IRQ & ADC pins * [ln882x] boards cosmetic * [ln882x] wifi sta use otp mac addr by default; re-enabled wifi powersave mode * [ln882x] clang-format clean code * [ln882x] clang-format clean code * Update families.json * Apply suggestions from code review * [ln882x] reformat json board files * [ln882x] os_queue cleanup * [ln882x] removed Beken auto-download command * [ln882x] removed personal script file * [ln882x] removed unusefull pi section in debugging.md * [ln882x] removed Arduino.h and changed private I2C definition * [ln882x] updated README.md * [ln882x] changed pin naming scheme to PA/PB * [ln882x] clean code * [ln882x] clean code * [ln882x] add ota image verification * Update push-dev.yml * [ln882x] fix boards ADC missing inputs] * [ln882x] removed reg_xxx fixup files and use include guards instead * [ln882x] cleanup code * [ln882x] cleanup code * [ln882x] fix lt_init weak functions linking * [ln882x] revert lt_api.h modification, fixed with previous commit * [ln882x] setup UF2 firmware for flasher with partitions * [ln882x] update README.md * [ln882x] include ln_wifi.h and ln_serial.h to avoid including bad headers on case insensitive systems * [ln882x] Replace RingBuffer by SerialRingBuffer * [ln882x] clang-format * [ln882x] update README.md * Apply suggestions from code review * Reformat board JSON files * Add mkdocs link redirect * Update ltchiptool to v4.12.0 --------- Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
This commit is contained in:
@@ -173,7 +173,7 @@ int MbedTLSClient::connect(
|
||||
|
||||
#ifdef MBEDTLS_SSL_ALPN
|
||||
if (_alpnProtocols) {
|
||||
ret = mbedtls_ssl_conf_alpn_protocols(&_sslCfg, _alpnProtocols);
|
||||
ret = mbedtls_ssl_conf_alpn_protocols(_sslCfg, _alpnProtocols);
|
||||
LT_RET_NZ(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,7 @@ typedef enum {
|
||||
F_BK7231N = 0x7B3EF230, // Beken 7231N
|
||||
F_BK7251 = 0x6A82CC42, // Beken 7251/7252
|
||||
F_BL60X = 0xDE1270B7, // Boufallo 602
|
||||
F_LN882H = 0xA38090A8, // Lightning LN882H
|
||||
} lt_cpu_family_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -44,4 +45,8 @@ typedef enum {
|
||||
BL2028N = BK7231N,
|
||||
BK7231S = BK7231T,
|
||||
BK7231U = BK7231T,
|
||||
// Lightning LN882x
|
||||
LN882HF = CPU_MODEL(F_LN882H, 0x00), // TODO / QFN24
|
||||
LN882HK = CPU_MODEL(F_LN882H, 0x00), // TODO / QFN32
|
||||
LN882HC = CPU_MODEL(F_LN882H, 0x00), // TODO / QFN40
|
||||
} lt_cpu_model_t;
|
||||
|
||||
99
cores/lightning-ln882h/arduino/libraries/Serial/Serial.cpp
Normal file
99
cores/lightning-ln882h/arduino/libraries/Serial/Serial.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#include "SerialPrivate.h"
|
||||
|
||||
extern Serial_t *serial_handles[SER_PORT_NUM];
|
||||
|
||||
#if LT_HW_UART0
|
||||
SerialClass Serial0(0, PIN_SERIAL0_RX, PIN_SERIAL0_TX);
|
||||
|
||||
static void callback_uart0(void) {
|
||||
SerialData *data = (SerialData *)Serial0.data;
|
||||
char ch;
|
||||
while (serial_read(serial_handles[0], &ch, 1)) {
|
||||
data->buf.store_char(ch);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define callback_uart0 NULL
|
||||
#endif
|
||||
#if LT_HW_UART1
|
||||
SerialClass Serial1(1, PIN_SERIAL1_RX, PIN_SERIAL1_TX);
|
||||
|
||||
static void callback_uart1(void) {
|
||||
SerialData *data = (SerialData *)Serial1.data;
|
||||
char ch;
|
||||
while (serial_read(serial_handles[1], &ch, 1)) {
|
||||
data->buf.store_char(ch);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define callback_uart1 NULL
|
||||
#endif
|
||||
#if LT_HW_UART2
|
||||
SerialClass Serial2(2, PIN_SERIAL2_RX, PIN_SERIAL2_TX);
|
||||
|
||||
static void callback_uart2(void) {
|
||||
SerialData *data = (SerialData *)Serial2.data;
|
||||
char ch;
|
||||
while (serial_read(serial_handles[2], &ch, 1)) {
|
||||
data->buf.store_char(ch);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define callback_uart2 NULL
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
static const serial_rx_callbcak serial_rx_callbacks[SER_PORT_NUM] = {
|
||||
callback_uart0,
|
||||
callback_uart1,
|
||||
callback_uart2
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void SerialClass::begin(unsigned long baudrate, uint16_t config) {
|
||||
if (!this->data) {
|
||||
this->data = new SerialData();
|
||||
this->buf = &BUF;
|
||||
}
|
||||
|
||||
if (this->baudrate != baudrate || this->config != config)
|
||||
this->configure(baudrate, config);
|
||||
}
|
||||
|
||||
void SerialClass::configure(unsigned long baudrate, uint16_t config) {
|
||||
if (!this->data)
|
||||
return;
|
||||
|
||||
serial_init(serial_handles[port], (serial_port_id_t)port, baudrate, serial_rx_callbacks[port]);
|
||||
|
||||
this->baudrate = baudrate;
|
||||
this->config = config;
|
||||
}
|
||||
|
||||
void SerialClass::end() {
|
||||
if (!this->data)
|
||||
return;
|
||||
|
||||
serial_deinit(serial_handles[port]);
|
||||
|
||||
delete (SerialData *)this->data;
|
||||
delete this->buf;
|
||||
this->data = NULL;
|
||||
this->buf = NULL;
|
||||
this->baudrate = 0;
|
||||
}
|
||||
|
||||
void SerialClass::flush() {
|
||||
if (!this->data)
|
||||
return;
|
||||
serial_flush(serial_handles[port]);
|
||||
}
|
||||
|
||||
size_t SerialClass::write(uint8_t c) {
|
||||
if (!this->data)
|
||||
return 0;
|
||||
serial_putchar(serial_handles[port], c);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
typedef struct {
|
||||
SerialRingBuffer buf;
|
||||
void (*callback)(void);
|
||||
} SerialData;
|
||||
|
||||
#define DATA ((SerialData *)this->data)
|
||||
#define BUF (DATA->buf)
|
||||
59
cores/lightning-ln882h/arduino/libraries/WiFi/WiFi.cpp
Normal file
59
cores/lightning-ln882h/arduino/libraries/WiFi/WiFi.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-18. */
|
||||
|
||||
#include "WiFiPrivate.h"
|
||||
|
||||
WiFiClass::WiFiClass() {
|
||||
data = (WiFiData *)calloc(1, sizeof(WiFiData));
|
||||
|
||||
DATA->scanSem = xSemaphoreCreateBinary();
|
||||
}
|
||||
|
||||
WiFiClass::~WiFiClass() {
|
||||
vSemaphoreDelete(DATA->scanSem);
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
WiFiAuthMode securityTypeToAuthMode(uint8_t type) {
|
||||
switch (type) {
|
||||
case LN_WIFI_AUTH_OPEN:
|
||||
return WIFI_AUTH_OPEN;
|
||||
case LN_WIFI_AUTH_WEP:
|
||||
return WIFI_AUTH_WEP;
|
||||
case LN_WIFI_AUTH_WPA_PSK:
|
||||
return WIFI_AUTH_WPA_PSK;
|
||||
case LN_WIFI_AUTH_WPA2_PSK:
|
||||
return WIFI_AUTH_WPA2_PSK;
|
||||
case LN_WIFI_AUTH_WPA_WPA2_PSK:
|
||||
return WIFI_AUTH_WPA_WPA2_PSK;
|
||||
case LN_WIFI_AUTH_WPA2_ENTERPRISE:
|
||||
return WIFI_AUTH_WPA2_ENTERPRISE;
|
||||
case LN_WIFI_AUTH_WPA3_SAE:
|
||||
return WIFI_AUTH_WPA3_PSK;
|
||||
case LN_WIFI_AUTH_WPA2_PSK_WPA3_SAE:
|
||||
return WIFI_AUTH_WPA2_WPA3_PSK;
|
||||
}
|
||||
return WIFI_AUTH_INVALID;
|
||||
}
|
||||
|
||||
uint8_t authModeToSecurityType(WiFiAuthMode auth) {
|
||||
switch (auth) {
|
||||
case WIFI_AUTH_OPEN:
|
||||
return LN_WIFI_AUTH_OPEN;
|
||||
case WIFI_AUTH_WEP:
|
||||
return LN_WIFI_AUTH_WEP;
|
||||
case WIFI_AUTH_WPA_PSK:
|
||||
return LN_WIFI_AUTH_WPA_PSK;
|
||||
case WIFI_AUTH_WPA2_PSK:
|
||||
return LN_WIFI_AUTH_WPA2_PSK;
|
||||
case WIFI_AUTH_WPA_WPA2_PSK:
|
||||
return LN_WIFI_AUTH_WPA_WPA2_PSK;
|
||||
case WIFI_AUTH_WPA2_ENTERPRISE:
|
||||
return LN_WIFI_AUTH_WPA2_ENTERPRISE;
|
||||
case WIFI_AUTH_WPA3_PSK:
|
||||
return LN_WIFI_AUTH_WPA3_SAE;
|
||||
case WIFI_AUTH_WPA2_WPA3_PSK:
|
||||
return LN_WIFI_AUTH_WPA2_PSK_WPA3_SAE;
|
||||
}
|
||||
return WIFI_AUTH_INVALID;
|
||||
}
|
||||
134
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiAP.cpp
Normal file
134
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiAP.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-18. */
|
||||
|
||||
#include "WiFiPrivate.h"
|
||||
|
||||
static uint8_t psk_value[40] = {0x0};
|
||||
static uint8_t mac_addr[6] = {0x00, 0x50, 0xC2, 0x7F, 0xBC, 0x01};
|
||||
|
||||
bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bool ssidHidden, int maxClients) {
|
||||
if (!enableAP(true))
|
||||
return false;
|
||||
if (!validate(ssid, passphrase))
|
||||
return false;
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
WiFiNetworkInfo &info = DATA->ap;
|
||||
if (info.ssid != ssid)
|
||||
// free network info, if not called from restoreAPConfig()
|
||||
resetNetworkInfo(info);
|
||||
|
||||
if (info.ssid != ssid)
|
||||
info.ssid = strdup(ssid);
|
||||
if (info.password != passphrase)
|
||||
info.password = strdup(passphrase);
|
||||
info.ssidHidden = ssidHidden;
|
||||
info.bssid = softAPmacAddress(mac_addr);
|
||||
info.channel = channel;
|
||||
info.auth = passphrase ? LN_WIFI_AUTH_WPA2_PSK : LN_WIFI_AUTH_OPEN;
|
||||
|
||||
LT_IM(WIFI, "Creating SoftAP %s", ssid);
|
||||
|
||||
// clang-format off
|
||||
wifi_softap_cfg_t ap_cfg = {
|
||||
.ssid = info.ssid,
|
||||
.pwd = info.password,
|
||||
.bssid = info.bssid,
|
||||
.ext_cfg = {
|
||||
.channel = (uint8_t)info.channel,
|
||||
.authmode = (ln_wifi_auth_mode_t)info.auth,
|
||||
.ssid_hidden = info.ssidHidden,
|
||||
.beacon_interval = 100,
|
||||
.psk_value = NULL,
|
||||
}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
if ((strlen(ap_cfg.pwd) != 0) && (ap_cfg.ext_cfg.authmode != LN_WIFI_AUTH_OPEN) &&
|
||||
(ap_cfg.ext_cfg.authmode != LN_WIFI_AUTH_WEP)) {
|
||||
memset(psk_value, 0, sizeof(psk_value));
|
||||
if (0 == ln_psk_calc(ap_cfg.ssid, ap_cfg.pwd, psk_value, sizeof(psk_value))) {
|
||||
ap_cfg.ext_cfg.psk_value = psk_value;
|
||||
hexdump(psk_value, sizeof(psk_value));
|
||||
}
|
||||
}
|
||||
|
||||
// wifi start
|
||||
__wrap_ln_printf_disable();
|
||||
int ret = wifi_softap_start(&ap_cfg);
|
||||
__wrap_ln_printf_enable();
|
||||
if (ret != 0) {
|
||||
LT_EM(WIFI, "SoftAP failed; ret=%d", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet) {
|
||||
if (!enableAP(true))
|
||||
return false;
|
||||
WiFiNetworkInfo &info = DATA->ap;
|
||||
|
||||
// dhcp server config
|
||||
server_config_t server_config;
|
||||
server_config.server.addr = localIP;
|
||||
server_config.port = 67;
|
||||
server_config.lease = 2880;
|
||||
server_config.renew = 2880;
|
||||
server_config.ip_start.addr = IPAddress(localIP[0], localIP[1], localIP[2], 100);
|
||||
server_config.ip_end.addr = IPAddress(localIP[0], localIP[1], localIP[2], 150);
|
||||
server_config.client_max = 3;
|
||||
dhcpd_curr_config_set(&server_config);
|
||||
|
||||
// net device config
|
||||
tcpip_ip_info_t ip_info;
|
||||
ip_info.ip.addr = info.localIP = localIP;
|
||||
ip_info.netmask.addr = info.subnet = subnet;
|
||||
ip_info.gw.addr = info.gateway = gateway;
|
||||
netdev_set_ip_info(NETIF_IDX_AP, &ip_info);
|
||||
netdev_set_active(NETIF_IDX_AP);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::softAPdisconnect(bool wifiOff) {
|
||||
return enableAP(false);
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::softAPgetStationNum() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::softAPIP() {
|
||||
return netif_ip_addr4(netdev_get_netif(NETIF_IDX_AP))->addr;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::softAPSubnetMask() {
|
||||
return netif_ip_netmask4(netdev_get_netif(NETIF_IDX_AP))->addr;
|
||||
}
|
||||
|
||||
const char *WiFiClass::softAPgetHostname() {
|
||||
return netif_get_hostname(netdev_get_netif(NETIF_IDX_AP));
|
||||
}
|
||||
|
||||
bool WiFiClass::softAPsetHostname(const char *hostname) {
|
||||
netif_set_hostname(netdev_get_netif(NETIF_IDX_AP), (char *)hostname);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *WiFiClass::softAPmacAddress(uint8_t *mac) {
|
||||
memcpy(mac, netdev_get_netif(NETIF_IDX_AP)->hwaddr, MAC_ADDRESS_LEN);
|
||||
return mac;
|
||||
}
|
||||
|
||||
String WiFiClass::softAPmacAddress(void) {
|
||||
uint8_t mac[MAC_ADDRESS_LEN];
|
||||
softAPmacAddress(mac);
|
||||
return macToString(mac);
|
||||
}
|
||||
|
||||
const String WiFiClass::softAPSSID(void) {
|
||||
WiFiNetworkInfo &info = DATA->ap;
|
||||
return (char *)info.ssid;
|
||||
}
|
||||
122
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiEvents.cpp
Normal file
122
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiEvents.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-10. */
|
||||
|
||||
#include "WiFiPrivate.h"
|
||||
|
||||
void wifiEventSendArduino(EventId event) {
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
if (!pWiFi)
|
||||
return; // failsafe
|
||||
pWiFi->postEvent(event, eventInfo);
|
||||
}
|
||||
|
||||
static void wifiEventStaStartup(void *arg) {
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_START);
|
||||
}
|
||||
|
||||
static void wifiEventStaConnected(void *arg) {
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
if (!pWiFi)
|
||||
return; // failsafe
|
||||
|
||||
String ssid = pWiFi->SSID();
|
||||
eventInfo.wifi_sta_connected.ssid_len = ssid.length();
|
||||
eventInfo.wifi_sta_connected.channel = pWiFi->channel();
|
||||
eventInfo.wifi_sta_connected.authmode = pWiFi->getEncryption();
|
||||
memcpy(eventInfo.wifi_sta_connected.ssid, ssid.c_str(), eventInfo.wifi_sta_connected.ssid_len + 1);
|
||||
memcpy(eventInfo.wifi_sta_connected.bssid, pWiFi->BSSID(), 6);
|
||||
|
||||
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_CONNECTED, eventInfo);
|
||||
}
|
||||
|
||||
static void wifiEventStaDisconnected(void *arg) {
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
if (!pWiFi)
|
||||
return; // failsafe
|
||||
|
||||
eventInfo.wifi_sta_disconnected.ssid_len = 0;
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_ASSOC_LEAVE;
|
||||
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_DISCONNECTED, eventInfo);
|
||||
}
|
||||
|
||||
static void wifiEventStaConnectFailed(void *arg) {
|
||||
wifi_sta_connect_failed_reason_t reason = *(wifi_sta_connect_failed_reason_t *)arg;
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
if (!pWiFi)
|
||||
return; // failsafe
|
||||
|
||||
eventInfo.wifi_sta_disconnected.ssid_len = 0;
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_UNSPECIFIED;
|
||||
switch (reason) {
|
||||
case WIFI_STA_CONN_WRONG_PWD:
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_AUTH_FAIL;
|
||||
break;
|
||||
case WIFI_STA_CONN_TARGET_AP_NOT_FOUND:
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_NO_AP_FOUND;
|
||||
break;
|
||||
case WIFI_STA_CONN_TIMEOUT:
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_BEACON_TIMEOUT;
|
||||
break;
|
||||
case WIFI_STA_CONN_REFUSED:
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_CONNECTION_FAIL;
|
||||
break;
|
||||
}
|
||||
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_DISCONNECTED, eventInfo);
|
||||
}
|
||||
|
||||
static void wifiEventSoftAPStartup(void *arg) {
|
||||
netdev_set_state(NETIF_IDX_AP, NETDEV_UP);
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_START);
|
||||
}
|
||||
|
||||
static void wifiEventSoftAPAssociated(void *arg) {
|
||||
const uint8_t *mac_addr = (const uint8_t *)arg;
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
if (!pWiFi)
|
||||
return; // failsafe
|
||||
|
||||
memcpy(eventInfo.wifi_ap_staconnected.mac, mac_addr, 6);
|
||||
pWiFi->postEvent(ARDUINO_EVENT_WIFI_AP_STACONNECTED, eventInfo);
|
||||
}
|
||||
|
||||
static void wifiEventSoftAPDisassociated(void *arg) {
|
||||
const uint8_t *mac_addr = (const uint8_t *)arg;
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
if (!pWiFi)
|
||||
return; // failsafe
|
||||
|
||||
memcpy(eventInfo.wifi_ap_staconnected.mac, mac_addr, 6);
|
||||
pWiFi->postEvent(ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, eventInfo);
|
||||
}
|
||||
|
||||
static void wifiEventIpReceived(struct netif *nif) {
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
if (!pWiFi || !nif)
|
||||
return; // failsafe
|
||||
|
||||
eventInfo.got_ip.if_index = 0;
|
||||
eventInfo.got_ip.ip_changed = true;
|
||||
eventInfo.got_ip.ip_info.ip.addr = nif->ip_addr.addr;
|
||||
eventInfo.got_ip.ip_info.gw.addr = nif->gw.addr;
|
||||
eventInfo.got_ip.ip_info.netmask.addr = nif->netmask.addr;
|
||||
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_GOT_IP, eventInfo);
|
||||
}
|
||||
|
||||
void registerWifiHandlers() {
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_STARTUP, &wifiEventStaStartup);
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_CONNECTED, &wifiEventStaConnected);
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_DISCONNECTED, &wifiEventStaDisconnected);
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_CONNECT_FAILED, &wifiEventStaConnectFailed);
|
||||
|
||||
netdev_get_ip_cb_set(&wifiEventIpReceived);
|
||||
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_SOFTAP_STARTUP, &wifiEventSoftAPStartup);
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_SOFTAP_ASSOCIATED, &wifiEventSoftAPAssociated);
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_SOFTAP_DISASSOCIATED, &wifiEventSoftAPDisassociated);
|
||||
}
|
||||
144
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiGeneric.cpp
Normal file
144
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiGeneric.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-10. */
|
||||
|
||||
#include "WiFiPrivate.h"
|
||||
|
||||
static uint8_t psk_value[40] = {0x0};
|
||||
|
||||
bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
__wrap_ln_printf_disable();
|
||||
|
||||
if (!DATA->initialized) {
|
||||
// rf preprocess,img cal
|
||||
wifi_rf_calibration();
|
||||
// Init wifi stack.
|
||||
wifi_init();
|
||||
// Init lwip stack.
|
||||
LT_IM(WIFI, "Initializing LwIP");
|
||||
lwip_tcpip_init();
|
||||
// Init wifi manager
|
||||
wifi_manager_init();
|
||||
// Register event handlers
|
||||
registerWifiHandlers();
|
||||
DATA->mode = WIFI_MODE_NULL;
|
||||
DATA->initialized = true;
|
||||
}
|
||||
|
||||
LT_HEAP_I();
|
||||
WiFiMode currentMode = DATA->mode;
|
||||
WiFiNetworkInfo &staInfo = DATA->sta;
|
||||
WiFiNetworkInfo &apInfo = DATA->ap;
|
||||
|
||||
if (mode == WIFI_MODE_APSTA) {
|
||||
LT_EM(WIFI, "AP+STA mode not supported!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (sta == WLMODE_ENABLE) {
|
||||
LT_DM(WIFI, "Enabling STA");
|
||||
|
||||
// 1. sta mac get
|
||||
uint8_t mac_addr[6];
|
||||
setMacAddress(macAddress(mac_addr));
|
||||
|
||||
// 2. net device(lwip)
|
||||
netdev_set_active(NETIF_IDX_STA);
|
||||
|
||||
// 3. wifi start
|
||||
wifi_sta_start(mac_addr, WIFI_NO_POWERSAVE);
|
||||
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_START);
|
||||
} else if (sta == WLMODE_DISABLE) {
|
||||
LT_DM(WIFI, "Disabling STA");
|
||||
wifi_sta_disconnect();
|
||||
netdev_set_state(NETIF_IDX_STA, NETDEV_DOWN);
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_STOP);
|
||||
}
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
if (ap == WLMODE_ENABLE) {
|
||||
LT_DM(WIFI, "Enabling AP");
|
||||
|
||||
// 1. ap mac get
|
||||
uint8_t mac_addr[6];
|
||||
sysparam_softap_mac_get(mac_addr);
|
||||
netdev_set_mac_addr(NETIF_IDX_AP, mac_addr);
|
||||
|
||||
// 2. net device(lwip)
|
||||
netdev_set_active(NETIF_IDX_AP);
|
||||
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_START);
|
||||
} else if (ap == WLMODE_DISABLE) {
|
||||
LT_DM(WIFI, "Disabling AP");
|
||||
wifi_softap_deauth_all();
|
||||
netdev_set_state(NETIF_IDX_AP, NETDEV_DOWN);
|
||||
|
||||
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_STOP);
|
||||
}
|
||||
|
||||
DATA->mode = mode;
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
__wrap_ln_printf_enable();
|
||||
return true;
|
||||
|
||||
error:
|
||||
__wrap_ln_printf_enable();
|
||||
return false;
|
||||
}
|
||||
|
||||
WiFiMode WiFiClass::getMode() {
|
||||
if (!DATA->initialized)
|
||||
return WIFI_MODE_NULL;
|
||||
|
||||
// return fake value because the chip doesn't report the mode before it is started
|
||||
return DATA->mode;
|
||||
|
||||
/*switch (wifi_current_mode_get()) {
|
||||
case LN_WIFI_MODE_STATION:
|
||||
return WIFI_MODE_STA;
|
||||
case LN_WIFI_MODE_AP:
|
||||
return WIFI_MODE_AP;
|
||||
case LN_WIFI_MODE_AP_STATION:
|
||||
return WIFI_MODE_APSTA;
|
||||
}
|
||||
return WIFI_MODE_NULL;*/
|
||||
}
|
||||
|
||||
WiFiStatus WiFiClass::status() {
|
||||
wifi_sta_status_t status = WIFI_STA_STATUS_STARTUP;
|
||||
wifi_get_sta_status(&status);
|
||||
if (status == WIFI_STA_STATUS_CONNECTED) {
|
||||
return WL_CONNECTED;
|
||||
} else {
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
bool WiFiClass::setSleep(bool enable) {
|
||||
LT_DM(WIFI, "WiFi sleep mode %u", enable);
|
||||
|
||||
if (enable) {
|
||||
if (wifi_sta_set_powersave(WIFI_MAX_POWERSAVE))
|
||||
return false;
|
||||
} else {
|
||||
if (wifi_sta_set_powersave(WIFI_NO_POWERSAVE))
|
||||
return false;
|
||||
}
|
||||
DATA->sleep = enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::getSleep() {
|
||||
return DATA->sleep;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::hostByName(const char *hostname) {
|
||||
ip_addr_t ip;
|
||||
int ret = netconn_gethostbyname(hostname, &ip);
|
||||
if (ret == ERR_OK) {
|
||||
return ip.addr;
|
||||
}
|
||||
return IPAddress();
|
||||
}
|
||||
47
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiPrivate.h
Normal file
47
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiPrivate.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
extern "C" {
|
||||
// copy defines from PIO builder (for IDE to understand)
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#define LWIP_NETIF_HOSTNAME 1
|
||||
#define LWIP_SO_RCVBUF 1
|
||||
|
||||
#include <lwip/api.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/netifapi.h>
|
||||
#include <netif/ethernetif.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
} // extern "C"
|
||||
|
||||
// WiFi.cpp
|
||||
extern WiFiAuthMode securityTypeToAuthMode(uint8_t type);
|
||||
uint8_t authModeToSecurityType(WiFiAuthMode auth);
|
||||
|
||||
// WiFiEvents.cpp
|
||||
extern void wifiEventSendArduino(EventId event);
|
||||
extern void registerWifiHandlers();
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
bool sleep;
|
||||
WiFiMode mode;
|
||||
SemaphoreHandle_t scanSem;
|
||||
WiFiNetworkInfo sta;
|
||||
WiFiNetworkInfo ap;
|
||||
} WiFiData;
|
||||
|
||||
#define DATA ((WiFiData *)data)
|
||||
#define pDATA ((WiFiData *)pWiFi->data)
|
||||
#define cDATA ((WiFiData *)cls->data)
|
||||
|
||||
#define IP_FMT "%u.%u.%u.%u"
|
||||
213
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiSTA.cpp
Normal file
213
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiSTA.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-10. */
|
||||
|
||||
#include "WiFiPrivate.h"
|
||||
|
||||
WiFiStatus WiFiClass::begin(
|
||||
const char *ssid,
|
||||
const char *passphrase,
|
||||
int32_t channel,
|
||||
const uint8_t *bssid,
|
||||
bool connect
|
||||
) {
|
||||
if (!enableSTA(true))
|
||||
return WL_CONNECT_FAILED;
|
||||
if (!validate(ssid, passphrase))
|
||||
return WL_CONNECT_FAILED;
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
WiFiNetworkInfo &info = DATA->sta;
|
||||
if (info.ssid != ssid)
|
||||
// free network info, if not called from restoreSTAConfig()
|
||||
resetNetworkInfo(info);
|
||||
|
||||
if (info.ssid != ssid)
|
||||
info.ssid = strdup(ssid);
|
||||
info.channel = channel;
|
||||
info.auth = LN_WIFI_AUTH_OPEN;
|
||||
|
||||
if (passphrase) {
|
||||
if (info.password != passphrase)
|
||||
info.password = strdup(passphrase);
|
||||
info.auth = LN_WIFI_AUTH_WPA_WPA2_PSK;
|
||||
}
|
||||
|
||||
if (reconnect(bssid))
|
||||
return WL_CONNECTED;
|
||||
else
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
|
||||
if (!enableSTA(true))
|
||||
return false;
|
||||
WiFiNetworkInfo &info = DATA->sta;
|
||||
struct netif *ifs = netdev_get_netif(NETIF_IDX_STA);
|
||||
|
||||
ip4_addr_t d1, d2;
|
||||
d1.addr = info.dns1 = dns1;
|
||||
d2.addr = info.dns2 = dns2;
|
||||
if (d1.addr)
|
||||
dns_setserver(0, &d1);
|
||||
if (d2.addr)
|
||||
dns_setserver(0, &d2);
|
||||
|
||||
if (!localIP[0]) {
|
||||
info.localIP = 0;
|
||||
netifapi_dhcp_start(ifs);
|
||||
return true;
|
||||
}
|
||||
ip4_addr_t ipaddr, netmask, gw;
|
||||
ipaddr.addr = info.localIP = localIP;
|
||||
netmask.addr = info.subnet = subnet;
|
||||
gw.addr = info.gateway = gateway;
|
||||
netif_set_addr(ifs, &ipaddr, &netmask, &gw);
|
||||
netifapi_dhcp_release_and_stop(ifs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::reconnect(const uint8_t *bssid) {
|
||||
WiFiNetworkInfo &info = DATA->sta;
|
||||
LT_IM(WIFI, "Connecting to %s (bssid=%p)", info.ssid, bssid);
|
||||
|
||||
if (bssid != info.bssid) {
|
||||
if (!info.bssid)
|
||||
info.bssid = (uint8_t *)malloc(BSSID_LEN);
|
||||
memcpy(info.bssid, bssid, BSSID_LEN);
|
||||
}
|
||||
|
||||
uint8_t psk_value[40] = {0x0};
|
||||
wifi_sta_connect_t connect = {
|
||||
.ssid = info.ssid,
|
||||
.pwd = info.password,
|
||||
.bssid = NULL, // info.bssid,
|
||||
.psk_value = NULL,
|
||||
};
|
||||
wifi_scan_cfg_t scan_cfg = {
|
||||
.channel = (uint8_t)info.channel,
|
||||
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
|
||||
.scan_time = 5,
|
||||
};
|
||||
|
||||
if (0 == ln_psk_calc(connect.ssid, connect.pwd, psk_value, sizeof(psk_value)))
|
||||
connect.psk_value = psk_value;
|
||||
|
||||
LT_DM(WIFI, "Starting WiFi...");
|
||||
|
||||
__wrap_ln_printf_disable();
|
||||
int ret = wifi_sta_connect(&connect, &scan_cfg);
|
||||
// int ret = wifi_sta_connect_v2(&connect, &scan_cfg, 10);
|
||||
__wrap_ln_printf_enable();
|
||||
|
||||
LT_DM(WIFI, "Start OK (%d)", ret);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::disconnect(bool wifiOff) {
|
||||
free(DATA->sta.ssid);
|
||||
DATA->sta.ssid = NULL;
|
||||
int ret = wifi_sta_disconnect();
|
||||
if (wifiOff)
|
||||
enableSTA(false);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
bool WiFiClass::setAutoReconnect(bool autoReconnect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WiFiClass::getAutoReconnect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::localIP() {
|
||||
tcpip_ip_info_t ip_info;
|
||||
netdev_get_ip_info(NETIF_IDX_STA, &ip_info);
|
||||
return IPAddress(ip_info.ip.addr);
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::subnetMask() {
|
||||
tcpip_ip_info_t ip_info;
|
||||
netdev_get_ip_info(NETIF_IDX_STA, &ip_info);
|
||||
return IPAddress(ip_info.netmask.addr);
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::gatewayIP() {
|
||||
tcpip_ip_info_t ip_info;
|
||||
netdev_get_ip_info(NETIF_IDX_STA, &ip_info);
|
||||
return IPAddress(ip_info.gw.addr);
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::dnsIP(uint8_t dns_no) {
|
||||
return dns_getserver(dns_no)->addr;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::broadcastIP() {
|
||||
return calculateBroadcast(localIP(), subnetMask());
|
||||
}
|
||||
|
||||
const char *WiFiClass::getHostname() {
|
||||
struct netif *ifs = netdev_get_netif(NETIF_IDX_STA);
|
||||
return netif_get_hostname(ifs);
|
||||
}
|
||||
|
||||
bool WiFiClass::setHostname(const char *hostname) {
|
||||
struct netif *ifs = netdev_get_netif(NETIF_IDX_STA);
|
||||
netif_set_hostname(ifs, (char *)hostname);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *WiFiClass::macAddress(uint8_t *mac) {
|
||||
if (SYSPARAM_ERR_NONE == sysparam_sta_mac_get(mac))
|
||||
return mac;
|
||||
else
|
||||
LT_WM(WIFI, "sysparam sta mac get failed!");
|
||||
|
||||
lt_get_device_mac(mac);
|
||||
return mac;
|
||||
}
|
||||
|
||||
bool WiFiClass::setMacAddress(const uint8_t *mac) {
|
||||
sysparam_sta_mac_update(mac);
|
||||
return netdev_set_mac_addr(NETIF_IDX_STA, (uint8_t *)mac) == 0;
|
||||
}
|
||||
|
||||
const String WiFiClass::SSID() {
|
||||
const char *ssid = NULL;
|
||||
const uint8_t *bssid = NULL;
|
||||
wifi_get_sta_conn_info(&ssid, &bssid);
|
||||
return ssid;
|
||||
}
|
||||
|
||||
const String WiFiClass::psk() {
|
||||
if (!isConnected() || !DATA->sta.password)
|
||||
return "";
|
||||
return DATA->sta.password;
|
||||
}
|
||||
|
||||
uint8_t *WiFiClass::BSSID() {
|
||||
const char *ssid = NULL;
|
||||
const uint8_t *bssid = NULL;
|
||||
wifi_get_sta_conn_info(&ssid, &bssid);
|
||||
return (uint8_t *)bssid;
|
||||
}
|
||||
|
||||
int32_t WiFiClass::channel() {
|
||||
uint8_t channel = 0;
|
||||
wifi_get_channel(&channel);
|
||||
return (int32_t)channel;
|
||||
}
|
||||
|
||||
int8_t WiFiClass::RSSI() {
|
||||
int8_t rssi = 0;
|
||||
wifi_sta_get_rssi(&rssi);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
WiFiAuthMode WiFiClass::getEncryption() {
|
||||
ln_wifi_auth_mode_t mode;
|
||||
wifi_sta_get_connected_ap_security(&mode);
|
||||
return securityTypeToAuthMode(mode);
|
||||
}
|
||||
114
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiScan.cpp
Normal file
114
cores/lightning-ln882h/arduino/libraries/WiFi/WiFiScan.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-13. */
|
||||
|
||||
#include "WiFiPrivate.h"
|
||||
|
||||
static void scanHandler(void *arg) {
|
||||
WiFiClass *cls = (WiFiClass *)pWiFi;
|
||||
WiFiScanData *scan = cls->scan;
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
ln_list_t *list;
|
||||
uint8_t n = 0, node_count = 0;
|
||||
ap_info_node_t *pnode;
|
||||
|
||||
wifi_manager_ap_list_update_enable(LN_FALSE);
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_SCAN_COMPLETE, NULL);
|
||||
|
||||
// 1.get ap info list.
|
||||
if (wifi_manager_get_ap_list(&list, &node_count)) {
|
||||
LT_EM(WIFI, "Failed to get scan result");
|
||||
goto end;
|
||||
}
|
||||
LT_IM(WIFI, "Found %d APs", node_count);
|
||||
|
||||
cls->scanAlloc(node_count);
|
||||
if (!scan->ap) {
|
||||
LT_WM(WIFI, "scan->ap alloc failed");
|
||||
goto end;
|
||||
}
|
||||
|
||||
// 2.get all ap info in the list.
|
||||
LN_LIST_FOR_EACH_ENTRY(pnode, ap_info_node_t, list, list) {
|
||||
uint8_t *mac = (uint8_t *)pnode->info.bssid;
|
||||
ap_info_t *ap_info = &pnode->info;
|
||||
|
||||
scan->ap[n].ssid = strdup(ap_info->ssid);
|
||||
scan->ap[n].auth = securityTypeToAuthMode(ap_info->authmode);
|
||||
scan->ap[n].rssi = ap_info->rssi;
|
||||
scan->ap[n].channel = ap_info->channel;
|
||||
memcpy(scan->ap[n].bssid.addr, mac, 6);
|
||||
n++;
|
||||
}
|
||||
|
||||
end:
|
||||
scan->timeout = 0;
|
||||
if (scan->running) {
|
||||
// running == false means it was discarded (timeout)
|
||||
scan->running = false;
|
||||
xSemaphoreGive(cDATA->scanSem);
|
||||
|
||||
// Send event scan finished
|
||||
EventInfo eventInfo;
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
eventInfo.wifi_scan_done.status = 0;
|
||||
eventInfo.wifi_scan_done.number = scan->count;
|
||||
pWiFi->postEvent(ARDUINO_EVENT_WIFI_SCAN_DONE, eventInfo);
|
||||
}
|
||||
// wifi_manager_ap_list_update_enable(LN_TRUE);
|
||||
// wifi_sta_disconnect();
|
||||
LT_HEAP_I();
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint32_t maxMsPerChannel, uint8_t channel) {
|
||||
if (scan && scan->running) {
|
||||
if (scan->timeout && millis() > scan->timeout) {
|
||||
LT_WM(WIFI, "Scan timeout, discarding");
|
||||
scan->running = false;
|
||||
} else {
|
||||
return WIFI_SCAN_RUNNING;
|
||||
}
|
||||
}
|
||||
enableSTA(true);
|
||||
scanDelete();
|
||||
scanInit();
|
||||
|
||||
LT_IM(WIFI, "Starting WiFi scan");
|
||||
|
||||
__wrap_ln_printf_disable();
|
||||
|
||||
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_SCAN_COMPLETE, &scanHandler);
|
||||
wifi_manager_ap_list_update_enable(LN_TRUE);
|
||||
wifi_manager_cleanup_scan_results();
|
||||
|
||||
wifi_scan_cfg_t scan_cfg = {
|
||||
.channel = 0,
|
||||
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
|
||||
.scan_time = 5,
|
||||
};
|
||||
wifi_sta_scan(&scan_cfg);
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
scan->running = true;
|
||||
scan->timeout = millis() + maxMsPerChannel * 20 + 1000;
|
||||
|
||||
int16_t ret = WIFI_SCAN_RUNNING;
|
||||
if (!async) {
|
||||
LT_IM(WIFI, "Waiting for results");
|
||||
xSemaphoreTake(DATA->scanSem, 1); // reset the semaphore quickly
|
||||
xSemaphoreTake(DATA->scanSem, pdMS_TO_TICKS(maxMsPerChannel * 20));
|
||||
if (scan->running) {
|
||||
scanDelete();
|
||||
ret = WIFI_SCAN_FAILED;
|
||||
goto exit;
|
||||
}
|
||||
ret = scan->count;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
__wrap_ln_printf_enable();
|
||||
return ret;
|
||||
}
|
||||
295
cores/lightning-ln882h/arduino/libraries/Wire/Wire.cpp
Normal file
295
cores/lightning-ln882h/arduino/libraries/Wire/Wire.cpp
Normal file
@@ -0,0 +1,295 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2025-01-19. */
|
||||
|
||||
#include "wiring_private.h"
|
||||
#include <sdk_private.h>
|
||||
|
||||
#define I2C_PRIV i2c_init_t_def
|
||||
#include "Wire.h"
|
||||
|
||||
// Functions from I2C demo of SDK
|
||||
static uint8_t hal_i2c_master_7bit_write(uint32_t i2c_x_base, uint8_t dev_addr, const uint8_t *buf, uint16_t buf_len);
|
||||
static uint8_t hal_i2c_master_7bit_read(uint32_t i2c_x_base, uint8_t dev_addr, uint8_t *buf, uint16_t buf_len);
|
||||
|
||||
#ifdef PIN_WIRE0_SDA
|
||||
// Wire object associated to I2C0 interface.
|
||||
TwoWire Wire(PIN_WIRE0_SDA, PIN_WIRE0_SCL);
|
||||
#endif
|
||||
|
||||
TwoWire::TwoWire(int8_t sda, int8_t scl) {
|
||||
_sda = sda;
|
||||
_scl = scl;
|
||||
}
|
||||
|
||||
TwoWire::~TwoWire() {}
|
||||
|
||||
bool TwoWire::setPins(int8_t sda, int8_t scl) {
|
||||
// return true when changing pins on initialized I2C
|
||||
if (_inSetPins)
|
||||
return true;
|
||||
// check if pins are provided
|
||||
if (sda == -1 || scl == -1)
|
||||
return false;
|
||||
// set private pins
|
||||
_sda = sda;
|
||||
_scl = scl;
|
||||
uint32_t pin_sda = pinInfo(sda)->gpio;
|
||||
uint32_t pin_scl = pinInfo(scl)->gpio;
|
||||
|
||||
hal_gpio_pin_afio_select(GPIO_GET_BASE(pin_sda), GPIO_GET_PIN(pin_sda), I2C0_SDA); // TODO: check pin value
|
||||
hal_gpio_pin_afio_select(GPIO_GET_BASE(pin_scl), GPIO_GET_PIN(pin_scl), I2C0_SCL);
|
||||
hal_gpio_pin_afio_en(GPIO_GET_BASE(pin_sda), GPIO_GET_PIN(pin_sda), HAL_ENABLE);
|
||||
hal_gpio_pin_afio_en(GPIO_GET_BASE(pin_scl), GPIO_GET_PIN(pin_scl), HAL_ENABLE);
|
||||
|
||||
// restart I2C if changing pins
|
||||
// this will never be called from begin()
|
||||
if (_i2c) {
|
||||
_inSetPins = true;
|
||||
end();
|
||||
begin();
|
||||
_inSetPins = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::begin(int8_t sda, int8_t scl, uint32_t frequency) {
|
||||
if (_i2c)
|
||||
return true;
|
||||
// set private i2c pins
|
||||
if (!setPins(sda, scl))
|
||||
return false;
|
||||
// use default frequency
|
||||
if (!frequency)
|
||||
frequency = WIRE_DEFAULT_FREQ;
|
||||
|
||||
/* disable the i2c */
|
||||
hal_i2c_en(I2C_BASE, HAL_DISABLE);
|
||||
|
||||
_freq = frequency;
|
||||
_i2c = new i2c_init_t_def;
|
||||
memset(&_i2c, 0, sizeof(_i2c));
|
||||
_i2c->i2c_peripheral_clock_freq = 4;
|
||||
_i2c->i2c_master_mode_sel = I2C_FM_MODE;
|
||||
_i2c->i2c_fm_mode_duty_cycle = I2C_FM_MODE_DUTY_CYCLE_2;
|
||||
/*
|
||||
* TPCLK1 = 1/80MHz = 0.0125us
|
||||
* Thigh = 9 x CCR x TPCLK1
|
||||
* Tlow = 16 x CCR x TPCLK1
|
||||
* Thigh + Tlow = 1/frequency
|
||||
* ccr = 3.200.000/frequency
|
||||
*/
|
||||
_i2c->i2c_ccr = 3200000 / frequency;
|
||||
_i2c->i2c_trise = 0xF;
|
||||
|
||||
hal_i2c_init(I2C_BASE, _i2c);
|
||||
|
||||
hal_i2c_en(I2C_BASE, HAL_ENABLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency) {
|
||||
if (_i2c)
|
||||
return true;
|
||||
// init master bus first, return if failed
|
||||
if (!begin(sda, scl, frequency))
|
||||
return false;
|
||||
|
||||
hal_i2c_slave_set_add_mode(I2C_BASE, I2C_ADD_7BIT_MODE);
|
||||
hal_i2c_slave_set_add1(I2C_BASE, address);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::end() {
|
||||
hal_i2c_deinit();
|
||||
delete _i2c;
|
||||
_i2c = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::setClock(uint32_t freq) {
|
||||
if (_i2c) {
|
||||
_i2c->i2c_ccr = 3200000 / freq;
|
||||
hal_i2c_init(I2C_BASE, _i2c);
|
||||
}
|
||||
_freq = freq;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint8_t address) {
|
||||
_txAddr = address;
|
||||
_txBuf.clear();
|
||||
}
|
||||
|
||||
// Errors:
|
||||
// 0 : Success
|
||||
// 1 : Data too long
|
||||
// 2 : NACK on transmit of address
|
||||
// 3 : NACK on transmit of data
|
||||
// 4 : Other error
|
||||
uint8_t TwoWire::endTransmission(bool stopBit) {
|
||||
if (!_i2c || !_txAddr)
|
||||
return 4;
|
||||
uint8_t *buf = (uint8_t *)malloc(_txBuf.available());
|
||||
uint8_t i = 0;
|
||||
while (_txBuf.available()) {
|
||||
buf[i++] = _txBuf.read_char();
|
||||
}
|
||||
if (hal_i2c_master_7bit_write(I2C_BASE, _txAddr, buf, i) == HAL_RESET)
|
||||
return 4;
|
||||
free(buf);
|
||||
_txAddr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t TwoWire::requestFrom(uint8_t address, size_t len, bool stopBit) {
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (len > SERIAL_BUFFER_SIZE)
|
||||
len = SERIAL_BUFFER_SIZE;
|
||||
|
||||
_rxBuf.clear();
|
||||
|
||||
uint8_t *buf = (uint8_t *)malloc(_txBuf.available());
|
||||
if (hal_i2c_master_7bit_read(I2C_BASE, address, buf, len) == HAL_RESET)
|
||||
return 0;
|
||||
|
||||
uint8_t i = 0;
|
||||
while (len) {
|
||||
_rxBuf.store_char(buf[i++]);
|
||||
len--;
|
||||
}
|
||||
free(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(uint8_t data) {
|
||||
if (!_txAddr || _txBuf.isFull())
|
||||
return 0;
|
||||
_txBuf.store_char(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(const uint8_t *data, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (!write(data[i]))
|
||||
return i;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int TwoWire::available() {
|
||||
return _rxBuf.available();
|
||||
}
|
||||
|
||||
int TwoWire::read() {
|
||||
return _rxBuf.read_char();
|
||||
}
|
||||
|
||||
int TwoWire::peek() {
|
||||
return _rxBuf.peek();
|
||||
}
|
||||
|
||||
void TwoWire::flush() {}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
#define TIMEOUT_CYCLE 4000
|
||||
|
||||
static uint8_t hal_i2c_master_7bit_write(uint32_t i2c_x_base, uint8_t dev_addr, const uint8_t *buf, uint16_t buf_len) {
|
||||
// 1. check busy
|
||||
if (hal_i2c_wait_bus_idle(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET) {
|
||||
hal_i2c_master_reset(i2c_x_base);
|
||||
return HAL_RESET;
|
||||
}
|
||||
|
||||
// 2. send start
|
||||
if (hal_i2c_master_start(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET)
|
||||
return HAL_RESET;
|
||||
|
||||
// 3. send addr
|
||||
hal_i2c_master_send_data(i2c_x_base, dev_addr);
|
||||
|
||||
// 4. wait send complete
|
||||
if (hal_i2c_master_wait_addr(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET)
|
||||
return HAL_RESET;
|
||||
|
||||
// 5. clear addr flag
|
||||
hal_i2c_clear_sr(i2c_x_base);
|
||||
|
||||
// 6. send data
|
||||
for (uint32_t i = 0; i < buf_len; i++) {
|
||||
// wait tx empty flag
|
||||
if (hal_i2c_wait_txe(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET) {
|
||||
return HAL_RESET;
|
||||
} else {
|
||||
hal_i2c_master_send_data(i2c_x_base, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 7. wait send complete.
|
||||
if (hal_i2c_wait_btf(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET)
|
||||
return HAL_RESET;
|
||||
|
||||
// 8. stop the i2c.
|
||||
hal_i2c_master_stop(i2c_x_base);
|
||||
|
||||
return HAL_SET;
|
||||
}
|
||||
|
||||
static uint8_t hal_i2c_master_7bit_read(uint32_t i2c_x_base, uint8_t dev_addr, uint8_t *buf, uint16_t buf_len) {
|
||||
// 1. check busy
|
||||
if (hal_i2c_wait_bus_idle(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET) {
|
||||
hal_i2c_master_reset(i2c_x_base);
|
||||
return HAL_RESET;
|
||||
}
|
||||
|
||||
// 2. send start
|
||||
if (hal_i2c_master_start(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET)
|
||||
return HAL_RESET;
|
||||
|
||||
// 3. send addr (+1 is read operation)
|
||||
hal_i2c_master_send_data(i2c_x_base, dev_addr + 1);
|
||||
|
||||
// 4. Wait for an ack after sending the address
|
||||
if (hal_i2c_master_wait_addr(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET)
|
||||
return HAL_RESET;
|
||||
|
||||
// 5. clear addr flag
|
||||
hal_i2c_clear_sr(i2c_x_base);
|
||||
|
||||
// 6. clear the DR
|
||||
hal_i2c_master_recv_data(i2c_x_base);
|
||||
|
||||
// 7. receive data
|
||||
for (int i = buf_len; i > 0; i--) {
|
||||
// when reading the last byte,do not send the ack
|
||||
if (buf_len == 1) {
|
||||
// do not send the ack
|
||||
hal_i2c_ack_en(i2c_x_base, HAL_DISABLE);
|
||||
|
||||
/// wait rx not empty
|
||||
if (hal_i2c_wait_rxne(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET) {
|
||||
return HAL_RESET;
|
||||
} else {
|
||||
*buf = hal_i2c_master_recv_data(i2c_x_base);
|
||||
}
|
||||
// read data
|
||||
} else {
|
||||
// send ack
|
||||
hal_i2c_ack_en(i2c_x_base, HAL_ENABLE);
|
||||
|
||||
// wait rx not empty
|
||||
if (hal_i2c_wait_rxne(i2c_x_base, TIMEOUT_CYCLE) == HAL_RESET) {
|
||||
return HAL_RESET;
|
||||
} else {
|
||||
*buf = hal_i2c_master_recv_data(i2c_x_base);
|
||||
}
|
||||
}
|
||||
buf_len--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
// 8. stop the i2c.
|
||||
hal_i2c_master_stop(i2c_x_base);
|
||||
|
||||
return HAL_SET;
|
||||
}
|
||||
66
cores/lightning-ln882h/arduino/libraries/Wire/Wire.h
Normal file
66
cores/lightning-ln882h/arduino/libraries/Wire/Wire.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2025-01-19. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HardwareI2C.h>
|
||||
#include <api/RingBuffer.h>
|
||||
|
||||
#define Wire1 Wire
|
||||
|
||||
#define WIRE_HAS_END 1
|
||||
#define WIRE_DEFAULT_FREQ 100000
|
||||
|
||||
#ifndef I2C_PRIV
|
||||
#define I2C_PRIV void
|
||||
#endif
|
||||
|
||||
using arduino::RingBuffer;
|
||||
|
||||
class TwoWire : public HardwareI2C {
|
||||
private:
|
||||
I2C_PRIV *_i2c = NULL;
|
||||
|
||||
RingBuffer _rxBuf;
|
||||
RingBuffer _txBuf;
|
||||
uint8_t _txAddr = 0;
|
||||
bool _inSetPins = false;
|
||||
|
||||
public:
|
||||
TwoWire();
|
||||
TwoWire(int8_t sda, int8_t scl);
|
||||
~TwoWire();
|
||||
|
||||
bool setPins(int8_t sda, int8_t scl);
|
||||
|
||||
bool begin(int8_t sda, int8_t scl, uint32_t frequency = 0);
|
||||
bool begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency = 0);
|
||||
bool end();
|
||||
|
||||
bool setClock(uint32_t freq);
|
||||
|
||||
void beginTransmission(uint8_t address);
|
||||
uint8_t endTransmission(bool stopBit);
|
||||
|
||||
size_t requestFrom(uint8_t address, size_t len, bool stopBit);
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
int available();
|
||||
int read();
|
||||
int peek();
|
||||
void flush();
|
||||
|
||||
using HardwareI2C::begin;
|
||||
using HardwareI2C::endTransmission;
|
||||
using HardwareI2C::requestFrom;
|
||||
using HardwareI2C::write;
|
||||
using Print::write;
|
||||
};
|
||||
|
||||
#ifdef PIN_WIRE0_SDA
|
||||
extern TwoWire Wire;
|
||||
#endif
|
||||
#ifdef PIN_WIRE1_SDA
|
||||
extern TwoWire Wire1;
|
||||
#endif
|
||||
27
cores/lightning-ln882h/arduino/src/ArduinoFamily.h
Normal file
27
cores/lightning-ln882h/arduino/src/ArduinoFamily.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// Provide GPIO names to variant.cpp files
|
||||
#define LT_VARIANT_INCLUDE "sdk_private.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
extern void vPortClearInterruptMask(uint32_t ulNewMaskValue);
|
||||
extern uint32_t ulPortSetInterruptMask(void);
|
||||
|
||||
// TODO
|
||||
// #define clockCyclesPerMicrosecond() (SystemCoreClock / 1000000L)
|
||||
// #define clockCyclesToMicroseconds(a) (a * 1000L / (SystemCoreClock / 1000L))
|
||||
// #define microsecondsToClockCycles(a) (a * (SystemCoreClock / 1000000L))
|
||||
|
||||
#define interrupts() vPortClearInterruptMask(0)
|
||||
#define noInterrupts() ulPortSetInterruptMask()
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
8
cores/lightning-ln882h/arduino/src/lt_defs.h
Normal file
8
cores/lightning-ln882h/arduino/src/lt_defs.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#error "Don't include this file directly"
|
||||
|
||||
#define LT_ARD_HAS_WIFI 1
|
||||
#define LT_ARD_HAS_SERIAL 1
|
||||
#define LT_ARD_HAS_WIRE 1
|
||||
#define LT_ARD_MD5_MBEDTLS 1
|
||||
35
cores/lightning-ln882h/arduino/src/main.cpp
Normal file
35
cores/lightning-ln882h/arduino/src/main.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-17. */
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#define MAIN_TASK_STACK_SIZE 8192
|
||||
|
||||
static OS_Thread_t g_mainTask_thread;
|
||||
|
||||
bool startMainTask() {
|
||||
OS_Status ret = OS_ThreadCreate(
|
||||
&g_mainTask_thread,
|
||||
"main",
|
||||
(OS_ThreadEntry_t)mainTask,
|
||||
NULL,
|
||||
OS_PRIORITY_BELOW_NORMAL,
|
||||
MAIN_TASK_STACK_SIZE
|
||||
);
|
||||
|
||||
if (ret != OS_OK)
|
||||
return false;
|
||||
OS_ThreadStartScheduler();
|
||||
return true;
|
||||
}
|
||||
|
||||
void wait_for_debug() {
|
||||
while (((CoreDebug->DHCSR) & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0) {
|
||||
asm("nop");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
66
cores/lightning-ln882h/arduino/src/wiring.c
Normal file
66
cores/lightning-ln882h/arduino/src/wiring.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-17. */
|
||||
|
||||
#include "wiring_private.h"
|
||||
|
||||
#ifndef portNVIC_SYSTICK_CURRENT_VALUE_REG
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG (*((volatile uint32_t *)0xe000e018))
|
||||
#endif
|
||||
|
||||
void delayMicroseconds(unsigned int us) {
|
||||
int i;
|
||||
uint32_t t0, tn;
|
||||
int dfactor = 20 * us - 10 + (81 * us / 100);
|
||||
|
||||
if (us > 100) {
|
||||
t0 = micros();
|
||||
do {
|
||||
tn = micros();
|
||||
} while (tn >= t0 && tn < (t0 + us - 1));
|
||||
} else {
|
||||
for (i = 0; i < dfactor; i++) {
|
||||
asm("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long millis(void) {
|
||||
return (__get_IPSR() == 0) ? xTaskGetTickCount() : xTaskGetTickCountFromISR();
|
||||
}
|
||||
|
||||
unsigned long micros(void) {
|
||||
uint32_t tick1, tick2;
|
||||
uint32_t us;
|
||||
uint32_t tick_per_us = F_CPU / 1000;
|
||||
|
||||
if (__get_IPSR() == 0) {
|
||||
tick1 = xTaskGetTickCount();
|
||||
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
tick2 = xTaskGetTickCount();
|
||||
} else {
|
||||
tick1 = xTaskGetTickCountFromISR();
|
||||
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
tick2 = xTaskGetTickCountFromISR();
|
||||
}
|
||||
|
||||
if (tick1 == tick2) {
|
||||
return tick1 * 1000 - us * 1000 / tick_per_us;
|
||||
} else if ((us * 1000 / tick_per_us) < 500) {
|
||||
return tick1 * 1000 - us * 1000 / tick_per_us;
|
||||
} else {
|
||||
return tick1 * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
void pinRemoveMode(PinInfo *pin, uint32_t mask) {
|
||||
PinData *data = pinData(pin);
|
||||
if ((mask & PIN_GPIO) && (pin->enabled & PIN_GPIO)) {
|
||||
hal_gpio_pin_direction_set(data->gpio_base, data->gpio->pin, GPIO_INPUT);
|
||||
free(data->gpio);
|
||||
pinDisable(pin, PIN_GPIO);
|
||||
}
|
||||
if ((mask & PIN_IRQ) && (pin->enabled & PIN_IRQ)) {
|
||||
data->irqHandler = NULL;
|
||||
hal_gpio_pin_it_en(data->gpio_base, data->gpio->pin, HAL_DISABLE);
|
||||
pinDisable(pin, PIN_IRQ);
|
||||
}
|
||||
}
|
||||
80
cores/lightning-ln882h/arduino/src/wiring_analog.c
Normal file
80
cores/lightning-ln882h/arduino/src/wiring_analog.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2025-01-19. */
|
||||
|
||||
#include "wiring_private.h"
|
||||
|
||||
#ifndef PIN_ADC1
|
||||
#define PIN_ADC1 -1
|
||||
#endif
|
||||
#ifndef PIN_ADC2
|
||||
#define PIN_ADC2 -1
|
||||
#endif
|
||||
#ifndef PIN_ADC3
|
||||
#define PIN_ADC3 -1
|
||||
#endif
|
||||
#ifndef PIN_ADC4
|
||||
#define PIN_ADC4 -1
|
||||
#endif
|
||||
#ifndef PIN_ADC5
|
||||
#define PIN_ADC5 -1
|
||||
#endif
|
||||
#ifndef PIN_ADC6
|
||||
#define PIN_ADC6 -1
|
||||
#endif
|
||||
#ifndef PIN_ADC7
|
||||
#define PIN_ADC7 -1
|
||||
#endif
|
||||
|
||||
const uint32_t adc_channels[] = {
|
||||
-1,
|
||||
PIN_ADC1,
|
||||
PIN_ADC2,
|
||||
PIN_ADC3,
|
||||
PIN_ADC4,
|
||||
PIN_ADC5,
|
||||
PIN_ADC6,
|
||||
PIN_ADC7,
|
||||
};
|
||||
|
||||
static adc_ch_t pinToAdcCh(uint32_t gpio) {
|
||||
for (uint8_t i = 0; i < ADC_CH_NUM; i++) {
|
||||
if (adc_channels[i] == gpio)
|
||||
return (adc_ch_t)(1 << i);
|
||||
}
|
||||
return ADC_CH0;
|
||||
}
|
||||
|
||||
// WARN: adc values are quite bad (zero value of ~ 1000lsb and full scale value ~ 3450lsb)
|
||||
uint16_t analogReadVoltage(pin_size_t pinNumber) {
|
||||
uint16_t ret = 0;
|
||||
pinCheckGetInfo(pinNumber, PIN_ADC, 0);
|
||||
|
||||
hal_gpio_pin_mode_set(GPIO_GET_BASE(pin->gpio), pin->gpio, GPIO_MODE_ANALOG);
|
||||
|
||||
adc_ch_t ch = pinToAdcCh(pin->gpio);
|
||||
adc_init_t_def adc_init;
|
||||
|
||||
memset(&adc_init, 0, sizeof(adc_init_t_def));
|
||||
adc_init.adc_ch = ch;
|
||||
adc_init.adc_conv_mode = ADC_CONV_MODE_CONTINUE;
|
||||
adc_init.adc_presc = 80;
|
||||
adc_init.adc_ov_smp_ratio = ADC_OVER_SAMPLING_RATIO_X8;
|
||||
adc_init.adc_ov_smp_ratio_en = ADC_OVER_SAMPLING_EN_STATUS_BIT0;
|
||||
hal_adc_init(ADC_BASE, &adc_init);
|
||||
|
||||
hal_adc_en(ADC_BASE, HAL_ENABLE);
|
||||
|
||||
hal_adc_start_conv(ADC_BASE);
|
||||
|
||||
while (hal_adc_get_conv_status(ADC_BASE, ch) == 0)
|
||||
;
|
||||
|
||||
ret = hal_adc_get_data(ADC_BASE, ch);
|
||||
|
||||
hal_adc_clr_conv_status(ADC_BASE, ch);
|
||||
|
||||
return (uint16_t)(3300UL * ret / 4095);
|
||||
}
|
||||
|
||||
uint16_t analogReadMaxVoltage(pin_size_t pinNumber) {
|
||||
return 3300;
|
||||
}
|
||||
27
cores/lightning-ln882h/arduino/src/wiring_data.h
Normal file
27
cores/lightning-ln882h/arduino/src/wiring_data.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-17. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct PinData_s {
|
||||
gpio_init_t_def *gpio;
|
||||
PinMode gpioMode;
|
||||
uint32_t gpio_base;
|
||||
PinStatus irqMode;
|
||||
void *irqHandler;
|
||||
void *irqParam;
|
||||
};
|
||||
|
||||
#define GPIO_GET_PORT(pin) (pin >> 4)
|
||||
#define GPIO_GET_PIN(pin) ((gpio_pin_t)(1 << (pin & 0xF)))
|
||||
#define GPIO_GET_BASE(pin) (GPIO_GET_PORT(pin) == 1 ? GPIOB_BASE : GPIOA_BASE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
67
cores/lightning-ln882h/arduino/src/wiring_digital.c
Normal file
67
cores/lightning-ln882h/arduino/src/wiring_digital.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-17. */
|
||||
|
||||
#include "wiring_private.h"
|
||||
|
||||
void pinMode(pin_size_t pinNumber, PinMode pinMode) {
|
||||
pinCheckGetData(pinNumber, PIN_GPIO, );
|
||||
|
||||
if (pinEnabled(pin, PIN_GPIO) && data->gpioMode == pinMode)
|
||||
return;
|
||||
|
||||
// GPIO can't be used together with PWM
|
||||
pinRemoveMode(pin, PIN_PWM);
|
||||
|
||||
gpio_init_t_def *gpio = data->gpio;
|
||||
if (!gpio) {
|
||||
// allocate memory if pin not used before
|
||||
data->gpio = gpio = malloc(sizeof(gpio_init_t_def));
|
||||
pinEnable(pin, PIN_GPIO);
|
||||
}
|
||||
|
||||
gpio->pin = GPIO_GET_PIN(pinNumber);
|
||||
gpio->speed = GPIO_NORMAL_SPEED;
|
||||
data->gpio_base = GPIO_GET_BASE(pinNumber);
|
||||
data->gpioMode = pinMode;
|
||||
|
||||
switch (pinMode) {
|
||||
case INPUT:
|
||||
gpio->dir = GPIO_INPUT;
|
||||
gpio->pull = GPIO_PULL_NONE;
|
||||
break;
|
||||
case INPUT_PULLDOWN:
|
||||
gpio->dir = GPIO_INPUT;
|
||||
gpio->pull = GPIO_PULL_DOWN;
|
||||
break;
|
||||
case INPUT_PULLUP:
|
||||
gpio->dir = GPIO_INPUT;
|
||||
gpio->pull = GPIO_PULL_UP;
|
||||
break;
|
||||
case OUTPUT:
|
||||
gpio->dir = GPIO_OUTPUT;
|
||||
gpio->pull = GPIO_PULL_NONE;
|
||||
break;
|
||||
case OUTPUT_OPENDRAIN:
|
||||
gpio->dir = GPIO_INPUT;
|
||||
gpio->pull = GPIO_PULL_NONE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
hal_gpio_init(data->gpio_base, gpio);
|
||||
}
|
||||
|
||||
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
|
||||
pinCheckGetData(pinNumber, PIN_GPIO, );
|
||||
pinSetOutputPull(pin, data, pinNumber, status);
|
||||
if (status)
|
||||
hal_gpio_pin_set(data->gpio_base, data->gpio->pin);
|
||||
else
|
||||
hal_gpio_pin_reset(data->gpio_base, data->gpio->pin);
|
||||
}
|
||||
|
||||
PinStatus digitalRead(pin_size_t pinNumber) {
|
||||
pinCheckGetData(pinNumber, PIN_GPIO, LOW);
|
||||
pinSetInputMode(pin, data, pinNumber);
|
||||
return hal_gpio_pin_input_read(data->gpio_base, data->gpio->pin);
|
||||
}
|
||||
91
cores/lightning-ln882h/arduino/src/wiring_irq.c
Normal file
91
cores/lightning-ln882h/arduino/src/wiring_irq.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-04. */
|
||||
|
||||
#include "wiring_private.h"
|
||||
|
||||
void GPIOA_IRQHandler() {
|
||||
for (pin_size_t pinNumber = 0; pinNumber < 16; pinNumber++) {
|
||||
gpio_pin_t gpio = GPIO_GET_PIN(pinNumber);
|
||||
|
||||
if (hal_gpio_pin_get_it_flag(GPIOA_BASE, gpio) == HAL_SET) {
|
||||
hal_gpio_pin_clr_it_flag(GPIOA_BASE, gpio);
|
||||
|
||||
PinInfo *pin = pinInfo(pinNumber);
|
||||
if (!pin)
|
||||
continue;
|
||||
|
||||
PinData *data = pinData(pin);
|
||||
if (!data->irqHandler)
|
||||
continue;
|
||||
if (!data->irqParam)
|
||||
((voidFuncPtr)data->irqHandler)();
|
||||
else
|
||||
((voidFuncPtrParam)data->irqHandler)(data->irqParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPIOB_IRQHandler() {
|
||||
for (pin_size_t pinNumber = 16; pinNumber < 32; pinNumber++) {
|
||||
gpio_pin_t gpio = GPIO_GET_PIN(pinNumber);
|
||||
|
||||
if (hal_gpio_pin_get_it_flag(GPIOB_BASE, gpio) == HAL_SET) {
|
||||
hal_gpio_pin_clr_it_flag(GPIOB_BASE, gpio);
|
||||
|
||||
PinInfo *pin = pinInfo(pinNumber);
|
||||
if (!pin)
|
||||
continue;
|
||||
|
||||
PinData *data = pinData(pin);
|
||||
if (!data->irqHandler)
|
||||
continue;
|
||||
if (!data->irqParam)
|
||||
((voidFuncPtr)data->irqHandler)();
|
||||
else
|
||||
((voidFuncPtrParam)data->irqHandler)(data->irqParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void *param) {
|
||||
pinCheckGetData(interruptNumber, PIN_IRQ, );
|
||||
|
||||
data->irqHandler = callback;
|
||||
data->irqParam = param;
|
||||
|
||||
if (pinEnabled(pin, PIN_IRQ) && data->irqMode == mode)
|
||||
return;
|
||||
|
||||
// GPIO can't be used together with PWM
|
||||
pinRemoveMode(pin, PIN_PWM);
|
||||
|
||||
uint32_t event = 0;
|
||||
switch (mode) {
|
||||
case LOW:
|
||||
LT_W("LOW interrupts not supported, setting FALLING instead");
|
||||
case FALLING:
|
||||
event = GPIO_INT_FALLING;
|
||||
break;
|
||||
case HIGH:
|
||||
LT_W("HIGH interrupts not supported, setting RISING instead");
|
||||
case RISING:
|
||||
event = GPIO_INT_RISING;
|
||||
break;
|
||||
case CHANGE:
|
||||
event = GPIO_INT_RISING_FALLING;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
pinEnable(pin, PIN_IRQ);
|
||||
data->irqMode = mode;
|
||||
|
||||
hal_gpio_pin_it_cfg(data->gpio_base, data->gpio->pin, event);
|
||||
hal_gpio_pin_it_en(data->gpio_base, data->gpio->pin, HAL_ENABLE);
|
||||
}
|
||||
|
||||
void detachInterrupt(pin_size_t interruptNumber) {
|
||||
pinCheckGetData(interruptNumber, PIN_IRQ, );
|
||||
|
||||
hal_gpio_pin_it_en(data->gpio_base, data->gpio->pin, HAL_DISABLE);
|
||||
pinModeRemove(interruptNumber, PIN_IRQ);
|
||||
}
|
||||
52
cores/lightning-ln882h/base/PinNames.h
Normal file
52
cores/lightning-ln882h/base/PinNames.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _PINNAMES_H_
|
||||
#define _PINNAMES_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <hal/hal_gpio.h>
|
||||
|
||||
typedef enum {
|
||||
PORT_A = 0,
|
||||
PORT_B = 1,
|
||||
} ln_PinPort;
|
||||
|
||||
typedef enum {
|
||||
PA_0 = 0,
|
||||
PA_1,
|
||||
PA_2,
|
||||
PA_3,
|
||||
PA_4,
|
||||
PA_5,
|
||||
PA_6,
|
||||
PA_7,
|
||||
PA_8,
|
||||
PA_9,
|
||||
PA_10,
|
||||
PA_11,
|
||||
PA_12,
|
||||
PA_13,
|
||||
PA_14,
|
||||
PA_15,
|
||||
|
||||
PB_0,
|
||||
PB_1,
|
||||
PB_2,
|
||||
PB_3,
|
||||
PB_4,
|
||||
PB_5,
|
||||
PB_6,
|
||||
PB_7,
|
||||
PB_8,
|
||||
PB_9,
|
||||
|
||||
// Not connected
|
||||
NC = -1
|
||||
} ln_PinName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
8
cores/lightning-ln882h/base/api/lt_cpu.c
Normal file
8
cores/lightning-ln882h/base/api/lt_cpu.c
Normal file
@@ -0,0 +1,8 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-24. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
const char *lt_cpu_get_core_type() {
|
||||
return "ARM Cortex-M4F (ARMv7E-M)";
|
||||
}
|
||||
27
cores/lightning-ln882h/base/api/lt_device.c
Normal file
27
cores/lightning-ln882h/base/api/lt_device.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-03. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
void lt_get_device_mac(uint8_t *mac) {
|
||||
ln_fotp_get_mac_val(mac);
|
||||
}
|
||||
|
||||
void lt_reboot() {
|
||||
ln_chip_reboot();
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
lt_reboot_reason_t lt_get_reboot_reason() {
|
||||
chip_reboot_cause_t reason = ln_chip_get_reboot_cause();
|
||||
switch (reason) {
|
||||
case CHIP_REBOOT_POWER_ON:
|
||||
return REBOOT_REASON_POWER;
|
||||
case CHIP_REBOOT_SOFTWARE:
|
||||
return REBOOT_REASON_SOFTWARE;
|
||||
case CHIP_REBOOT_WATCHDOG:
|
||||
return REBOOT_REASON_WATCHDOG;
|
||||
default:
|
||||
return REBOOT_REASON_UNKNOWN;
|
||||
}
|
||||
}
|
||||
15
cores/lightning-ln882h/base/api/lt_flash.c
Normal file
15
cores/lightning-ln882h/base/api/lt_flash.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-03. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
uint32_t hal_flash_read_id(void);
|
||||
|
||||
lt_flash_id_t lt_flash_get_id() {
|
||||
lt_flash_id_t id;
|
||||
uint32_t fl_id = hal_flash_read_id();
|
||||
id.manufacturer_id = (uint8_t)(fl_id >> 16);
|
||||
id.chip_id = (uint8_t)(fl_id >> 8);
|
||||
id.chip_size_id = (uint8_t)(fl_id >> 0);
|
||||
return id;
|
||||
}
|
||||
58
cores/lightning-ln882h/base/api/lt_init.c
Normal file
58
cores/lightning-ln882h/base/api/lt_init.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-24. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
extern uint8_t uart_print_port;
|
||||
extern Serial_t m_LogSerial;
|
||||
|
||||
static void lt_init_log(void) {
|
||||
// default LT print port
|
||||
uart_print_port = LT_UART_DEFAULT_LOGGER;
|
||||
// default SDK print port
|
||||
serial_init(&m_LogSerial, LT_UART_DEFAULT_PORT, CFG_UART_BAUDRATE_LOG, NULL);
|
||||
}
|
||||
|
||||
void lt_init_family() {
|
||||
// 0. check reboot cause
|
||||
ln_chip_get_reboot_cause();
|
||||
|
||||
// 1. sys clock,interrupt
|
||||
SetSysClock();
|
||||
set_interrupt_priority();
|
||||
switch_global_interrupt(HAL_ENABLE);
|
||||
ln_runtime_measure_init();
|
||||
|
||||
// 2. register os heap mem
|
||||
OS_DefineHeapRegions();
|
||||
|
||||
// 3. log init
|
||||
lt_init_log();
|
||||
|
||||
cm_backtrace_init("LibreTiny - LN882H", "HW_V1.0", "SW_V1.0");
|
||||
|
||||
if (NVDS_ERR_OK != ln_nvds_init(FLASH_NVDS_OFFSET)) {
|
||||
LT_E("NVDS init failed!");
|
||||
}
|
||||
|
||||
if (KV_ERR_NONE != ln_kv_port_init(FLASH_KV_OFFSET, (FLASH_KV_OFFSET + FLASH_KV_LENGTH))) {
|
||||
LT_E("KV init failed!");
|
||||
}
|
||||
|
||||
// init system parameter
|
||||
sysparam_integrity_check_all();
|
||||
|
||||
ln_pm_sleep_mode_set(ACTIVE);
|
||||
// ln_pm_always_clk_disable_select(CLK_G_I2S | CLK_G_WS2811 | CLK_G_SDIO);
|
||||
/*ln_pm_always_clk_disable_select(CLK_G_I2S | CLK_G_WS2811 | CLK_G_SDIO | CLK_G_AES);
|
||||
ln_pm_lightsleep_clk_disable_select(CLK_G_GPIOA | CLK_G_GPIOB | CLK_G_SPI0 | CLK_G_SPI1 | CLK_G_I2C0 |
|
||||
CLK_G_UART1 | CLK_G_UART2 | CLK_G_WDT | CLK_G_TIM1 | CLK_G_TIM2 | CLK_G_MAC |
|
||||
CLK_G_DMA | CLK_G_RF | CLK_G_ADV_TIMER| CLK_G_TRNG);*/
|
||||
}
|
||||
|
||||
void lt_init_arduino() {
|
||||
#if LT_AUTO_DOWNLOAD_REBOOT && LT_ARD_HAS_SERIAL && LT_HW_UART0
|
||||
// initialize auto-download-reboot parser
|
||||
Serial0.begin(115200);
|
||||
#endif
|
||||
}
|
||||
8
cores/lightning-ln882h/base/api/lt_mem.c
Normal file
8
cores/lightning-ln882h/base/api/lt_mem.c
Normal file
@@ -0,0 +1,8 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-24. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
uint32_t lt_ram_get_size() {
|
||||
return 296 * 1024;
|
||||
}
|
||||
45
cores/lightning-ln882h/base/api/lt_ota.c
Normal file
45
cores/lightning-ln882h/base/api/lt_ota.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-12-21. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <ota_image.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
lt_ota_type_t lt_ota_get_type() {
|
||||
return OTA_TYPE_SINGLE;
|
||||
}
|
||||
|
||||
bool lt_ota_is_valid(uint8_t index) {
|
||||
image_hdr_t ota_header;
|
||||
|
||||
if (OTA_ERR_NONE != image_header_fast_read(FLASH_OTA_OFFSET, &ota_header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OTA_ERR_NONE != image_header_verify(&ota_header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OTA_ERR_NONE != image_body_verify(FLASH_OTA_OFFSET, &ota_header)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t lt_ota_dual_get_current() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t lt_ota_dual_get_stored() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lt_ota_set_write_protect(uf2_ota_t *uf2) {
|
||||
LT_DM(OTA, "lt_ota_set_write_protect");
|
||||
ln_nvds_set_ota_upg_state(UPG_STATE_DOWNLOAD_ING);
|
||||
}
|
||||
|
||||
bool lt_ota_switch(bool revert) {
|
||||
LT_DM(OTA, "lt_ota_switch(%d)", revert);
|
||||
ln_nvds_set_ota_upg_state(UPG_STATE_DOWNLOAD_OK);
|
||||
return true;
|
||||
}
|
||||
43
cores/lightning-ln882h/base/api/lt_wdt.c
Normal file
43
cores/lightning-ln882h/base/api/lt_wdt.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2025-01-19. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
bool lt_wdt_enable(uint32_t timeout) {
|
||||
|
||||
wdt_top_value_t wdt_top_value = 0;
|
||||
for (uint8_t i = 0; i < 15; i++) {
|
||||
if ((0x100UL << i) < (timeout * 32768 / 1000))
|
||||
wdt_top_value = i;
|
||||
}
|
||||
|
||||
wdt_init_t_def wdt_init;
|
||||
memset(&wdt_init, 0, sizeof(wdt_init));
|
||||
wdt_init.wdt_rmod = WDT_RMOD_1;
|
||||
wdt_init.wdt_rpl = WDT_RPL_32_PCLK;
|
||||
wdt_init.top = wdt_top_value;
|
||||
|
||||
hal_wdt_init(WDT_BASE, &wdt_init);
|
||||
|
||||
/* Configure Interrupt */
|
||||
NVIC_SetPriority(WDT_IRQn, 4);
|
||||
NVIC_EnableIRQ(WDT_IRQn);
|
||||
|
||||
/* Watchdog enable */
|
||||
/* Note : Watchdog cannot be disabled */
|
||||
hal_wdt_en(WDT_BASE, HAL_ENABLE);
|
||||
|
||||
/* Start feeding */
|
||||
hal_wdt_cnt_restart(WDT_BASE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lt_wdt_disable() {
|
||||
hal_wdt_deinit();
|
||||
hal_wdt_en(WDT_BASE, HAL_DISABLE);
|
||||
}
|
||||
|
||||
void lt_wdt_feed() {
|
||||
hal_wdt_cnt_restart(WDT_BASE);
|
||||
}
|
||||
31
cores/lightning-ln882h/base/config/lwipopts.h
Normal file
31
cores/lightning-ln882h/base/config/lwipopts.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-03-10. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include_next "lwipopts.h"
|
||||
|
||||
#if (!defined(LWIP_IPV4) || LWIP_IPV4) && !LWIP_IPV6
|
||||
#define ip_addr ip4_addr // LwIP 2.0.x compatibility
|
||||
#define ip_addr_t ip4_addr_t // LwIP 2.0.x compatibility
|
||||
#endif
|
||||
#if !LWIP_IPV4 && LWIP_IPV6
|
||||
#define ip_addr ip6_addr // LwIP 2.0.x compatibility
|
||||
#define ip_addr_t ip6_addr_t // LwIP 2.0.x compatibility
|
||||
#endif
|
||||
#define in_addr_t u32_t
|
||||
#define IN_ADDR_T_DEFINED 1
|
||||
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 2147483647 // for RECV_BUFSIZE_DEFAULT
|
||||
#endif
|
||||
|
||||
#define LWIP_NUM_NETIF_CLIENT_DATA 1
|
||||
#define LWIP_NETIF_EXT_STATUS_CALLBACK 1
|
||||
#undef MEMP_NUM_UDP_PCB
|
||||
#define MEMP_NUM_UDP_PCB 7
|
||||
|
||||
// LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define
|
||||
// LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)
|
||||
#define LWIP_COMPAT_MUTEX_ALLOWED 1
|
||||
|
||||
#define LWIP_TCPIP_TIMEOUT 1
|
||||
82
cores/lightning-ln882h/base/config/proj_config.h
Normal file
82
cores/lightning-ln882h/base/config/proj_config.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef _PROJ_CONFIG_H_
|
||||
#define _PROJ_CONFIG_H_
|
||||
|
||||
#define DISABLE (0)
|
||||
#define ENABLE (1)
|
||||
|
||||
#define __CONFIG_OS_KERNEL RTOS_FREERTOS
|
||||
|
||||
/*
|
||||
* Clock settings section
|
||||
* Note:
|
||||
*
|
||||
*/
|
||||
#define XTAL_CLOCK (40000000)
|
||||
#define RCO_CLOCK (32000)
|
||||
#define PLL_CLOCK (160000000)
|
||||
|
||||
// TODO: SystemCoreClock
|
||||
#define SYSTEM_CLOCK (160000000)
|
||||
|
||||
/*
|
||||
* Module enable/disable control
|
||||
*/
|
||||
#define FLASH_XIP ENABLE
|
||||
#define LN_ASSERT_EN ENABLE
|
||||
#define HAL_ASSERT_EN ENABLE
|
||||
#define PRINTF_OMIT DISABLE // when release software, set 1 to omit all printf logs
|
||||
#define OS_TICK_COMPENSATE
|
||||
|
||||
// Check big and endian mode
|
||||
#if defined(__CC_ARM)
|
||||
#if defined(__BIG_ENDIAN)
|
||||
#error "Please set the compiler to little-endian mode"
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#if (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
|
||||
#error "Please set the compiler to little-endian mode"
|
||||
#endif // __BYTE_ORDER__
|
||||
#else
|
||||
#error "Unsupported compiler"
|
||||
#endif
|
||||
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
/*
|
||||
* flash image settings
|
||||
*/
|
||||
#define FLASH_IMAGE_VER_MAJOR 0
|
||||
#define FLASH_IMAGE_VER_MINOR 1
|
||||
#define SOC_CRP_FLAG 0
|
||||
|
||||
/*
|
||||
* Hardware config
|
||||
*/
|
||||
#define CFG_UART0_TX_BUF_SIZE 256
|
||||
#define CFG_UART0_RX_BUF_SIZE 256
|
||||
#define CFG_UART1_TX_BUF_SIZE 128
|
||||
#define CFG_UART1_RX_BUF_SIZE 256
|
||||
#define CFG_UART2_TX_BUF_SIZE 128
|
||||
#define CFG_UART2_RX_BUF_SIZE 256
|
||||
|
||||
#define CFG_UART_BAUDRATE_LOG 115200
|
||||
#define CFG_UART_BAUDRATE_CONSOLE 115200
|
||||
|
||||
/*
|
||||
* FreeRTOS config
|
||||
*/
|
||||
|
||||
#define configTOTAL_HEAP_SIZE ((size_t)(160 * 1024))
|
||||
|
||||
/*
|
||||
* log
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
#define hexdump ln_hexdump
|
||||
#endif // __cplusplus
|
||||
|
||||
#define mbedtls_platform_set_calloc_free(calloc, free)
|
||||
|
||||
#endif /* _PROJ_CONFIG_H_ */
|
||||
2
cores/lightning-ln882h/base/fixups/.clang-format
Normal file
2
cores/lightning-ln882h/base/fixups/.clang-format
Normal file
@@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: Never
|
||||
4
cores/lightning-ln882h/base/fixups/os_queue.h
Normal file
4
cores/lightning-ln882h/base/fixups/os_queue.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
518
cores/lightning-ln882h/base/fixups/serial_hw.c
Normal file
518
cores/lightning-ln882h/base/fixups/serial_hw.c
Normal file
@@ -0,0 +1,518 @@
|
||||
#include "proj_config.h"
|
||||
#include "hal/hal_uart.h"
|
||||
#include "serial/ln_serial.h"
|
||||
#include "serial_hw.h"
|
||||
#include "utils/debug/ln_assert.h"
|
||||
#include "hal/hal_gpio.h"
|
||||
#include "hal/hal_misc.h"
|
||||
|
||||
#include "reg_sysc_cmp.h"//gpio fullmux
|
||||
|
||||
#define UART0_TX_BUF_SIZE CFG_UART0_TX_BUF_SIZE
|
||||
#define UART0_RX_BUF_SIZE CFG_UART0_RX_BUF_SIZE
|
||||
#define UART1_TX_BUF_SIZE CFG_UART1_TX_BUF_SIZE
|
||||
#define UART1_RX_BUF_SIZE CFG_UART1_RX_BUF_SIZE
|
||||
#define UART2_TX_BUF_SIZE CFG_UART2_TX_BUF_SIZE
|
||||
#define UART2_RX_BUF_SIZE CFG_UART2_RX_BUF_SIZE
|
||||
|
||||
/* TX and RX fifo buffer */
|
||||
uint8_t uart0_txbuf[UART0_TX_BUF_SIZE];
|
||||
uint8_t uart0_rxbuf[UART0_RX_BUF_SIZE];
|
||||
uint8_t uart1_txbuf[UART1_TX_BUF_SIZE];
|
||||
uint8_t uart1_rxbuf[UART1_RX_BUF_SIZE];
|
||||
uint8_t uart2_txbuf[UART2_TX_BUF_SIZE];
|
||||
uint8_t uart2_rxbuf[UART2_RX_BUF_SIZE];
|
||||
|
||||
/* From the high-level serial driver */
|
||||
extern Serial_t serial_handles[SER_PORT_NUM];
|
||||
|
||||
/* UART device*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t uart_base;
|
||||
uart_init_t_def init_cfg;
|
||||
} uart_dev_t;
|
||||
|
||||
static uart_dev_t g_uart0;
|
||||
static uart_dev_t g_uart1;
|
||||
static uart_dev_t g_uart2;
|
||||
|
||||
/* serial */
|
||||
typedef struct
|
||||
{
|
||||
struct SerialHardware Hardware;
|
||||
struct Serial *serial;
|
||||
} ln_serial_t;
|
||||
ln_serial_t uart_serial[SER_PORT_NUM];
|
||||
|
||||
|
||||
static void uart_io_pin_request(struct Serial *serial)
|
||||
{
|
||||
if (serial->port_id == SER_PORT_UART0)
|
||||
{
|
||||
hal_gpio_pin_afio_select(GPIOA_BASE,GPIO_PIN_2,UART0_TX);
|
||||
hal_gpio_pin_afio_select(GPIOA_BASE,GPIO_PIN_3,UART0_RX);
|
||||
hal_gpio_pin_afio_en(GPIOA_BASE,GPIO_PIN_2,HAL_ENABLE);
|
||||
hal_gpio_pin_afio_en(GPIOA_BASE,GPIO_PIN_3,HAL_ENABLE);
|
||||
}
|
||||
else if (serial->port_id == SER_PORT_UART1)
|
||||
{
|
||||
hal_gpio_pin_afio_select(GPIOB_BASE,GPIO_PIN_8,UART1_RX);
|
||||
hal_gpio_pin_afio_select(GPIOB_BASE,GPIO_PIN_9,UART1_TX);
|
||||
hal_gpio_pin_afio_en(GPIOB_BASE,GPIO_PIN_8,HAL_ENABLE);
|
||||
hal_gpio_pin_afio_en(GPIOB_BASE,GPIO_PIN_9,HAL_ENABLE);
|
||||
}
|
||||
else if (serial->port_id == SER_PORT_UART2)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_io_pin_release(struct Serial *serial)
|
||||
{
|
||||
if (serial == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (serial->port_id == SER_PORT_UART0)
|
||||
{
|
||||
hal_gpio_pin_afio_en(GPIOA_BASE,GPIO_PIN_2,HAL_DISABLE);
|
||||
hal_gpio_pin_afio_en(GPIOA_BASE,GPIO_PIN_3,HAL_DISABLE);
|
||||
}
|
||||
else if (serial->port_id == SER_PORT_UART1)
|
||||
{
|
||||
hal_gpio_pin_afio_en(GPIOB_BASE,GPIO_PIN_8,HAL_DISABLE);
|
||||
hal_gpio_pin_afio_en(GPIOB_BASE,GPIO_PIN_9,HAL_DISABLE);
|
||||
}
|
||||
else if (serial->port_id == SER_PORT_UART2)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static void hw_uart0_init(struct SerialHardware *_hw, struct Serial *serial, uint32_t baudrate)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
|
||||
LN_ASSERT(_hw && serial);
|
||||
hw = (ln_serial_t *)_hw;
|
||||
hw->serial = serial;
|
||||
|
||||
g_uart0.uart_base = UART0_BASE;
|
||||
g_uart0.init_cfg.baudrate = baudrate;//115200 921600 2000000
|
||||
g_uart0.init_cfg.word_len = UART_WORD_LEN_8;
|
||||
g_uart0.init_cfg.parity = UART_PARITY_NONE;
|
||||
g_uart0.init_cfg.stop_bits = UART_STOP_BITS_1;
|
||||
g_uart0.init_cfg.over_sampl= UART_OVER_SAMPL_8;
|
||||
|
||||
hal_uart_init(g_uart0.uart_base, &g_uart0.init_cfg);
|
||||
|
||||
hal_uart_rx_mode_en(g_uart0.uart_base, HAL_ENABLE);
|
||||
hal_uart_tx_mode_en(g_uart0.uart_base, HAL_ENABLE);
|
||||
hal_uart_en(g_uart0.uart_base, HAL_ENABLE);
|
||||
|
||||
hal_uart_it_en(g_uart0.uart_base, USART_IT_RXNE);
|
||||
//uart_it_enable(g_uart0.uart_base, USART_IT_TXE);//uart_it_enable(g_uart0.uart_base, USART_IT_TXE);
|
||||
|
||||
NVIC_EnableIRQ(UART0_IRQn);
|
||||
|
||||
//request pin for uart
|
||||
uart_io_pin_request(hw->serial);
|
||||
}
|
||||
|
||||
static void hw_uart1_init(struct SerialHardware *_hw, struct Serial *serial, uint32_t baudrate)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
|
||||
LN_ASSERT(_hw && serial);
|
||||
hw = (ln_serial_t *)_hw;
|
||||
hw->serial = serial;
|
||||
|
||||
g_uart1.uart_base = UART1_BASE;
|
||||
g_uart1.init_cfg.baudrate = baudrate;//115200 921600 2000000
|
||||
g_uart1.init_cfg.word_len = UART_WORD_LEN_8;
|
||||
g_uart1.init_cfg.parity = UART_PARITY_NONE;
|
||||
g_uart1.init_cfg.stop_bits = UART_STOP_BITS_1;
|
||||
g_uart1.init_cfg.over_sampl= UART_OVER_SAMPL_8;
|
||||
|
||||
hal_uart_init(g_uart1.uart_base, &g_uart1.init_cfg);
|
||||
|
||||
hal_uart_rx_mode_en(g_uart1.uart_base, HAL_ENABLE);
|
||||
hal_uart_tx_mode_en(g_uart1.uart_base, HAL_ENABLE);
|
||||
hal_uart_en(g_uart1.uart_base, HAL_ENABLE);
|
||||
|
||||
hal_uart_it_en(g_uart1.uart_base, USART_IT_RXNE);
|
||||
//uart_it_enable(g_uart1.uart_base, USART_IT_TXE);
|
||||
NVIC_EnableIRQ(UART1_IRQn);
|
||||
|
||||
//request pin for uart
|
||||
uart_io_pin_request(hw->serial);
|
||||
}
|
||||
|
||||
static void hw_uart2_init(struct SerialHardware *_hw, struct Serial *serial, uint32_t baudrate)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
|
||||
LN_ASSERT(_hw && serial);
|
||||
hw = (ln_serial_t *)_hw;
|
||||
hw->serial = serial;
|
||||
|
||||
g_uart2.uart_base = UART2_BASE;
|
||||
g_uart2.init_cfg.baudrate = baudrate;//115200 921600 2000000
|
||||
g_uart2.init_cfg.word_len = UART_WORD_LEN_8;
|
||||
g_uart2.init_cfg.parity = UART_PARITY_NONE;
|
||||
g_uart2.init_cfg.stop_bits = UART_STOP_BITS_1;
|
||||
g_uart2.init_cfg.over_sampl= UART_OVER_SAMPL_8;
|
||||
|
||||
hal_uart_init(g_uart2.uart_base, &g_uart2.init_cfg);
|
||||
|
||||
hal_uart_rx_mode_en(g_uart2.uart_base, HAL_ENABLE);
|
||||
hal_uart_tx_mode_en(g_uart2.uart_base, HAL_ENABLE);
|
||||
hal_uart_en(g_uart2.uart_base, HAL_ENABLE);
|
||||
|
||||
hal_uart_it_en(g_uart2.uart_base, USART_IT_RXNE);
|
||||
//uart_it_enable(g_uart2.uart_base, USART_IT_TXE);
|
||||
NVIC_EnableIRQ(UART2_IRQn);
|
||||
|
||||
//request pin for uart
|
||||
uart_io_pin_request(hw->serial);
|
||||
}
|
||||
|
||||
static void hw_uart0_cleanup(struct SerialHardware *_hw)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
LN_ASSERT(_hw);
|
||||
|
||||
hal_misc_reset_uart0();
|
||||
NVIC_ClearPendingIRQ(UART0_IRQn);
|
||||
NVIC_DisableIRQ(UART0_IRQn);
|
||||
|
||||
hw = (ln_serial_t *)_hw;
|
||||
uart_io_pin_release(hw->serial);
|
||||
hw->serial = NULL; // must be reset to NULL
|
||||
}
|
||||
|
||||
static void hw_uart1_cleanup(struct SerialHardware *_hw)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
LN_ASSERT(_hw);
|
||||
|
||||
hal_misc_reset_uart1();
|
||||
NVIC_ClearPendingIRQ(UART1_IRQn);
|
||||
NVIC_DisableIRQ(UART1_IRQn);
|
||||
|
||||
hw = (ln_serial_t *)_hw;
|
||||
uart_io_pin_release(hw->serial);
|
||||
hw->serial = NULL; // must be reset to NULL
|
||||
}
|
||||
|
||||
static void hw_uart2_cleanup(struct SerialHardware *_hw)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
LN_ASSERT(_hw);
|
||||
|
||||
hal_misc_reset_uart2();
|
||||
NVIC_ClearPendingIRQ(UART2_IRQn);
|
||||
NVIC_DisableIRQ(UART2_IRQn);
|
||||
|
||||
hw = (ln_serial_t *)_hw;
|
||||
uart_io_pin_release(hw->serial);
|
||||
hw->serial = NULL; // must be reset to NULL
|
||||
}
|
||||
|
||||
static void hw_uart_tx_start_polling(struct SerialHardware * _hw)
|
||||
{
|
||||
uint8_t ch;
|
||||
ln_serial_t *hw = NULL;
|
||||
uart_dev_t * pdev;
|
||||
|
||||
LN_ASSERT(_hw);
|
||||
hw = (ln_serial_t *)_hw;
|
||||
while(!fifo_isempty(&hw->serial->txfifo))
|
||||
{
|
||||
ch = fifo_pop(&hw->serial->txfifo);
|
||||
pdev = (uart_dev_t *)hw->Hardware.hw_device;
|
||||
while (hal_uart_flag_get(pdev->uart_base, USART_FLAG_TXE) != HAL_SET) {};
|
||||
//while (uart_flag_get(pdev->uart_base, USART_FLAG_TX_FIFO_FULL) == HAL_SET) {};
|
||||
hal_uart_send_data(pdev->uart_base, ch);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void hw_uart_tx_start_isr(struct SerialHardware * _hw)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
LN_ASSERT(_hw);
|
||||
hw = (ln_serial_t *)_hw;
|
||||
|
||||
if (hw->Hardware.isSending){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!fifo_isempty(&hw->serial->txfifo))
|
||||
{
|
||||
hw->Hardware.isSending = LN_TRUE;
|
||||
/* Enable TX empty interrupts. */
|
||||
uart_it_enable(UART0_BASE, USART_IT_TXE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int8_t hw_uart_tx_is_sending(struct SerialHardware * _hw)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
|
||||
LN_ASSERT(_hw);
|
||||
hw = (ln_serial_t *)_hw;
|
||||
return hw->Hardware.isSending;
|
||||
}
|
||||
|
||||
static int8_t hw_uart_set_baudrate(struct SerialHardware * _hw, uint32_t baudrate)
|
||||
{
|
||||
ln_serial_t *hw = NULL;
|
||||
uart_dev_t * pdev;
|
||||
|
||||
LN_ASSERT(_hw);
|
||||
hw = (ln_serial_t *)_hw;
|
||||
|
||||
pdev = (uart_dev_t *)hw->Hardware.hw_device;
|
||||
|
||||
hal_uart_baudrate_set(pdev->uart_base, baudrate);
|
||||
return LN_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* High-level interface data structures.
|
||||
*/
|
||||
static const struct SerialHardwareVT uart0_vtable =
|
||||
{
|
||||
.init = hw_uart0_init,
|
||||
.cleanup = hw_uart0_cleanup,
|
||||
.txStart = hw_uart_tx_start_polling,//hw_uart_tx_start_polling,//hw_uart_tx_start_isr
|
||||
.txSending = hw_uart_tx_is_sending,
|
||||
.setBaudrate = hw_uart_set_baudrate,
|
||||
};
|
||||
|
||||
static const struct SerialHardwareVT uart1_vtable =
|
||||
{
|
||||
.init = hw_uart1_init,
|
||||
.cleanup = hw_uart1_cleanup,
|
||||
.txStart = hw_uart_tx_start_polling,//hw_uart_tx_start_isr
|
||||
.txSending = hw_uart_tx_is_sending,
|
||||
.setBaudrate = hw_uart_set_baudrate,
|
||||
};
|
||||
|
||||
static const struct SerialHardwareVT uart2_vtable =
|
||||
{
|
||||
.init = hw_uart2_init,
|
||||
.cleanup = hw_uart2_cleanup,
|
||||
.txStart = hw_uart_tx_start_polling,//hw_uart_tx_start_isr
|
||||
.txSending = hw_uart_tx_is_sending,
|
||||
.setBaudrate = hw_uart_set_baudrate,
|
||||
};
|
||||
|
||||
ln_serial_t uart_serial[SER_PORT_NUM] =
|
||||
{
|
||||
{
|
||||
.Hardware =
|
||||
{
|
||||
.table = &uart0_vtable,
|
||||
.txbuffer = uart0_txbuf,
|
||||
.rxbuffer = uart0_rxbuf,
|
||||
.txbuffer_size = sizeof(uart0_txbuf),
|
||||
.rxbuffer_size = sizeof(uart0_rxbuf),
|
||||
.hw_device = (void *)&g_uart0,
|
||||
.isSending = LN_FALSE,
|
||||
},
|
||||
.serial = NULL,
|
||||
},
|
||||
{
|
||||
.Hardware =
|
||||
{
|
||||
.table = &uart1_vtable,
|
||||
.txbuffer = uart1_txbuf,
|
||||
.rxbuffer = uart1_rxbuf,
|
||||
.txbuffer_size = sizeof(uart1_txbuf),
|
||||
.rxbuffer_size = sizeof(uart1_rxbuf),
|
||||
.hw_device = (void *)&g_uart1,
|
||||
.isSending = LN_FALSE,
|
||||
},
|
||||
.serial = NULL,
|
||||
},
|
||||
{
|
||||
.Hardware =
|
||||
{
|
||||
.table = &uart2_vtable,
|
||||
.txbuffer = uart2_txbuf,
|
||||
.rxbuffer = uart2_rxbuf,
|
||||
.txbuffer_size = sizeof(uart2_txbuf),
|
||||
.rxbuffer_size = sizeof(uart2_rxbuf),
|
||||
.hw_device = (void *)&g_uart2,
|
||||
.isSending = LN_FALSE,
|
||||
},
|
||||
.serial = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
struct SerialHardware *serial_hw_getdesc(serial_port_id_t port_id)
|
||||
{
|
||||
LN_ASSERT(port_id < SER_PORT_NUM);
|
||||
return (struct SerialHardware *)&uart_serial[port_id].Hardware;
|
||||
}
|
||||
|
||||
///=====================UART0/1/2 IQR Handle===============================///
|
||||
static inline void uart0_send_data_isr(void)
|
||||
{
|
||||
ln_serial_t *hw = (ln_serial_t *)&uart_serial[SER_PORT_UART0];
|
||||
uint8_t tx_char = 0;
|
||||
|
||||
if (fifo_isempty(&hw->serial->txfifo))
|
||||
{
|
||||
hal_uart_it_disable(UART0_BASE, USART_IT_TXE);
|
||||
hw->Hardware.isSending = LN_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_char = fifo_pop(&hw->serial->txfifo);
|
||||
hal_uart_send_data(UART0_BASE, tx_char);
|
||||
while (hal_uart_flag_get(UART0_BASE, USART_FLAG_TX_FIFO_FULL) == HAL_SET) {};
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart0_recv_data_isr(void)
|
||||
{
|
||||
uint8_t ch = 0;
|
||||
|
||||
ln_serial_t *hw = (ln_serial_t *)&uart_serial[SER_PORT_UART0];
|
||||
|
||||
while (fifo_isfull(&hw->serial->rxfifo)){
|
||||
serial_purge_rx(hw->serial);
|
||||
}
|
||||
|
||||
ch = hal_uart_recv_data(UART0_BASE);
|
||||
|
||||
fifo_push(&hw->serial->rxfifo, ch);
|
||||
hw->serial->rx_callback();
|
||||
}
|
||||
|
||||
static inline void serial_uart0_isr_callback(void)
|
||||
{
|
||||
if (hal_uart_it_en_status_get(UART0_BASE, USART_IT_RXNE) && \
|
||||
hal_uart_flag_get(UART0_BASE, USART_FLAG_RXNE)) {
|
||||
uart0_recv_data_isr();
|
||||
}
|
||||
|
||||
if (hal_uart_it_en_status_get(UART0_BASE, USART_IT_TXE) && \
|
||||
hal_uart_flag_get(UART0_BASE, USART_FLAG_TXE)) {
|
||||
uart0_send_data_isr();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart1_send_data_isr(void)
|
||||
{
|
||||
ln_serial_t *hw = (ln_serial_t *)&uart_serial[SER_PORT_UART1];
|
||||
uint8_t tx_char = 0;
|
||||
|
||||
if (fifo_isempty(&hw->serial->txfifo))
|
||||
{
|
||||
hal_uart_it_disable(UART1_BASE, USART_IT_TXE);
|
||||
hw->Hardware.isSending = LN_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_char = fifo_pop(&hw->serial->txfifo);
|
||||
hal_uart_send_data(UART1_BASE, tx_char);
|
||||
while (hal_uart_flag_get(UART1_BASE, USART_FLAG_TX_FIFO_FULL) == HAL_SET) {};
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart1_recv_data_isr(void)
|
||||
{
|
||||
uint8_t ch = 0;
|
||||
|
||||
ln_serial_t *hw = (ln_serial_t *)&uart_serial[SER_PORT_UART1];
|
||||
|
||||
while (fifo_isfull(&hw->serial->rxfifo)){
|
||||
serial_purge_rx(hw->serial);
|
||||
}
|
||||
|
||||
ch = hal_uart_recv_data(UART1_BASE);
|
||||
|
||||
fifo_push(&hw->serial->rxfifo, ch);
|
||||
hw->serial->rx_callback();
|
||||
}
|
||||
|
||||
static inline void serial_uart1_isr_callback(void)
|
||||
{
|
||||
if (hal_uart_it_en_status_get(UART1_BASE, USART_IT_RXNE) && \
|
||||
hal_uart_flag_get(UART1_BASE, USART_FLAG_RXNE)) {
|
||||
uart1_recv_data_isr();
|
||||
}
|
||||
|
||||
if (hal_uart_it_en_status_get(UART1_BASE, USART_IT_TXE) && \
|
||||
hal_uart_flag_get(UART1_BASE, USART_FLAG_TXE)) {
|
||||
uart1_send_data_isr();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart2_send_data_isr(void)
|
||||
{
|
||||
ln_serial_t *hw = (ln_serial_t *)&uart_serial[SER_PORT_UART2];
|
||||
uint8_t tx_char = 0;
|
||||
|
||||
if (fifo_isempty(&hw->serial->txfifo))
|
||||
{
|
||||
hal_uart_it_disable(UART2_BASE, USART_IT_TXE);
|
||||
hw->Hardware.isSending = LN_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_char = fifo_pop(&hw->serial->txfifo);
|
||||
hal_uart_send_data(UART2_BASE, tx_char);
|
||||
while (hal_uart_flag_get(UART2_BASE, USART_FLAG_TX_FIFO_FULL) == HAL_SET) {};
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart2_recv_data_isr(void)
|
||||
{
|
||||
uint8_t ch = 0;
|
||||
|
||||
ln_serial_t *hw = (ln_serial_t *)&uart_serial[SER_PORT_UART2];
|
||||
|
||||
while (fifo_isfull(&hw->serial->rxfifo)){
|
||||
serial_purge_rx(hw->serial);
|
||||
}
|
||||
|
||||
ch = hal_uart_recv_data(UART2_BASE);
|
||||
|
||||
fifo_push(&hw->serial->rxfifo, ch);
|
||||
hw->serial->rx_callback();
|
||||
}
|
||||
|
||||
static inline void serial_uart2_isr_callback(void)
|
||||
{
|
||||
if (hal_uart_it_en_status_get(UART2_BASE, USART_IT_RXNE) && \
|
||||
hal_uart_flag_get(UART2_BASE, USART_FLAG_RXNE)) {
|
||||
uart2_recv_data_isr();
|
||||
}
|
||||
|
||||
if (hal_uart_it_en_status_get(UART2_BASE, USART_IT_TXE) && \
|
||||
hal_uart_flag_get(UART2_BASE, USART_FLAG_TXE)) {
|
||||
uart2_send_data_isr();
|
||||
}
|
||||
}
|
||||
|
||||
void UART0_IRQHandler(void)
|
||||
{
|
||||
serial_uart0_isr_callback();
|
||||
}
|
||||
|
||||
void UART1_IRQHandler(void)
|
||||
{
|
||||
serial_uart1_isr_callback();
|
||||
}
|
||||
|
||||
void UART2_IRQHandler(void)
|
||||
{
|
||||
serial_uart2_isr_callback();
|
||||
}
|
||||
|
||||
42
cores/lightning-ln882h/base/fixups/serial_hw.h
Normal file
42
cores/lightning-ln882h/base/fixups/serial_hw.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef __SERIAL_HW_H__
|
||||
#define __SERIAL_HW_H__
|
||||
|
||||
#include "hal/hal_uart.h"
|
||||
#include "ln_types.h"
|
||||
|
||||
struct SerialHardware;
|
||||
struct Serial;
|
||||
|
||||
typedef enum {
|
||||
SER_PORT_UART0 = 0,
|
||||
SER_PORT_UART1 = 1,
|
||||
SER_PORT_UART2 = 2,
|
||||
SER_PORT_NUM = 3, /**< Number of serial ports */
|
||||
SER_PORT_ID_INVALID = SER_PORT_NUM
|
||||
}serial_port_id_t;
|
||||
|
||||
struct SerialHardwareVT
|
||||
{
|
||||
void (*init )(struct SerialHardware *ctx, struct Serial *ser, uint32_t baudrate);
|
||||
void (*cleanup )(struct SerialHardware *ctx);
|
||||
void (*txStart )(struct SerialHardware *ctx);
|
||||
int8_t (*txSending )(struct SerialHardware *ctx);
|
||||
int8_t (*setBaudrate)(struct SerialHardware *ctx, uint32_t baudrate);
|
||||
};
|
||||
|
||||
struct SerialHardware
|
||||
{
|
||||
const struct SerialHardwareVT *table;
|
||||
unsigned char *txbuffer;
|
||||
unsigned char *rxbuffer;
|
||||
size_t txbuffer_size;
|
||||
size_t rxbuffer_size;
|
||||
void *hw_device;
|
||||
volatile int8_t isSending;
|
||||
};
|
||||
|
||||
struct SerialHardware *serial_hw_getdesc(serial_port_id_t port_id);
|
||||
|
||||
|
||||
|
||||
#endif /* __SERIAL_HW_H__ */
|
||||
262
cores/lightning-ln882h/base/fixups/startup_ln882h_gcc.c
Normal file
262
cores/lightning-ln882h/base/fixups/startup_ln882h_gcc.c
Normal file
@@ -0,0 +1,262 @@
|
||||
|
||||
#include "ln882h.h"
|
||||
#include "ln_compiler.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Linker generated Symbols
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern uint32_t __copysection_ram0_load;
|
||||
extern uint32_t __copysection_ram0_start;
|
||||
extern uint32_t __copysection_ram0_end;
|
||||
extern uint32_t __etext;
|
||||
extern uint32_t __bss_ram0_start__;
|
||||
extern uint32_t __bss_ram0_end__;
|
||||
extern uint32_t __StackTop;
|
||||
extern uint32_t __retention_start__;
|
||||
extern uint32_t __retention_end__;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Handler Function Prototype
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef void( *pFunc )( void );
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
External References
|
||||
*----------------------------------------------------------------------------*/
|
||||
//extern void _start (void) __attribute__((noreturn)); /* PreeMain (C library entry point) */
|
||||
extern void lt_main (void);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Internal References
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Reset_Handler (void) ;
|
||||
__WEAK__ void NMI_Handler (void);
|
||||
__WEAK__ void HardFault_Handler (void);
|
||||
__WEAK__ void MemManage_Handler (void);
|
||||
__WEAK__ void BusFault_Handler (void);
|
||||
__WEAK__ void UsageFault_Handler (void);
|
||||
__WEAK__ void SVC_Handler (void);
|
||||
__WEAK__ void DebugMon_Handler (void);
|
||||
__WEAK__ void PendSV_Handler (void);
|
||||
__WEAK__ void SysTick_Handler (void);
|
||||
__WEAK__ void WDT_IRQHandler (void);
|
||||
__WEAK__ void EXT_IRQHandler (void);
|
||||
__WEAK__ void RTC_IRQHandler (void);
|
||||
__WEAK__ void RFSLP_IRQHandler (void);
|
||||
__WEAK__ void MAC_IRQHandler (void);
|
||||
__WEAK__ void BLE_WAKE_IRQHandler (void);
|
||||
__WEAK__ void BLE_ERR_IRQHandler (void);
|
||||
__WEAK__ void BLE_MAC_IRQHandler (void);
|
||||
__WEAK__ void DMA_IRQHandler (void);
|
||||
__WEAK__ void QSPI_IRQHandler (void);
|
||||
__WEAK__ void SDIO_F1_IRQHandler (void);
|
||||
__WEAK__ void SDIO_F2_IRQHandler (void);
|
||||
__WEAK__ void SDIO_F3_IRQHandler (void);
|
||||
__WEAK__ void CM4_FPIXC_IRQHandler (void);
|
||||
__WEAK__ void CM4_FPOFC_IRQHandler (void);
|
||||
__WEAK__ void CM4_FPUFC_IRQHandler (void);
|
||||
__WEAK__ void CM4_FPIOC_IRQHandler (void);
|
||||
__WEAK__ void CM4_FPDZC_IRQHandler (void);
|
||||
__WEAK__ void CM4_FPIDC_IRQHandler (void);
|
||||
__WEAK__ void I2C_IRQHandler (void);
|
||||
__WEAK__ void SPI0_IRQHandler (void);
|
||||
__WEAK__ void SPI1_IRQHandler (void);
|
||||
__WEAK__ void UART0_IRQHandler (void);
|
||||
__WEAK__ void UART1_IRQHandler (void);
|
||||
__WEAK__ void UART2_IRQHandler (void);
|
||||
__WEAK__ void ADC_IRQHandler (void);
|
||||
__WEAK__ void WS_IRQHandler (void);
|
||||
__WEAK__ void I2S_IRQHandler (void);
|
||||
__WEAK__ void GPIOA_IRQHandler (void);
|
||||
__WEAK__ void GPIOB_IRQHandler (void);
|
||||
__WEAK__ void TIMER0_IRQHandler (void);
|
||||
__WEAK__ void TIMER1_IRQHandler (void);
|
||||
__WEAK__ void TIMER2_IRQHandler (void);
|
||||
__WEAK__ void TIMER3_IRQHandler (void);
|
||||
__WEAK__ void ADV_TIMER_IRQHandler (void);
|
||||
__WEAK__ void AES_IRQHandler (void);
|
||||
__WEAK__ void TRNG_IRQHandler (void);
|
||||
__WEAK__ void PAOTD_IRQHandler (void);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
User Initial Stack & Heap
|
||||
*----------------------------------------------------------------------------*/
|
||||
//<h> Stack Configuration
|
||||
// <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
//</h>
|
||||
#define __STACK_SIZE 0x00000600
|
||||
static uint8_t stack[__STACK_SIZE] __attribute__ ((aligned(8), used, section(".stack")));
|
||||
|
||||
#if 0
|
||||
//<h> Heap Configuration
|
||||
// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
//</h>
|
||||
#define __HEAP_SIZE 0x00004000
|
||||
#if __HEAP_SIZE > 0
|
||||
static uint8_t heap[__HEAP_SIZE] __attribute__ ((aligned(8), used, section(".heap")));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Handler
|
||||
*----------------------------------------------------------------------------*/
|
||||
/* Exceptions */
|
||||
__WEAK__ void NMI_Handler (void) { while(1); }
|
||||
__WEAK__ void HardFault_Handler (void) { while(1); }
|
||||
__WEAK__ void MemManage_Handler (void) { while(1); }
|
||||
__WEAK__ void BusFault_Handler (void) { while(1); }
|
||||
__WEAK__ void UsageFault_Handler (void) { while(1); }
|
||||
__WEAK__ void SVC_Handler (void) { while(1); }
|
||||
__WEAK__ void DebugMon_Handler (void) { while(1); }
|
||||
__WEAK__ void PendSV_Handler (void) { while(1); }
|
||||
__WEAK__ void SysTick_Handler (void) { while(1); }
|
||||
__WEAK__ void WDT_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void EXT_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void RTC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void RFSLP_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void MAC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void BLE_WAKE_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void BLE_ERR_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void BLE_MAC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void DMA_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void QSPI_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void SDIO_F1_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void SDIO_F2_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void SDIO_F3_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void CM4_FPIXC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void CM4_FPOFC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void CM4_FPUFC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void CM4_FPIOC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void CM4_FPDZC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void CM4_FPIDC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void I2C_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void SPI0_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void SPI1_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void UART0_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void UART1_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void UART2_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void ADC_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void WS_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void I2S_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void GPIOA_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void GPIOB_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void TIMER0_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void TIMER1_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void TIMER2_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void TIMER3_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void ADV_TIMER_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void AES_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void TRNG_IRQHandler (void) { while(1); }
|
||||
__WEAK__ void PAOTD_IRQHandler (void) { while(1); }
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Vector table
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern const pFunc __Vectors[240];
|
||||
const pFunc __Vectors[240] __attribute__ ((section(".vectors"))) = {
|
||||
(pFunc)(&__StackTop), /* (0x00)Top of Stack */
|
||||
Reset_Handler, /* (0x04)IRQ -15 Reset Handler */
|
||||
NMI_Handler, /* (0x08)IRQ -14 NMI Handler */
|
||||
HardFault_Handler, /* (0x0C)IRQ -13 Hard Fault Handler */
|
||||
MemManage_Handler, /* (0x10)IRQ -12 MPU Fault Handler */
|
||||
BusFault_Handler, /* (0x14)IRQ -11 Bus Fault Handler */
|
||||
UsageFault_Handler, /* (0x18)IRQ -10 Usage Fault Handler */
|
||||
0, /* (0x1C)IRQ -9 Reserved */
|
||||
0, /* (0x20)IRQ -8 Reserved */
|
||||
0, /* (0x24)IRQ -7 Reserved */
|
||||
0, /* (0x28)IRQ -6 Reserved */
|
||||
SVC_Handler, /* (0x2C)IRQ -5 SVCall Handler */
|
||||
DebugMon_Handler, /* (0x30)IRQ -4 Debug Monitor Handler */
|
||||
0, /* (0x34)IRQ -3 Reserved */
|
||||
PendSV_Handler, /* (0x38)IRQ -2 PendSV Handler */
|
||||
SysTick_Handler, /* (0x3C)IRQ -1 SysTick Handler */
|
||||
|
||||
/* Interrupts */
|
||||
WDT_IRQHandler, /* (0x40)IRQ0 */
|
||||
EXT_IRQHandler, /* (0x44)IRQ1 */
|
||||
RTC_IRQHandler, /* (0x48)IRQ2 */
|
||||
RFSLP_IRQHandler, /* (0x4C)IRQ3 */
|
||||
MAC_IRQHandler, /* (0x50)IRQ4 */
|
||||
BLE_WAKE_IRQHandler, /* (0x54)IRQ5 */
|
||||
BLE_ERR_IRQHandler, /* (0x58)IRQ6 */
|
||||
BLE_MAC_IRQHandler, /* (0x5C)IRQ7 */
|
||||
DMA_IRQHandler, /* (0x60)IRQ8 */
|
||||
QSPI_IRQHandler, /* (0x64)IRQ9 */
|
||||
SDIO_F1_IRQHandler, /* (0x68)IRQ10 */
|
||||
SDIO_F2_IRQHandler, /* (0x6C)IRQ11 */
|
||||
SDIO_F3_IRQHandler, /* (0x70)IRQ12 */
|
||||
CM4_FPIXC_IRQHandler, /* (0x74)IRQ13 */
|
||||
CM4_FPOFC_IRQHandler, /* (0x78)IRQ14 */
|
||||
CM4_FPUFC_IRQHandler, /* (0x7C)IRQ15 */
|
||||
CM4_FPIOC_IRQHandler, /* (0x80)IRQ16 */
|
||||
CM4_FPDZC_IRQHandler, /* (0x84)IRQ17 */
|
||||
CM4_FPIDC_IRQHandler, /* (0x88)IRQ18 */
|
||||
I2C_IRQHandler, /* (0x8C)IRQ19 */
|
||||
SPI0_IRQHandler, /* (0x90)IRQ20 */
|
||||
SPI1_IRQHandler, /* (0x94)IRQ21 */
|
||||
UART0_IRQHandler, /* (0x98)IRQ22 */
|
||||
UART1_IRQHandler, /* (0x9C)IRQ23 */
|
||||
UART2_IRQHandler, /* (0xA0)IRQ24 */
|
||||
ADC_IRQHandler, /* (0xA4)IRQ25 */
|
||||
WS_IRQHandler, /* (0xA8)IRQ26 */
|
||||
I2S_IRQHandler, /* (0xAC)IRQ27 */
|
||||
GPIOA_IRQHandler, /* (0xB0)IRQ28 */
|
||||
GPIOB_IRQHandler, /* (0xB4)IRQ29 */
|
||||
TIMER0_IRQHandler, /* (0xB8)IRQ30 */
|
||||
TIMER1_IRQHandler, /* (0xBC)IRQ31 */
|
||||
TIMER2_IRQHandler, /* (0xC0)IRQ32 */
|
||||
TIMER3_IRQHandler, /* (0xC4)IRQ33 */
|
||||
ADV_TIMER_IRQHandler, /* (0xC8)IRQ34 */
|
||||
AES_IRQHandler, /* (0xCC)IRQ35 */
|
||||
TRNG_IRQHandler, /* (0xD0)IRQ36 */
|
||||
PAOTD_IRQHandler, /* (0xD4)IRQ37 */
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Reset Handler called on controller reset
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Reset_Handler(void) {
|
||||
uint32_t *pSrc, *pDest;
|
||||
uint32_t *pTable __attribute__((unused));
|
||||
|
||||
/* Firstly it copies data from read only memory to RAM.
|
||||
* There are two schemes to copy. One can copy more than one sections.
|
||||
* Another can copy only one section. The former scheme needs more
|
||||
* instructions and read-only data to implement than the latter.
|
||||
* Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes.
|
||||
*/
|
||||
pSrc = &__copysection_ram0_load;
|
||||
pDest = &__copysection_ram0_start;
|
||||
|
||||
for ( ; (pDest < &__copysection_ram0_end); ) {
|
||||
*pDest++ = *pSrc++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Single BSS section scheme.
|
||||
*
|
||||
* The BSS section is specified by following symbols
|
||||
* __bss_start__: start of the BSS section.
|
||||
* __bss_end__: end of the BSS section.
|
||||
*
|
||||
* Both addresses must be aligned to 4 bytes boundary.
|
||||
*/
|
||||
pDest = &__bss_ram0_start__;
|
||||
for ( ; pDest < &__bss_ram0_end__ ; ) {
|
||||
*pDest++ = 0UL;
|
||||
}
|
||||
|
||||
pDest = &__retention_start__;
|
||||
for ( ; pDest < &__retention_end__ ; ) {
|
||||
*pDest++ = 0UL;
|
||||
}
|
||||
|
||||
SystemInit(); /* CMSIS System Initialization */
|
||||
lt_main();
|
||||
}
|
||||
16
cores/lightning-ln882h/base/fixups/utils/debug/log.h
Normal file
16
cores/lightning-ln882h/base/fixups/utils/debug/log.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __cplusplus
|
||||
|
||||
#undef log_printf
|
||||
#define __wrap_sprintf __wrap_ln_sprintf
|
||||
#include_next "utils/debug/log.h"
|
||||
#undef __wrap_sprintf
|
||||
#undef log_printf
|
||||
#define log_printf(...) __wrap_ln_printf(__VA_ARGS__)
|
||||
#define __sprintf(tag, fct, ...) __wrap_ln_printf(tag);__wrap_ln_vprintf(__VA_ARGS__)
|
||||
|
||||
// Redefine LOG_LVL_CTRL
|
||||
#undef LOG_LVL_CTRL
|
||||
#define LOG_LVL_CTRL LOG_LVL_DEBUG
|
||||
|
||||
#endif //__cplusplus */
|
||||
|
||||
19
cores/lightning-ln882h/base/lt_defs.h
Normal file
19
cores/lightning-ln882h/base/lt_defs.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#error "Don't include this file directly"
|
||||
|
||||
#define LT_HAS_FLASH 1
|
||||
#define LT_HAS_FREERTOS 1
|
||||
#define LT_HAS_LWIP 1
|
||||
#define LT_HAS_LWIP2 1
|
||||
#define LT_HAS_MBEDTLS 1
|
||||
#define LT_HAS_OTA 1
|
||||
#define LT_HAS_PRINTF 1
|
||||
#define LT_HW_DEEP_SLEEP 0
|
||||
#define LT_HW_WATCHDOG 1
|
||||
#define LT_HW_WIFI 1
|
||||
|
||||
#define LT_REMALLOC 1
|
||||
|
||||
#define LT_HEAP_FUNC xPortGetFreeHeapSize
|
||||
#define LT_REALLOC_FUNC pvPortReAlloc
|
||||
18
cores/lightning-ln882h/base/lt_family.h
Normal file
18
cores/lightning-ln882h/base/lt_family.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <lt_pins.h>
|
||||
|
||||
// Choose the main UART output port
|
||||
#ifndef LT_UART_DEFAULT_PORT
|
||||
#if LT_HW_UART0
|
||||
#define LT_UART_DEFAULT_PORT 0
|
||||
#elif LT_HW_UART1
|
||||
#define LT_UART_DEFAULT_PORT 1
|
||||
#elif LT_HW_UART2
|
||||
#define LT_UART_DEFAULT_PORT 2
|
||||
#else
|
||||
#error "No serial port is available"
|
||||
#endif
|
||||
#endif
|
||||
39
cores/lightning-ln882h/base/port/fal_flash_ln882h_port.c
Normal file
39
cores/lightning-ln882h/base/port/fal_flash_ln882h_port.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
#include <fal.h>
|
||||
#include <hal/hal_flash.h>
|
||||
|
||||
#define FLASH_ERASE_MIN_SIZE (4 * 1024)
|
||||
|
||||
static int init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read(long offset, uint8_t *buf, size_t size) {
|
||||
hal_flash_read(offset, size, buf);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int write(long offset, const uint8_t *buf, size_t size) {
|
||||
hal_flash_program(offset, size, (uint8_t *)buf);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int erase(long offset, size_t size) {
|
||||
offset &= ~(FLASH_ERASE_MIN_SIZE - 1);
|
||||
size = ((size - 1) / FLASH_ERASE_MIN_SIZE) + 1;
|
||||
hal_flash_erase(offset, size * FLASH_ERASE_MIN_SIZE);
|
||||
return size * FLASH_ERASE_MIN_SIZE;
|
||||
}
|
||||
|
||||
const struct fal_flash_dev flash0 = {
|
||||
.name = FAL_FLASH_DEV_NAME,
|
||||
.addr = 0x0,
|
||||
.len = FLASH_LENGTH,
|
||||
.blk_size = FLASH_ERASE_MIN_SIZE,
|
||||
.ops = {init, read, write, erase},
|
||||
.write_gran = 1,
|
||||
};
|
||||
21
cores/lightning-ln882h/base/port/printf.c
Normal file
21
cores/lightning-ln882h/base/port/printf.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-19. */
|
||||
|
||||
#include <libretiny.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
#include <printf/printf.h>
|
||||
|
||||
extern Serial_t *serial_handles[SER_PORT_NUM];
|
||||
|
||||
uint8_t uart_print_port = LT_UART_DEFAULT_LOGGER;
|
||||
|
||||
void putchar_(char c) {
|
||||
putchar_p(c, uart_print_port);
|
||||
}
|
||||
|
||||
void putchar_p(char c, unsigned long port) {
|
||||
serial_putchar(serial_handles[port], c);
|
||||
}
|
||||
|
||||
WRAP_PRINTF(ln_printf);
|
||||
WRAP_VPRINTF(ln_vprintf);
|
||||
15
cores/lightning-ln882h/base/port/printf_port.h
Normal file
15
cores/lightning-ln882h/base/port/printf_port.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <printf_config.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
WRAP_DISABLE_DEF(ln_printf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
87
cores/lightning-ln882h/base/sdk_private.h
Normal file
87
cores/lightning-ln882h/base/sdk_private.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
// Fix to not include SDK reg_xx.h files in C++
|
||||
// These files declare inline functions with unallowed volatile assignments in C++
|
||||
#define __REG_CACHE_H__
|
||||
#define __REG_GPIO_H__
|
||||
#define __REG_I2C_H__
|
||||
#define __REG_LN_UART_H__
|
||||
#define __REG_QSPI_H__
|
||||
#define __REG_WDT_H__
|
||||
#define __REG_SYSC_AWO_H__
|
||||
#define __REG_SYSC_CMP_H__
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// PinNames
|
||||
#include "PinNames.h"
|
||||
|
||||
// undefine ROM stdio in favor of printf() library (wrappers)
|
||||
#undef printf
|
||||
#undef sprintf
|
||||
#undef vsprintf
|
||||
#undef snprintf
|
||||
#undef vsnprintf
|
||||
#undef vprintf
|
||||
#include <stdio.h>
|
||||
|
||||
// Conflicting types
|
||||
#define WIFI_MODE_STATION LN_WIFI_MODE_STATION
|
||||
#define WIFI_MODE_AP LN_WIFI_MODE_AP
|
||||
#define WIFI_MODE_AP_STATION LN_WIFI_MODE_AP_STATION
|
||||
#define WIFI_MODE_MAX LN_WIFI_MODE_MAX
|
||||
#define WIFI_AUTH_OPEN LN_WIFI_AUTH_OPEN
|
||||
#define WIFI_AUTH_WEP LN_WIFI_AUTH_WEP
|
||||
#define WIFI_AUTH_WPA_PSK LN_WIFI_AUTH_WPA_PSK
|
||||
#define WIFI_AUTH_WPA2_PSK LN_WIFI_AUTH_WPA2_PSK
|
||||
#define WIFI_AUTH_WPA_WPA2_PSK LN_WIFI_AUTH_WPA_WPA2_PSK
|
||||
#define WIFI_AUTH_WPA2_ENTERPRISE LN_WIFI_AUTH_WPA2_ENTERPRISE
|
||||
#define WIFI_AUTH_WPA3_SAE LN_WIFI_AUTH_WPA3_SAE
|
||||
#define WIFI_AUTH_WPA2_PSK_WPA3_SAE LN_WIFI_AUTH_WPA2_PSK_WPA3_SAE
|
||||
#define WIFI_AUTH_MAX LN_WIFI_AUTH_MAX
|
||||
#define wifi_mode_t ln_wifi_mode_t
|
||||
#define wifi_auth_mode_t ln_wifi_auth_mode_t
|
||||
|
||||
// SDK
|
||||
#include "ln_kv_api.h"
|
||||
#include "ln_nvds.h"
|
||||
#include "utils/debug/CmBacktrace/cm_backtrace.h"
|
||||
#include "utils/ln_psk_calc.h"
|
||||
#include "utils/power_mgmt/ln_pm.h"
|
||||
#include "utils/reboot_trace/reboot_trace.h"
|
||||
#include "utils/runtime/runtime.h"
|
||||
#include "utils/system_parameter.h"
|
||||
#include <hal/hal_adc.h>
|
||||
#include <hal/hal_gpio.h>
|
||||
#include <hal/hal_i2c.h>
|
||||
#include <hal/hal_interrupt.h>
|
||||
#include <hal/hal_wdt.h>
|
||||
#include <ln_wifi.h>
|
||||
#include <osal/osal.h>
|
||||
#include <serial/ln_serial.h>
|
||||
#include <wifi_manager.h>
|
||||
|
||||
#ifndef LN882H_SDK
|
||||
#undef WIFI_MODE_STATION
|
||||
#undef WIFI_MODE_AP
|
||||
#undef WIFI_MODE_AP_STATION
|
||||
#undef WIFI_MODE_MAX
|
||||
#undef WIFI_AUTH_OPEN
|
||||
#undef WIFI_AUTH_WEP
|
||||
#undef WIFI_AUTH_WPA_PSK
|
||||
#undef WIFI_AUTH_WPA2_PSK
|
||||
#undef WIFI_AUTH_WPA_WPA2_PSK
|
||||
#undef WIFI_AUTH_WPA2_ENTERPRISE
|
||||
#undef WIFI_AUTH_WPA3_SAE
|
||||
#undef WIFI_AUTH_WPA2_PSK_WPA3_SAE
|
||||
#undef WIFI_AUTH_MAX
|
||||
#undef wifi_mode_t
|
||||
#undef wifi_auth_mode_t
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
BIN
cores/lightning-ln882h/misc/boot_ln882h.bin
Normal file
BIN
cores/lightning-ln882h/misc/boot_ln882h.bin
Normal file
Binary file not shown.
177
cores/lightning-ln882h/misc/ln882hki_bsp.template.ld
Normal file
177
cores/lightning-ln882h/misc/ln882hki_bsp.template.ld
Normal file
@@ -0,0 +1,177 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Linker script to configure memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x10007100, LENGTH = 1228544
|
||||
RAM0 (rwx) : ORIGIN = 0x20000000, LENGTH = 295K
|
||||
RETENTION (rwx) : ORIGIN = 0x20049C00, LENGTH = 1K
|
||||
CACHE_MEM (rwx) : ORIGIN = 0x2004A000, LENGTH = 32K
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.flash_copysection :
|
||||
{
|
||||
__copysection_ram0_load = LOADADDR(.flash_copysection);
|
||||
__copysection_ram0_start = .;
|
||||
KEEP(*(.vectors)) /* startup code: ARM vectors */
|
||||
|
||||
*hal_qspi.c.o*(.text*)
|
||||
*hal_cache.c.o*(.text*)
|
||||
*hal_dma.c.o*(.text*)
|
||||
*hal_rtc.c.o*(.text*)
|
||||
*qspi.c.o*(.text*)
|
||||
*hal_flash.c.o*(.text*)
|
||||
*port.c.o*(.text*)
|
||||
*port.o*(.text*)
|
||||
|
||||
/* Optional .text part*/
|
||||
/*
|
||||
*hal_uart.o*(.text)
|
||||
*log.o*(.text)
|
||||
*serial.o*(.text)
|
||||
*serial_hw.o*(.text)
|
||||
*fifobuf.o*(.text)
|
||||
*/
|
||||
|
||||
. = ALIGN(4);
|
||||
/* all RW data in ram0 of wlan shared memory and lwip pubf pool are not in this section, they are in .bss section */
|
||||
*(.data*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
KEEP(*(.jcr*))
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__copysection_ram0_end = .;
|
||||
|
||||
} >RAM0 AT>FLASH
|
||||
|
||||
.flash_text :
|
||||
{
|
||||
PROVIDE(_stext = .);
|
||||
*(.text*)
|
||||
PROVIDE(_etext = .);
|
||||
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
KEEP(*(.eh_frame*))
|
||||
|
||||
/* section information for ln_at */
|
||||
. = ALIGN(4);
|
||||
__ln_at_cmd_tbl_start = .;
|
||||
KEEP(*(ln_at_cmd_tbl))
|
||||
__ln_at_cmd_tbl_end = .;
|
||||
} >FLASH
|
||||
|
||||
/* .stack_dummy section doesn't contain any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
PROVIDE(__stack_start__ = .);
|
||||
KEEP(*(.stack*))
|
||||
PROVIDE(__c_stack_top__ = .);
|
||||
PROVIDE(__stack_end__ = .);
|
||||
} >RAM0
|
||||
|
||||
/* Location counter can end up 2byte aligned with narrow Thumb code but
|
||||
__etext is assumed by startup code to be the LMA of a section in RAM
|
||||
which must be 4byte aligned */
|
||||
__etext = ALIGN (4);
|
||||
.bss_ram0 (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_ram0_start__ = .;
|
||||
*memp.o(.bss* COMMON)
|
||||
*(wlan_mem_local)
|
||||
*(wlan_mem_pkt)
|
||||
*(wlan_mem_dscr)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_ram0_end__ = .;
|
||||
} >RAM0
|
||||
|
||||
.no_init_data (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.no_init_data)
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4);
|
||||
__retention_start__ = .;
|
||||
*(retention_data)
|
||||
. = ALIGN(4);
|
||||
__retention_end__ = .;
|
||||
} >RETENTION
|
||||
|
||||
/* Group unwind sections together: */
|
||||
.ARM.extab : { *(.ARM.extab*) }
|
||||
.ARM.exidx :
|
||||
{
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
*(.gnu.linkonce.armexidx.*)
|
||||
__exidx_end = .;
|
||||
}
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.ARM.exidx.exit.text)
|
||||
*(.ARM.extab.exit.text)
|
||||
*(.ARM.exidx.devexit.text)
|
||||
*(.ARM.extab.devexit.text)
|
||||
}
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
PROVIDE(__StackTop = __c_stack_top__);
|
||||
PROVIDE(__StackLimit = __stack_start__);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
PROVIDE(heap0_start = __bss_ram0_end__);
|
||||
PROVIDE(heap0_end = ORIGIN(RAM0) + LENGTH(RAM0)); /* RAM0 end */
|
||||
PROVIDE(heap0_len = heap0_end - heap0_start);
|
||||
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
/* ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") */
|
||||
ASSERT(heap0_start < heap0_end, "region RAM0 overflowed with .bss")
|
||||
}
|
||||
59
cores/lightning-ln882h/misc/ln882x.cfg
Normal file
59
cores/lightning-ln882h/misc/ln882x.cfg
Normal file
@@ -0,0 +1,59 @@
|
||||
# Main file for ln882x series Cortex-M3 parts
|
||||
#
|
||||
# !!!!!!
|
||||
#
|
||||
|
||||
set CHIPNAME ln882h
|
||||
set CHIPSERIES ln882x
|
||||
|
||||
transport select swd
|
||||
|
||||
# Adapt based on what transport is active.
|
||||
source [find target/swj-dp.tcl]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
error "CHIPNAME not set. Please do not include ln882x.cfg directly."
|
||||
}
|
||||
|
||||
if { [info exists CHIPSERIES] } {
|
||||
# Validate chip series is supported
|
||||
if { $CHIPSERIES != "ln882x" } {
|
||||
error "Unsupported chip series specified."
|
||||
}
|
||||
set _CHIPSERIES $CHIPSERIES
|
||||
} else {
|
||||
error "CHIPSERIES not set. Please do not include ln882x.cfg directly."
|
||||
}
|
||||
|
||||
if { [info exists CPUTAPID] } {
|
||||
# Allow user override
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
# ln882x use a Cortex M4 core.
|
||||
if { $_CHIPSERIES == "ln882x" } {
|
||||
set _CPUTAPID 0x2ba01477
|
||||
}
|
||||
}
|
||||
|
||||
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||
|
||||
set _ENDIAN little
|
||||
|
||||
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
|
||||
|
||||
adapter speed 1000
|
||||
adapter srst delay 200
|
||||
|
||||
# ln882x (Cortex M4 core) support SYSRESETREQ
|
||||
if {![using_hla]} {
|
||||
# if srst is not fitted use SYSRESETREQ to
|
||||
# perform a soft reset
|
||||
cortex_m reset_config sysresetreq
|
||||
}
|
||||
|
||||
#$_TARGETNAME configure -event reset-init {ln882x_init}
|
||||
59
cores/lightning-ln882x/misc/ln882x.cfg
Normal file
59
cores/lightning-ln882x/misc/ln882x.cfg
Normal file
@@ -0,0 +1,59 @@
|
||||
# Main file for ln882x series Cortex-M3 parts
|
||||
#
|
||||
# !!!!!!
|
||||
#
|
||||
|
||||
set CHIPNAME ln882h
|
||||
set CHIPSERIES ln882x
|
||||
|
||||
transport select swd
|
||||
|
||||
# Adapt based on what transport is active.
|
||||
source [find target/swj-dp.tcl]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
error "CHIPNAME not set. Please do not include ln882x.cfg directly."
|
||||
}
|
||||
|
||||
if { [info exists CHIPSERIES] } {
|
||||
# Validate chip series is supported
|
||||
if { $CHIPSERIES != "ln882x" } {
|
||||
error "Unsupported chip series specified."
|
||||
}
|
||||
set _CHIPSERIES $CHIPSERIES
|
||||
} else {
|
||||
error "CHIPSERIES not set. Please do not include ln882x.cfg directly."
|
||||
}
|
||||
|
||||
if { [info exists CPUTAPID] } {
|
||||
# Allow user override
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
# ln882x use a Cortex M4 core.
|
||||
if { $_CHIPSERIES == "ln882x" } {
|
||||
set _CPUTAPID 0x2ba01477
|
||||
}
|
||||
}
|
||||
|
||||
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||
|
||||
set _ENDIAN little
|
||||
|
||||
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
|
||||
|
||||
adapter speed 1000
|
||||
adapter srst delay 200
|
||||
|
||||
# ln882x (Cortex M4 core) support SYSRESETREQ
|
||||
if {![using_hla]} {
|
||||
# if srst is not fitted use SYSRESETREQ to
|
||||
# perform a soft reset
|
||||
cortex_m reset_config sysresetreq
|
||||
}
|
||||
|
||||
#$_TARGETNAME configure -event reset-init {ln882x_init}
|
||||
Reference in New Issue
Block a user