mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b766c65615 | ||
|
|
8296b88fb6 | ||
|
|
a5efbf0592 | ||
|
|
37c98dd893 | ||
|
|
770a4ff27e | ||
|
|
b6560306ba | ||
|
|
5b39c93478 | ||
|
|
086008b716 | ||
|
|
35eb50a1e6 | ||
|
|
431e35ae8c | ||
|
|
25e2a99d8e | ||
|
|
88b01ef6f0 | ||
|
|
bd8ee86f9e | ||
|
|
ef96f7a28c | ||
|
|
03f240a244 | ||
|
|
c775f31ca7 | ||
|
|
1ca4fd1fef | ||
|
|
a6b6a0d779 |
No files matched your search
@@ -1,8 +1,12 @@
|
||||
# Mongoose - Embedded Network Library
|
||||
# Mongoose: a full-stack embedded networking library
|
||||
|
||||
Mongoose is a full-stack embedded networking library for C/C++: a TCP/IP stack
|
||||
with drivers, TLS 1.3, an embedded web server (HTTP, WebSocket), MQTT and
|
||||
firmware OTA updates in two files, `mongoose.c` and `mongoose.h`. Mongoose runs on
|
||||
STM32, NXP and other microcontrollers, on bare metal or with an RTOS, with no
|
||||
external dependencies. Use it for cloud connectivity, device web dashboards,
|
||||
secure firmware updates and remote control.
|
||||
|
||||
Mongoose is an open source, two-file C networking library and embedded web server for
|
||||
microcontrollers that combines TCP/IP stack, HTTP, WebSocket, MQTT, TLS 1.3
|
||||
stack, built-in firmware OTA updates, and device-dashboard infrastructure.
|
||||
License: GPLv2 or commercial.
|
||||
Website: https://mongoose.ws/
|
||||
GitHub repo: https://github.com/cesanta/mongoose
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mongoose - Embedded Web Server / Embedded Network Library
|
||||
# Mongoose: a full-stack embedded networking library
|
||||
|
||||
[](https://opensource.org/licenses/gpl-2.0.php)
|
||||
[](https://github.com/cesanta/mongoose/actions)
|
||||
@@ -7,11 +7,17 @@
|
||||
|
||||
<img src="https://mongoose.ws/images/logo.svg" width="48" height="48"
|
||||
align="left" style="float:left;" />
|
||||
Two files. Drop `mongoose.c` and `mongoose.h` into any C/C++ project and get a
|
||||
full network stack — HTTP, WebSocket, MQTT, TLS, firmware OTA
|
||||
updates, device dashboard — on any microcontroller or desktop OS.
|
||||
Mongoose is a full-stack embedded networking library for C/C++: a TCP/IP stack
|
||||
with drivers, TLS 1.3, an embedded web server (HTTP, WebSocket), MQTT and
|
||||
firmware OTA updates in two files, `mongoose.c` and `mongoose.h`. Mongoose runs on
|
||||
STM32, NXP and other microcontrollers, on bare metal or with an RTOS, with no
|
||||
external dependencies. Use it for cloud connectivity, device web dashboards,
|
||||
secure firmware updates and remote control.
|
||||
|
||||
On the market since 2004, used by vast number of open source and commercial
|
||||
Use it instead of lwIP + mbedTLS + httpd + an MQTT client + OTA glue code, or
|
||||
run it on top of lwIP or Zephyr.
|
||||
|
||||
On the market since 2004, used by a vast number of open source and commercial
|
||||
products - it even runs on the International Space Station! Features include:
|
||||
|
||||
- Cross-platform:
|
||||
@@ -24,7 +30,7 @@ products - it even runs on the International Space Station! Features include:
|
||||
- Source code is both ISO C and ISO C++ compliant
|
||||
- Very easy to integrate
|
||||
- Own TCP/IP stack for bare metal / RTOS, or run on top of any existing one (lwIP, Zephyr, ...)
|
||||
- Built-in TLS 1.3 ECC stack. Also can use external TLS libraries - mbedTLS, OpenSSL, or other
|
||||
- Built-in TLS 1.3 stack. Also can use external TLS libraries - mbedTLS, OpenSSL, or other
|
||||
- Does not depend on any other software to implement networking
|
||||
- Built-in firmware updates for STM32 H5, STM32 H7, NXP IMXRT, RP2040/2350, ESP32 and more
|
||||
- Commercial support with proactive security updates; [CRA-compliant](https://mongoose.ws/security/cra-compliance/)
|
||||
@@ -35,8 +41,32 @@ See https://mongoose.ws/ for complete documentation, videos, case studies, etc.
|
||||
|
||||
## Supported platforms
|
||||
|
||||
Mongoose can work on top of any TCP/IP stack that supports BSD sockets API.
|
||||
Platforms supported by the 3rd party TCP/IP stacks:
|
||||
Mongoose has its own built-in TCP/IP stack with drivers, so it needs no
|
||||
additional software to implement networking. The built-in stack runs on bare
|
||||
metal and under any RTOS. Platforms supported by the Mongoose built-in TCP/IP
|
||||
stack:
|
||||
|
||||
| MCU | Connectivity | Notes |
|
||||
| :-- | :----------- | :---- |
|
||||
| **STM32** | Built-in Ethernet | Ethernet-capable STM32F, STM32H5, STM32H7, STM32N6, STM32C5 variants |
|
||||
| **NXP i.MX RT** | Built-in Ethernet | RT102x, RT104x, RT105x, RT106x, RT117x, RT118x (NETC) |
|
||||
| **NXP MCX** | Built-in Ethernet | MCXN94x, MCXE247 |
|
||||
| **NXP RW612** | Eth, WiFi, 802.15.4 | Separate Ethernet and radio drivers |
|
||||
| **Microchip ATSAME54** | Built-in Ethernet | GMAC driver |
|
||||
| **Renesas RA** | Built-in Ethernet | RA6M, RA8M |
|
||||
| **Infineon XMC** | Built-in Ethernet | XMC4, XMC7 |
|
||||
| **Texas Instruments** | Built-in Ethernet | TM4C, TMS570 |
|
||||
| **RP2040, RP2350, STM32, others** | CYW43xx Wi-Fi chips | SPI or SDIO; Pico W, Pico 2 W, Pico RM2, Arduino Portenta H7 |
|
||||
| **STM32, others** | ST67W6 Wi-Fi modules | SPI; for example, STM32U5 with the ST67W611M1 module |
|
||||
| **MCUs with an NXP Wi-Fi SDK port** | NXP Wi-Fi | Requires the SDK's Wi-Fi port implementing the driver's network hooks |
|
||||
| **NXP MCXW71** | Built-in 802.15.4 radio | IPv4 over IEEE 802.15.4 |
|
||||
| **NXP RW612** | Built-in 802.15.4 radio | IPv4 over IEEE 802.15.4; requires NXP radio firmware |
|
||||
| **Any MCU with SPI** | W5500 or W5100 Ethernet chips | External Wiznet MAC+PHY |
|
||||
| **MCUs connected to a cellular modem** | Cellular | AT commands and PPP; for example, SIM800 |
|
||||
| **MCUs with CMSIS Ethernet drivers** | Ethernet via CMSIS-Driver | Requires CMSIS Ethernet MAC and PHY drivers |
|
||||
|
||||
Mongoose can also run on top of any TCP/IP stack that supports the BSD
|
||||
sockets API. Platforms supported via 3rd party TCP/IP stacks:
|
||||
|
||||
| TCP/IP stack | Notes |
|
||||
| :-------------- | :------- |
|
||||
@@ -45,23 +75,6 @@ Platforms supported by the 3rd party TCP/IP stacks:
|
||||
| **Other** | Any other TCP/IP stack that supports BSD socket API, for example Amazon FreeRTOS-TCP |
|
||||
| **Linux, Mac, Windows** | Workstations, server, single board computers, embedded Linux devices running on MPUs or FPGAs |
|
||||
|
||||
Optionally, Mongoose provides its own built-in TCP/IP stack, eliminating the
|
||||
need for additional software to implement networking functionality. The
|
||||
built-in stack supports operation in both bare-metal and RTOS environments.
|
||||
Platforms supported by the Mongoose built-in TCP/IP stack:
|
||||
|
||||
| Hardware | Notes |
|
||||
| :------------- | :------- |
|
||||
| **STM32** | All STM32 MCUs with built-in Ethernet: STM32Fxx, STM32H5xx, STM32H7xx |
|
||||
| **NXP** | All NXP MCUs with built-in Ethernet: IMXRT102x, IMXRT104x, IMXRT105x, IMXRT106x, IMXRT117x, RW612, MCXN94x |
|
||||
| **Microchip** | ATSAME54 MCUs with built-int Ethernet |
|
||||
| **Renesas** | RA5M, RA6M, RA8M MCUs with built-in Ethernet |
|
||||
| **Infineon** | XMC4, XMC7 MCUs with built-in Ethernet |
|
||||
| **Texas Instruments** | TM4C, TMS570 MCUs with built-in Ethernet |
|
||||
| **Cypress WiFi** | Any MCU with CY43xx WiFi chips, like RP2040 Pico-W, RP2350 Pico2-W, Arduino Portenta |
|
||||
| **Wiznet Ethernet** | Any MCU that use Wiznet W5500 or Wiznet 5100 MAC+PHY chips |
|
||||
| **Cellular** | NRF9160, SIM800 |
|
||||
|
||||
## Usage Examples
|
||||
|
||||
Below are quick snippets that should give an idea how simple the API is and
|
||||
@@ -158,6 +171,17 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
## Licensing
|
||||
|
||||
Mongoose is dual-licensed:
|
||||
- GPLv2: free for open source projects. Many popular open source projects use
|
||||
Mongoose, for example
|
||||
[SWUpdate](https://github.com/sbabic/swupdate/tree/master/mongoose), the
|
||||
embedded Linux update framework
|
||||
- Commercial: for closed-source products. Includes support directly from the
|
||||
engineers who wrote the whole stack, and early security fixes.
|
||||
See [licensing](https://mongoose.ws/licensing/)
|
||||
|
||||
## Commercial use
|
||||
- Mongoose is used by hundreds of businesses, from Fortune500 giants like
|
||||
Siemens, Schneider Electric, Broadcom, Bosch, Google, Samsung, Qualcomm, Caterpillar to the small businesses
|
||||
@@ -222,12 +246,12 @@ Technical guides and deep dives into embedded web servers, WebUI integration and
|
||||
- [lwIP vs Mongoose - TCP/IP Stack Integration Benchmark](https://mongoose.ws/articles/lwip-vs-mongoose-tcpip-stack-integration/)
|
||||
- [Embedded TCP/IP Stacks Comparison](https://mongoose.ws/embedded-tcpip-stack-comparison/)
|
||||
- [STM32H5 File System on Internal Flash: LittleFS + Mongoose](https://mongoose.ws/articles/stm32h5-file-system-on-internal-flash/)
|
||||
- [Firmware OTA and remote control on NXP FRDM-RW612](https://mongoose.ws/articles/mdash/)
|
||||
- [Firmware OTA and remote control on NXP FRDM-RW612](https://mongoose.ws/articles/rw612-mdash/)
|
||||
- [25000 WebSocket messages per second on STM32 Nucleo-H723ZG](https://mongoose.ws/articles/stm32-websocket-benchmark/)
|
||||
- [How to connect STM32 to AWS IoT Core](https://mongoose.ws/articles/stm32-aws-iot/)
|
||||
- [How to connect STM32 to Azure IoT Hub](https://mongoose.ws/articles/stm32-azure-iot-hub/)
|
||||
- [How to connect STM32 to EMQX](https://mongoose.ws/articles/stm32-emqx/)
|
||||
- [STM32 Device Management deep dive: Secure OTA, Remote Control, health monitor](https://mongoose.ws/articles/stm32-mdash-deep-dive/")
|
||||
- [STM32 Device Management deep dive: Secure OTA, Remote Control, health monitor](https://mongoose.ws/articles/stm32-mdash-deep-dive/)
|
||||
- [STM32 TCP/IP footprint: how much flash and RAM does Mongoose take?](https://mongoose.ws/articles/tcp-ip-footprint/)
|
||||
|
||||
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
# Security Policy
|
||||
|
||||
Mongoose is a full-stack embedded networking library by Cesanta Software Ltd,
|
||||
<https://mongoose.ws>. This policy covers how to report vulnerabilities
|
||||
and how Cesanta handles them.
|
||||
|
||||
## Supported versions
|
||||
|
||||
Security fixes go to the `master` branch and the latest release.
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Do not report security issues in public GitHub issues. Report them
|
||||
privately using GitHub Security Advisories:
|
||||
<https://github.com/cesanta/mongoose/security/advisories/new>
|
||||
|
||||
Include the Mongoose version or commit, steps or a proof of concept to reproduce, and
|
||||
the impact. Cesanta usually responds the same business day.
|
||||
|
||||
## Disclosure process
|
||||
|
||||
1. Cesanta reviews the report and coordinates a fix with the reporter.
|
||||
2. Eligible commercial customers receive a notification and a private fix
|
||||
one month before the CVE becomes public.
|
||||
3. The fix and the CVE are then published. The reporter is credited in the
|
||||
GitHub Security Advisory.
|
||||
|
||||
## Security testing
|
||||
|
||||
- CI on every push, unit tests built with ASAN and UBSan
|
||||
- CodeQL static analysis on every commit
|
||||
- Continuous fuzzing on OSS-Fuzz, plus nightly libFuzzer runs
|
||||
- AI-assisted security review on every pull request
|
||||
- Regular review by independent security research groups worldwide
|
||||
|
||||
## EU Cyber Resilience Act (CRA)
|
||||
|
||||
Mongoose supports CRA compliance for connected products: a documented
|
||||
vulnerability handling process (this file), TLS 1.3, signed OTA firmware
|
||||
updates, and an SBOM (`sbom.cdx.json`). Details:
|
||||
<https://mongoose.ws/security/cra-compliance/>
|
||||
+923
-71
File diff suppressed because it is too large.
Load diff
+136
-96
@@ -165,6 +165,7 @@ extern "C" {
|
||||
|
||||
#if MG_ENABLE_TCPIP && !defined(MG_ENABLE_DRIVER_STM32F) && \
|
||||
!defined(MG_ENABLE_DRIVER_STM32H) && !defined(MG_ENABLE_DRIVER_STM32N) && \
|
||||
!defined(MG_ENABLE_DRIVER_STM32C) && \
|
||||
!defined(MG_ENABLE_DRIVER_CYW) && !defined(MG_ENABLE_DRIVER_CYW_SDIO) && \
|
||||
!defined(MG_ENABLE_DRIVER_ST67W6)
|
||||
#if defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
|
||||
@@ -173,6 +174,8 @@ extern "C" {
|
||||
#define MG_ENABLE_DRIVER_STM32H 1
|
||||
#elif defined(STM32N6)
|
||||
#define MG_ENABLE_DRIVER_STM32N 1
|
||||
#elif defined(STM32C5)
|
||||
#define MG_ENABLE_DRIVER_STM32C 1
|
||||
#else
|
||||
#error Select a driver in mongoose_config.h
|
||||
#endif
|
||||
@@ -189,70 +192,8 @@ extern "C" {
|
||||
#define MG_OTA MG_OTA_STM32H5
|
||||
#elif !defined(MG_OTA) && defined(STM32H7)
|
||||
#define MG_OTA MG_OTA_STM32H7
|
||||
#endif
|
||||
|
||||
// OTA rollback timer via IWDG. Fixed 10 s hang-detection window (prescaler
|
||||
// /1024, LSI ~32 kHz: reload = 10 * 32000 / 1024 = 312). mg_ota_poll() feeds
|
||||
// the watchdog every 500 ms while in MG_OTA_TESTING state; if the event loop
|
||||
// hangs for 10 s, the IWDG fires and the device rolls back.
|
||||
// STM32H7 names the peripheral IWDG1; all others use IWDG.
|
||||
// The total evaluation period is set by MG_OTA_ROLLBACK_TIMEOUT_SECONDS.
|
||||
// STM32H7 names the watchdog peripheral IWDG1; all other families use IWDG.
|
||||
#if defined(IWDG1) && !defined(IWDG)
|
||||
#define MG_IWDG IWDG1
|
||||
#else
|
||||
#define MG_IWDG IWDG
|
||||
#endif
|
||||
// PR=6 → /256 prescaler, RLR=1250 → ~10 s at LSI 32 kHz.
|
||||
// Works on F4/F7/H5/H7; uses direct register writes so it is safe before HAL_Init().
|
||||
#ifndef MG_OTA_ROLLBACK_TIMER_START
|
||||
#define MG_OTA_ROLLBACK_TIMER_START() \
|
||||
do { \
|
||||
MG_IWDG->KR = 0xCCCCU; /* start + LSI */ \
|
||||
MG_IWDG->KR = 0x5555U; /* unlock PR/RLR */ \
|
||||
MG_IWDG->PR = 6U; /* /256 */ \
|
||||
MG_IWDG->RLR = 1250U; /* 10 s */ \
|
||||
while (MG_IWDG->SR & (IWDG_SR_PVU | IWDG_SR_RVU)) (void) 0; \
|
||||
MG_IWDG->KR = 0xAAAAU; /* reload */ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// Feed (reload) the IWDG. Called from mg_ota_poll() every 500 ms.
|
||||
#ifndef MG_OTA_ROLLBACK_TIMER_FEED
|
||||
#define MG_OTA_ROLLBACK_TIMER_FEED() (MG_IWDG->KR = 0xAAAAU)
|
||||
#endif
|
||||
|
||||
// OTA state in a backup register that survives warm resets but clears on POR.
|
||||
// STATE_GET reads work without any setup. STATE_SET enables the RTC APB clock
|
||||
// and unlocks backup domain write access via direct register writes, so it is
|
||||
// safe to call from any context (before or after HAL_Init).
|
||||
// H5 (TAMP->BKP0R), H7 (RTC->BKP0R), F4/F7 (RTC->BKP0R).
|
||||
#ifndef MG_OTA_STATE_GET
|
||||
#if defined(PWR_DBPCR_DBP)
|
||||
#define MG_OTA_DBP_ENABLE() (PWR->DBPCR |= PWR_DBPCR_DBP)
|
||||
#elif defined(PWR_CR1_DBP)
|
||||
#define MG_OTA_DBP_ENABLE() (PWR->CR1 |= PWR_CR1_DBP)
|
||||
#else
|
||||
#define MG_OTA_DBP_ENABLE() (PWR->CR |= PWR_CR_DBP)
|
||||
#endif
|
||||
|
||||
#if defined(TAMP)
|
||||
#define MG_OTA_STATE_GET() \
|
||||
(RCC->APB3ENR |= RCC_APB3ENR_RTCAPBEN, TAMP->BKP0R)
|
||||
#define MG_OTA_STATE_SET(v) \
|
||||
(RCC->APB3ENR |= RCC_APB3ENR_RTCAPBEN, MG_OTA_DBP_ENABLE(), \
|
||||
(TAMP->BKP0R = (uint32_t) (v)), TAMP->BKP0R)
|
||||
#elif defined(RCC_APB4ENR_RTCAPBEN)
|
||||
#define MG_OTA_STATE_GET() (RTC->BKP0R)
|
||||
#define MG_OTA_STATE_SET(v) \
|
||||
(RCC->APB4ENR |= RCC_APB4ENR_RTCAPBEN, MG_OTA_DBP_ENABLE(), \
|
||||
(RTC->BKP0R = (uint32_t) (v)))
|
||||
#else
|
||||
#define MG_OTA_STATE_GET() (RTC->BKP0R)
|
||||
#define MG_OTA_STATE_SET(v) \
|
||||
(RCC->APB1ENR |= RCC_APB1ENR_PWREN, MG_OTA_DBP_ENABLE(), \
|
||||
(RTC->BKP0R = (uint32_t) (v)))
|
||||
#endif
|
||||
#elif !defined(MG_OTA) && defined(STM32C5)
|
||||
#define MG_OTA MG_OTA_STM32C5
|
||||
#endif
|
||||
|
||||
// use HAL-defined execute-in-ram section
|
||||
@@ -2783,29 +2724,32 @@ int mg_http_status(const struct mg_http_message *hm);
|
||||
|
||||
// Streams a POST/PUT body to a callback as it arrives, without buffering it.
|
||||
// Call it from an MG_EV_HTTP_HDRS handler, after matching the request, e.g.
|
||||
// with mg_match(). Returns true if it took over the connection, false if the
|
||||
// request is not POST/PUT, is chunked, or has no Content-Length.
|
||||
// with mg_match(). Always takes over the connection. Invalid requests receive
|
||||
// an HTTP error; client-side failures call mg_error(). Replies and connection
|
||||
// draining are handled internally, including callback failures.
|
||||
//
|
||||
// Callback upload_fn(hm, data, user_data) is called:
|
||||
// - at start: hm is set. Open the file, set *user_data.
|
||||
// - per chunk: data is set, 512 byte aligned except the last. Not called
|
||||
// again after a failure.
|
||||
// - at end: both NULL. Always called once, also when the connection drops
|
||||
// early, so release resources here. A truncated body looks like a complete
|
||||
// one: validate before committing.
|
||||
// Return true on success, false on error.
|
||||
// - at end: both NULL. Always called exactly once, including validation
|
||||
// failures before start and connections that drop early. Release resources
|
||||
// here. A truncated body looks like a complete one: validate before
|
||||
// committing.
|
||||
// The callback returns true on success, false on error. A failure stops
|
||||
// streaming immediately and calls the end callback before closing.
|
||||
// Example:
|
||||
// if (ev == MG_EV_HTTP_HDRS && mg_match(hm->uri, mg_str("/fs/*"), NULL) {
|
||||
// mg_http_stream_body(c, hm, upload, NULL));
|
||||
// if (ev == MG_EV_HTTP_HDRS && mg_match(hm->uri, mg_str("/fs/*"), NULL)) {
|
||||
// mg_http_stream_body(c, hm, upload, NULL);
|
||||
// }
|
||||
// Full example:
|
||||
// tutorials/http/file-upload-single-post
|
||||
// Related APIs:
|
||||
// mg_http_listen(), mg_http_next_multipart()
|
||||
// Notes:
|
||||
// After it returns true, this function hijacks the connection. Existing event
|
||||
// handler not called, hm is invalid, c->data and c->fn_data are modified
|
||||
bool mg_http_stream_body(struct mg_connection *c, struct mg_http_message *hm,
|
||||
// The existing event handler is no longer called. hm is invalid after this
|
||||
// call; c->data and c->fn_data are reserved for streaming state.
|
||||
void mg_http_stream_body(struct mg_connection *c, struct mg_http_message *hm,
|
||||
bool (*upload_fn)(struct mg_http_message *,
|
||||
struct mg_str *, void **user_data),
|
||||
void *user_data);
|
||||
@@ -4227,12 +4171,14 @@ extern void mg_mqtt_poll(struct mg_mgr *);
|
||||
|
||||
|
||||
|
||||
|
||||
// Supported OTA targets
|
||||
#define MG_OTA_NONE 0 // No OTA support
|
||||
#define MG_OTA_STM32H5 1 // STM32 H5
|
||||
#define MG_OTA_STM32H7 2 // STM32 H7
|
||||
#define MG_OTA_STM32H7_DUAL_CORE 3 // STM32 H7 dual core
|
||||
#define MG_OTA_STM32F 4 // STM32 F7/F4/F2
|
||||
#define MG_OTA_STM32C5 5 // STM32 C5, same flash controller as H5
|
||||
#define MG_OTA_CH32V307 100 // WCH CH32V307
|
||||
#define MG_OTA_U2A 200 // Renesas U2A16, U2A8, U2A6
|
||||
#define MG_OTA_RT1020 300 // IMXRT1020
|
||||
@@ -4242,6 +4188,7 @@ extern void mg_mqtt_poll(struct mg_mgr *);
|
||||
#define MG_OTA_RT1170 304 // IMXRT1170
|
||||
#define MG_OTA_RT1180 305 // IMXRT1180
|
||||
#define MG_OTA_MCXN 310 // MCXN947
|
||||
#define MG_OTA_MCXW71 311 // MCXW71
|
||||
#define MG_OTA_RW612 320 // FRDM-RW612
|
||||
#define MG_OTA_FLASH 900 // OTA via internal flash
|
||||
#define MG_OTA_ESP32 910 // ESP32 OTA implementation
|
||||
@@ -4271,6 +4218,18 @@ bool mg_ota_write(const void *buf, size_t len);
|
||||
// Ends the OTA process and commits the written firmware.
|
||||
bool mg_ota_end(void);
|
||||
|
||||
// Push-based OTA: mg_http_stream_body() callback that flashes the request
|
||||
//
|
||||
// ```c
|
||||
// if (ev == MG_EV_HTTP_HDRS) {
|
||||
// struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
// if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
// mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
bool mg_http_ota_cb(struct mg_http_message *hm, struct mg_str *data, void **p);
|
||||
|
||||
// MG_OTA_ROLLBACK: swap firmware banks and reset. On flash-based OTA, the
|
||||
// default calls swap_fn() (no-op on single-bank) then resets. Override in
|
||||
// mongoose_config.h for platforms without mg_flash (ESP32, PicoSDK, etc.).
|
||||
@@ -4414,32 +4373,15 @@ void mg_ota_poll(struct mg_mgr *);
|
||||
|
||||
|
||||
|
||||
// Memory usage in bytes. Override in mongoose_config.h for the target.
|
||||
#ifndef MG_HEALTH_STACK_USED
|
||||
#define MG_HEALTH_STACK_USED 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_STACK_TOTAL
|
||||
#define MG_HEALTH_STACK_TOTAL 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_HEAP_USED
|
||||
#define MG_HEALTH_HEAP_USED 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_HEAP_TOTAL
|
||||
#define MG_HEALTH_HEAP_TOTAL 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_MAGIC
|
||||
#define MG_HEALTH_MAGIC {'M', 'G', 'H', '3'} // '3' is the layout version
|
||||
#endif
|
||||
|
||||
#if !defined(MG_HEALTH_RAM) && (defined(STM32H7_DEV_ID) || defined(STM32H5))
|
||||
#if !defined(MG_HEALTH_RAM) && (defined(STM32H7_DEV_ID) || defined(STM32H5) || defined(STM32C5))
|
||||
#define MG_HEALTH_RAM __attribute__((section(".mg_health")))
|
||||
#endif
|
||||
|
||||
#if !defined(MG_HEALTH_DATA_SIZE) && (defined(STM32H7_DEV_ID) || defined(STM32H5))
|
||||
#if !defined(MG_HEALTH_DATA_SIZE) && (defined(STM32H7_DEV_ID) || defined(STM32H5) || defined(STM32C5))
|
||||
#define MG_HEALTH_DATA_SIZE 250
|
||||
#endif
|
||||
|
||||
@@ -4806,6 +4748,41 @@ extern struct mg_tcpip_driver mg_tcpip_driver_nxp_wifi;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_st67w6;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_atcmd;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_netc;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_mcxw71;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_rw612_154;
|
||||
|
||||
// IEEE 802.15.4 radio channel and PAN ID. Settable in mongoose_config.h
|
||||
#ifndef MG_L2_802154_CHANNEL
|
||||
#define MG_L2_802154_CHANNEL 15 // 11..26
|
||||
#endif
|
||||
#ifndef MG_L2_802154_PAN_ID
|
||||
#define MG_L2_802154_PAN_ID 0xabcd
|
||||
#endif
|
||||
|
||||
// driver_data for IEEE 802.15.4 radio drivers. The interface is Ethernet:
|
||||
// each Ethernet frame is split into broadcast radio frames, and reassembled
|
||||
// on the other side, see mg_l2_802154_tx() and mg_l2_802154_rx()
|
||||
struct mg_l2_802154_data {
|
||||
uint8_t channel; // User-set channel, 11..26
|
||||
uint16_t pan_id; // User-set PAN ID
|
||||
uint8_t seq, tag; // MAC sequence number, tag of the last sent frame
|
||||
uint8_t rxtag, rxnext; // Frame being reassembled: tag, next fragment
|
||||
uint8_t rxsrc[8]; // Its sender
|
||||
uint16_t rxlen; // Its bytes received so far
|
||||
uint8_t rxbuf[1514]; // Reassembly buffer, one Ethernet frame
|
||||
};
|
||||
|
||||
// Splits an Ethernet frame into radio frames, sends each by calling send().
|
||||
// Called by radio drivers' tx(). Return len, or 0 on error
|
||||
size_t mg_l2_802154_tx(struct mg_tcpip_if *ifp, const void *buf, size_t len,
|
||||
size_t (*send)(const uint8_t *, size_t,
|
||||
struct mg_tcpip_if *));
|
||||
|
||||
// Adds a received radio frame f of n bytes to the frame being reassembled.
|
||||
// Called by radio drivers' rx(). Return the Ethernet frame length, copied to
|
||||
// buf, when it is complete, otherwise 0
|
||||
size_t mg_l2_802154_rx(struct mg_tcpip_if *ifp, const uint8_t *f, size_t n,
|
||||
void *buf, size_t len);
|
||||
|
||||
// SPI bus abstraction for SPI-attached network chips (e.g. W5500).
|
||||
// Populate and assign to the driver's driver_data field.
|
||||
@@ -5193,6 +5170,31 @@ struct mg_tcpip_driver_imxrt_data {
|
||||
#endif
|
||||
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_MCXW71) && \
|
||||
MG_ENABLE_DRIVER_MCXW71
|
||||
|
||||
// NXP MCXW71 IEEE 802.15.4 radio, ZLL link layer, as an Ethernet interface:
|
||||
// Ethernet frames are split into radio frames, see mg_l2_802154_tx().
|
||||
// The transceiver (XCVR) must be set up for 802.15.4 before mg_tcpip_init(),
|
||||
// see hal_radio_init() in the FRDM-MCXW71 tutorial.
|
||||
// driver_data: struct mg_l2_802154_data, channel and PAN ID set
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_l2_802154_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.channel = MG_L2_802154_CHANNEL; \
|
||||
driver_data_.pan_id = MG_L2_802154_PAN_ID; \
|
||||
mif_.driver = &mg_tcpip_driver_mcxw71; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: mcxw71, channel %d", MG_L2_802154_CHANNEL)); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MG_ENABLE_TCPIP) && MG_ENABLE_TCPIP && \
|
||||
defined(MG_ENABLE_DRIVER_NETC) && MG_ENABLE_DRIVER_NETC
|
||||
|
||||
@@ -5411,6 +5413,35 @@ struct mg_tcpip_driver_rw612_data {
|
||||
#endif
|
||||
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RW612_154) && \
|
||||
MG_ENABLE_DRIVER_RW612_154
|
||||
|
||||
// NXP RW612 IEEE 802.15.4 radio, as an Ethernet interface: Ethernet frames
|
||||
// are split into radio frames, see mg_l2_802154_tx(). The radio runs on
|
||||
// CPU2: NXP BLE/802.15.4 combo firmware, an OpenThread radio co-processor
|
||||
// (RCP). The firmware must be loaded and running before mg_tcpip_init(), see
|
||||
// the FRDM-RW612 eth_radio_bridge tutorial. The driver talks to it over the
|
||||
// CPU2 <-> CPU3 IMU mailbox: IMUMC messages carrying HDLC framed Spinel.
|
||||
// driver_data: struct mg_l2_802154_data, channel and PAN ID set
|
||||
|
||||
#ifndef MG_TCPIP_DRIVER_INIT
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_l2_802154_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.channel = MG_L2_802154_CHANNEL; \
|
||||
driver_data_.pan_id = MG_L2_802154_PAN_ID; \
|
||||
mif_.driver = &mg_tcpip_driver_rw612_154; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: rw612_154, channel %d", MG_L2_802154_CHANNEL)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
|
||||
MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
@@ -5572,6 +5603,13 @@ struct mg_tcpip_driver_stm32f_data {
|
||||
#if !defined(MG_ENABLE_DRIVER_STM32H)
|
||||
#define MG_ENABLE_DRIVER_STM32H 0
|
||||
#endif
|
||||
#if !defined(MG_ENABLE_DRIVER_STM32C)
|
||||
#define MG_ENABLE_DRIVER_STM32C 0
|
||||
#endif
|
||||
#if MG_ENABLE_DRIVER_STM32C // STM32C5: STM32H5 MAC, the IRQ is ETH1
|
||||
#undef MG_ENABLE_DRIVER_STM32H
|
||||
#define MG_ENABLE_DRIVER_STM32H 1
|
||||
#endif
|
||||
#if !defined(MG_ENABLE_DRIVER_MCXN)
|
||||
#define MG_ENABLE_DRIVER_MCXN 0
|
||||
#endif
|
||||
@@ -5611,9 +5649,11 @@ struct mg_tcpip_driver_stm32h_data {
|
||||
#define MG_DRIVER_MDC_CR 4
|
||||
#endif
|
||||
|
||||
#if MG_ENABLE_DRIVER_STM32H && MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#if MG_ENABLE_DRIVER_STM32H && !MG_ENABLE_DRIVER_STM32C && \
|
||||
MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH_IRQn)
|
||||
#elif MG_ENABLE_DRIVER_STM32N && MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#elif (MG_ENABLE_DRIVER_STM32N || MG_ENABLE_DRIVER_STM32C) && \
|
||||
MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH1_IRQn)
|
||||
#elif !defined(MG_ENABLE_ETH_IRQ)
|
||||
#define MG_ENABLE_ETH_IRQ()
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
</environment>
|
||||
</environments>
|
||||
<releases>
|
||||
<release date="2026-10-21" version="7.23.3">See https://github.com/cesanta/mongoose/releases/tag/7.23</release>
|
||||
<release date="2026-10-19" version="7.23.2">See https://github.com/cesanta/mongoose/releases/tag/7.23</release>
|
||||
<release date="2026-09-28" version="7.23.1">See https://github.com/cesanta/mongoose/releases/tag/7.23</release>
|
||||
<release date="2026-05-11" version="7.21.7">See https://github.com/cesanta/mongoose/releases/tag/7.21</release>
|
||||
@@ -28,7 +29,7 @@
|
||||
<keyword>IMPLEMENTED_WITH_STM32CUBEMX</keyword>
|
||||
</keywords>
|
||||
<components>
|
||||
<component Cclass="Mongoose" Cgroup="Networking Core" Cversion="7.23.2" maxInstances="1">
|
||||
<component Cclass="Mongoose" Cgroup="Networking Core" Cversion="7.23.3" maxInstances="1">
|
||||
<description>Networking Core</description>
|
||||
<files>
|
||||
<file category="doc" name="README.md"/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION = 7.23.2
|
||||
VERSION = 7.23.3
|
||||
REPO_ROOT = ../..
|
||||
MX ?= /Applications/STMicroelectronics/STM32CubeMX.app/Contents/MacOs/STM32CubeMX
|
||||
FILES = Cesanta.I-CUBE-Mongoose.pdsc Release_Notes.html mongoose_config.h README.md .config/mongoose_parameters.json
|
||||
|
||||
+5
-64
@@ -32,6 +32,7 @@
|
||||
|
||||
#if MG_ENABLE_TCPIP && !defined(MG_ENABLE_DRIVER_STM32F) && \
|
||||
!defined(MG_ENABLE_DRIVER_STM32H) && !defined(MG_ENABLE_DRIVER_STM32N) && \
|
||||
!defined(MG_ENABLE_DRIVER_STM32C) && \
|
||||
!defined(MG_ENABLE_DRIVER_CYW) && !defined(MG_ENABLE_DRIVER_CYW_SDIO) && \
|
||||
!defined(MG_ENABLE_DRIVER_ST67W6)
|
||||
#if defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
|
||||
@@ -40,6 +41,8 @@
|
||||
#define MG_ENABLE_DRIVER_STM32H 1
|
||||
#elif defined(STM32N6)
|
||||
#define MG_ENABLE_DRIVER_STM32N 1
|
||||
#elif defined(STM32C5)
|
||||
#define MG_ENABLE_DRIVER_STM32C 1
|
||||
#else
|
||||
#error Select a driver in mongoose_config.h
|
||||
#endif
|
||||
@@ -56,70 +59,8 @@
|
||||
#define MG_OTA MG_OTA_STM32H5
|
||||
#elif !defined(MG_OTA) && defined(STM32H7)
|
||||
#define MG_OTA MG_OTA_STM32H7
|
||||
#endif
|
||||
|
||||
// OTA rollback timer via IWDG. Fixed 10 s hang-detection window (prescaler
|
||||
// /1024, LSI ~32 kHz: reload = 10 * 32000 / 1024 = 312). mg_ota_poll() feeds
|
||||
// the watchdog every 500 ms while in MG_OTA_TESTING state; if the event loop
|
||||
// hangs for 10 s, the IWDG fires and the device rolls back.
|
||||
// STM32H7 names the peripheral IWDG1; all others use IWDG.
|
||||
// The total evaluation period is set by MG_OTA_ROLLBACK_TIMEOUT_SECONDS.
|
||||
// STM32H7 names the watchdog peripheral IWDG1; all other families use IWDG.
|
||||
#if defined(IWDG1) && !defined(IWDG)
|
||||
#define MG_IWDG IWDG1
|
||||
#else
|
||||
#define MG_IWDG IWDG
|
||||
#endif
|
||||
// PR=6 → /256 prescaler, RLR=1250 → ~10 s at LSI 32 kHz.
|
||||
// Works on F4/F7/H5/H7; uses direct register writes so it is safe before HAL_Init().
|
||||
#ifndef MG_OTA_ROLLBACK_TIMER_START
|
||||
#define MG_OTA_ROLLBACK_TIMER_START() \
|
||||
do { \
|
||||
MG_IWDG->KR = 0xCCCCU; /* start + LSI */ \
|
||||
MG_IWDG->KR = 0x5555U; /* unlock PR/RLR */ \
|
||||
MG_IWDG->PR = 6U; /* /256 */ \
|
||||
MG_IWDG->RLR = 1250U; /* 10 s */ \
|
||||
while (MG_IWDG->SR & (IWDG_SR_PVU | IWDG_SR_RVU)) (void) 0; \
|
||||
MG_IWDG->KR = 0xAAAAU; /* reload */ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// Feed (reload) the IWDG. Called from mg_ota_poll() every 500 ms.
|
||||
#ifndef MG_OTA_ROLLBACK_TIMER_FEED
|
||||
#define MG_OTA_ROLLBACK_TIMER_FEED() (MG_IWDG->KR = 0xAAAAU)
|
||||
#endif
|
||||
|
||||
// OTA state in a backup register that survives warm resets but clears on POR.
|
||||
// STATE_GET reads work without any setup. STATE_SET enables the RTC APB clock
|
||||
// and unlocks backup domain write access via direct register writes, so it is
|
||||
// safe to call from any context (before or after HAL_Init).
|
||||
// H5 (TAMP->BKP0R), H7 (RTC->BKP0R), F4/F7 (RTC->BKP0R).
|
||||
#ifndef MG_OTA_STATE_GET
|
||||
#if defined(PWR_DBPCR_DBP)
|
||||
#define MG_OTA_DBP_ENABLE() (PWR->DBPCR |= PWR_DBPCR_DBP)
|
||||
#elif defined(PWR_CR1_DBP)
|
||||
#define MG_OTA_DBP_ENABLE() (PWR->CR1 |= PWR_CR1_DBP)
|
||||
#else
|
||||
#define MG_OTA_DBP_ENABLE() (PWR->CR |= PWR_CR_DBP)
|
||||
#endif
|
||||
|
||||
#if defined(TAMP)
|
||||
#define MG_OTA_STATE_GET() \
|
||||
(RCC->APB3ENR |= RCC_APB3ENR_RTCAPBEN, TAMP->BKP0R)
|
||||
#define MG_OTA_STATE_SET(v) \
|
||||
(RCC->APB3ENR |= RCC_APB3ENR_RTCAPBEN, MG_OTA_DBP_ENABLE(), \
|
||||
(TAMP->BKP0R = (uint32_t) (v)), TAMP->BKP0R)
|
||||
#elif defined(RCC_APB4ENR_RTCAPBEN)
|
||||
#define MG_OTA_STATE_GET() (RTC->BKP0R)
|
||||
#define MG_OTA_STATE_SET(v) \
|
||||
(RCC->APB4ENR |= RCC_APB4ENR_RTCAPBEN, MG_OTA_DBP_ENABLE(), \
|
||||
(RTC->BKP0R = (uint32_t) (v)))
|
||||
#else
|
||||
#define MG_OTA_STATE_GET() (RTC->BKP0R)
|
||||
#define MG_OTA_STATE_SET(v) \
|
||||
(RCC->APB1ENR |= RCC_APB1ENR_PWREN, MG_OTA_DBP_ENABLE(), \
|
||||
(RTC->BKP0R = (uint32_t) (v)))
|
||||
#endif
|
||||
#elif !defined(MG_OTA) && defined(STM32C5)
|
||||
#define MG_OTA MG_OTA_STM32C5
|
||||
#endif
|
||||
|
||||
// use HAL-defined execute-in-ram section
|
||||
|
||||
+3
-18
@@ -533,21 +533,6 @@ static void mg_dash_handle_add(struct mg_connection *c, struct mg_dash *dash,
|
||||
}
|
||||
}
|
||||
|
||||
// Firmware upload callback for mg_http_stream_body(). Uses *p as a flag:
|
||||
// non-NULL means an OTA session is open and must be closed by mg_ota_end()
|
||||
static bool otacb(struct mg_http_message *hm, struct mg_str *data, void **p) {
|
||||
if (hm != NULL) { // Start
|
||||
if (!mg_ota_begin(hm->body.len)) return false;
|
||||
*p = (void *) (ptrdiff_t) 1;
|
||||
return true;
|
||||
} else if (data != NULL) { // Next chunk
|
||||
return mg_ota_write(data->buf, data->len);
|
||||
}
|
||||
if (*p == NULL) return false; // End. Begin failed, nothing to finish
|
||||
*p = NULL;
|
||||
return mg_ota_end();
|
||||
}
|
||||
|
||||
static void mg_serve_fs(struct mg_connection *c, struct mg_http_message *hm,
|
||||
struct mg_dash_user *u, bool stream) {
|
||||
struct mg_dash *dash = (struct mg_dash *) c->fn_data;
|
||||
@@ -594,9 +579,9 @@ void mg_dash_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
mg_serve_fs(c, hm, u, true);
|
||||
return; // Important - the serve_fs() call can invalidate hm
|
||||
} else if (mg_match(hm->uri, mg_str("/api/ota"), NULL)) {
|
||||
// Authenticated above. If streaming started, the stream handler owns
|
||||
// the connection and c->data, so skip the marker check below
|
||||
if (mg_http_stream_body(c, hm, otacb, NULL)) return;
|
||||
// Authenticated above. Streaming owns the connection and c->data.
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
return;
|
||||
}
|
||||
if (d->marker != '\0') mg_log_http_req(c, hm);
|
||||
} else if (ev == MG_EV_HTTP_MSG && d->marker != '\0') {
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "net_builtin.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_MCXW71) && \
|
||||
MG_ENABLE_DRIVER_MCXW71
|
||||
|
||||
// ZLL, 802.15.4 link layer. See MCXW71 reference manual and NXP
|
||||
// ieee_802_15_4 PHY sources: PhyPacketProcessor.c, PhyPlmeData.c, PhyISR.c
|
||||
struct mg_zll {
|
||||
volatile uint32_t IRQSTS, PHY_CTRL, EVENT_TMR, TIMESTAMP, T1CMP, T2CMP,
|
||||
T2PRIMECMP, T3CMP, T4CMP, PA_PWR, CHANNEL_NUM0, LQI_AND_RSSI,
|
||||
MACSHORTADDRS0, MACLONGADDRS0_LSB, MACLONGADDRS0_MSB, RX_FRAME_FILTER,
|
||||
CCA_LQI_CTRL, CCA2_CTRL, RESERVED_0, DSM_CTRL, RESERVED_1,
|
||||
MACSHORTADDRS1, MACLONGADDRS1_LSB, MACLONGADDRS1_MSB, DUAL_PAN_CTRL,
|
||||
CHANNEL_NUM1, SAM_CTRL, SAM_TABLE, SAM_MATCH, SAM_FREE_IDX,
|
||||
SEQ_CTRL_STS, ACKDELAY, FILTERFAIL_CODE, RX_WTR_MARK, RESERVED_2,
|
||||
SLOT_PRELOAD, SEQ_STATE, TMR_PRESCALE, LENIENCY_LSB, LENIENCY_MSB,
|
||||
PART_ID, COEX_CTRL, COEX_PRIORITY, ENHACK_CTRL0;
|
||||
};
|
||||
|
||||
// TrustZone: code built for the secure state (-mcmse) uses the secure alias
|
||||
// of the radio registers, 0x5xxxxxxx. Otherwise, the non-secure alias
|
||||
#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE & 2)
|
||||
#define MGI_ZLL ((struct mg_zll *) 0x58A01000)
|
||||
#define MGI_PKT_RAM ((volatile uint8_t *) 0x58A08000)
|
||||
#else
|
||||
#define MGI_ZLL ((struct mg_zll *) 0x48A01000)
|
||||
#define MGI_PKT_RAM ((volatile uint8_t *) 0x48A08000)
|
||||
#endif
|
||||
|
||||
#define MGI_TX_PB MGI_PKT_RAM // Length byte (incl. FCS), then frame
|
||||
#define MGI_RX_PB (MGI_PKT_RAM + 0x80) // Received frame, no length byte
|
||||
|
||||
#define MGI_IRQSTS_SEQIRQ MG_BIT(0)
|
||||
#define MGI_IRQSTS_RXIRQ MG_BIT(2)
|
||||
#define MGI_IRQSTS_RX_LEN(x) (((x) >> 24) & 0x7f) // Frame length incl. FCS
|
||||
#define MGI_PHY_CTRL_XCVSEQ 7U
|
||||
#define MGI_PHY_CTRL_ALL_IRQ_MASKS 0x8007ff00U // Bits 8..18, 31: mask all IRQs
|
||||
#define MGI_SEQ_STATE_MASK 0x1fU
|
||||
#define MGI_SEQ_STATE_RX_WU 0x10U // RX warm up
|
||||
#define MGI_SEQ_CTRL_NO_RX_RECYCLE MG_BIT(5)
|
||||
#define MGI_FRAME_FILTER 0x70bU // Beacon, data, command; versions 0..2
|
||||
|
||||
enum { MGI_SEQ_IDLE = 0, MGI_SEQ_RX = 1, MGI_SEQ_TX = 2 }; // PHY_CTRL[XCVSEQ]
|
||||
#define MGI_TX_TIMEOUT 400U // Symbols, 16 us: 127 bytes
|
||||
|
||||
// Symbol timer, 16 us, 24 bits
|
||||
static uint32_t mg_mcxw71_symbols(void) {
|
||||
return MGI_ZLL->EVENT_TMR >> 8;
|
||||
}
|
||||
|
||||
// Wait for the sequence to end, up to MGI_TX_TIMEOUT symbols
|
||||
static bool mg_mcxw71_wait(void) {
|
||||
uint32_t start = mg_mcxw71_symbols();
|
||||
while (((mg_mcxw71_symbols() - start) & 0xffffffU) < MGI_TX_TIMEOUT) {
|
||||
if (MGI_ZLL->IRQSTS & MGI_IRQSTS_SEQIRQ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop the current sequence, wait for the sequencer to go idle. See PhyAbort()
|
||||
static void mg_mcxw71_idle(void) {
|
||||
if (MGI_ZLL->PHY_CTRL & MGI_PHY_CTRL_XCVSEQ) {
|
||||
while ((MGI_ZLL->SEQ_STATE & MGI_SEQ_STATE_MASK) == MGI_SEQ_STATE_RX_WU)
|
||||
(void) 0;
|
||||
MGI_ZLL->PHY_CTRL &= ~MGI_PHY_CTRL_XCVSEQ;
|
||||
while (MGI_ZLL->SEQ_STATE & MGI_SEQ_STATE_MASK) (void) 0;
|
||||
}
|
||||
MGI_ZLL->IRQSTS = MGI_ZLL->IRQSTS; // Clear all flags, write 1 to clear
|
||||
}
|
||||
|
||||
// Start a new sequence: MGI_SEQ_RX or MGI_SEQ_TX
|
||||
static void mg_mcxw71_start(uint32_t seq) {
|
||||
MGI_ZLL->IRQSTS = MGI_ZLL->IRQSTS;
|
||||
MGI_ZLL->PHY_CTRL |= seq;
|
||||
}
|
||||
|
||||
static bool mg_mcxw71_init(struct mg_tcpip_if *ifp) {
|
||||
struct mg_l2_802154_data *d =
|
||||
(struct mg_l2_802154_data *) ifp->driver_data;
|
||||
if (d == NULL || d->channel < 11 || d->channel > 26) {
|
||||
MG_ERROR(("Set driver_data, channel 11..26"));
|
||||
return false;
|
||||
}
|
||||
MGI_ZLL->SEQ_CTRL_STS |= MGI_SEQ_CTRL_NO_RX_RECYCLE;
|
||||
MGI_ZLL->PHY_CTRL = MGI_PHY_CTRL_ALL_IRQ_MASKS; // Mask all IRQs, we poll
|
||||
MGI_ZLL->IRQSTS = MGI_ZLL->IRQSTS;
|
||||
MGI_ZLL->SAM_CTRL = 0;
|
||||
MGI_ZLL->RX_FRAME_FILTER = MGI_FRAME_FILTER;
|
||||
MGI_ZLL->TMR_PRESCALE = 5; // 16 us timebase, one symbol
|
||||
MGI_ZLL->CHANNEL_NUM0 = d->channel;
|
||||
MGI_ZLL->MACSHORTADDRS0 = (0xfffeU << 16) | d->pan_id; // Filter by PAN ID
|
||||
MGI_ZLL->PA_PWR = 0x3f; // PA slices, max output power
|
||||
mg_mcxw71_start(MGI_SEQ_RX);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send one radio frame: MAC header and payload, no FCS
|
||||
static size_t mg_mcxw71_send(const uint8_t *p, size_t len,
|
||||
struct mg_tcpip_if *ifp) {
|
||||
size_t i;
|
||||
bool ok;
|
||||
mg_mcxw71_idle();
|
||||
MGI_TX_PB[0] = (uint8_t) (len + 2); // FCS is added by hardware
|
||||
for (i = 0; i < len; i++) MGI_TX_PB[i + 1] = p[i]; // 8-bit access only
|
||||
mg_mcxw71_start(MGI_SEQ_TX);
|
||||
ok = mg_mcxw71_wait();
|
||||
mg_mcxw71_idle();
|
||||
mg_mcxw71_start(MGI_SEQ_RX);
|
||||
(void) ifp;
|
||||
return ok ? len : 0;
|
||||
}
|
||||
|
||||
static size_t mg_mcxw71_tx(const void *buf, size_t len,
|
||||
struct mg_tcpip_if *ifp) {
|
||||
return mg_l2_802154_tx(ifp, buf, len, mg_mcxw71_send);
|
||||
}
|
||||
|
||||
static size_t mg_mcxw71_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||
uint32_t irqsts = MGI_ZLL->IRQSTS;
|
||||
uint8_t f[125];
|
||||
size_t i, n = 0;
|
||||
if ((irqsts & MGI_IRQSTS_SEQIRQ) == 0) return 0; // Still receiving
|
||||
if (irqsts & MGI_IRQSTS_RXIRQ) {
|
||||
n = MGI_IRQSTS_RX_LEN(irqsts);
|
||||
n = n >= 2 ? n - 2 : 0; // Strip FCS
|
||||
if (n > sizeof(f)) n = sizeof(f);
|
||||
for (i = 0; i < n; i++) f[i] = MGI_RX_PB[i];
|
||||
}
|
||||
mg_mcxw71_idle();
|
||||
mg_mcxw71_start(MGI_SEQ_RX);
|
||||
return mg_l2_802154_rx(ifp, f, n, buf, len);
|
||||
}
|
||||
|
||||
static bool mg_mcxw71_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
(void) ifp, (void) s1;
|
||||
return true; // Radio link is always up
|
||||
}
|
||||
|
||||
struct mg_tcpip_driver mg_tcpip_driver_mcxw71 = {mg_mcxw71_init, mg_mcxw71_tx,
|
||||
mg_mcxw71_rx, mg_mcxw71_poll};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_MCXW71) && \
|
||||
MG_ENABLE_DRIVER_MCXW71
|
||||
|
||||
// NXP MCXW71 IEEE 802.15.4 radio, ZLL link layer, as an Ethernet interface:
|
||||
// Ethernet frames are split into radio frames, see mg_l2_802154_tx().
|
||||
// The transceiver (XCVR) must be set up for 802.15.4 before mg_tcpip_init(),
|
||||
// see hal_radio_init() in the FRDM-MCXW71 tutorial.
|
||||
// driver_data: struct mg_l2_802154_data, channel and PAN ID set
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_l2_802154_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.channel = MG_L2_802154_CHANNEL; \
|
||||
driver_data_.pan_id = MG_L2_802154_PAN_ID; \
|
||||
mif_.driver = &mg_tcpip_driver_mcxw71; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: mcxw71, channel %d", MG_L2_802154_CHANNEL)); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,450 @@
|
||||
#include "net_builtin.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RW612_154) && \
|
||||
MG_ENABLE_DRIVER_RW612_154
|
||||
|
||||
// The 802.15.4 radio runs NXP combo firmware on CPU2, an OpenThread RCP. We
|
||||
// are CPU3. Messages go through the IMU mailbox: IMU messages carry IMUMC
|
||||
// messages, IMUMC messages carry HDLC framed Spinel. See NXP sources:
|
||||
// mcuxsdk-core drivers/imu/fsl_imu.c, mcux-component
|
||||
// imu_adapter/fsl_adapter_imu.c, connectivity framework
|
||||
// platform/rw61x/fwk_platform_hdlc.c; OpenThread src/lib/spinel/spinel.h
|
||||
|
||||
// IMU message FIFO registers, one block per direction. See fsl_imu.h
|
||||
struct mg_rw612_imu {
|
||||
volatile uint32_t WR_MSG, RD_MSG, STATUS, CNTL, RD_MSG_DBG;
|
||||
};
|
||||
#define MGI_IMU ((struct mg_rw612_imu *) 0x443ff804) // CPU3 -> CPU2
|
||||
#define MGI_IMU_PEER ((struct mg_rw612_imu *) 0x443ff818) // CPU2 -> CPU3
|
||||
#define MGI_IMU_LOCKED MG_BIT(0) // STATUS: FIFO locked
|
||||
#define MGI_IMU_ALMOST_FULL MG_BIT(1) // STATUS: FIFO almost full
|
||||
#define MGI_IMU_EMPTY MG_BIT(3) // STATUS: FIFO empty
|
||||
#define MGI_IMU_WR_PTR(s) (((s) >> 16) & 15U)
|
||||
#define MGI_IMU_INT_CLR MG_BIT(0) // CNTL: clear message ready IRQ
|
||||
#define MGI_IMU_FLUSH MG_BIT(16) // CNTL: flush send FIFO
|
||||
#define MGI_IMU_WAIT_FOR_ACK MG_BIT(17) // CNTL: lock send FIFO
|
||||
#define MGI_IMU_WATERMARK(x) ((uint32_t) (x) << 20)
|
||||
#define MGI_IMU_WATERMARK_MASK (15U << 20)
|
||||
|
||||
// IMU message: header, then payload words. See IMU_Msg_t
|
||||
struct mg_rw612_msg {
|
||||
uint8_t type, subtype, seq, len; // len: number of payload words
|
||||
uint32_t payload[8];
|
||||
};
|
||||
|
||||
// Mailbox in SMU2 shared memory, at the address CPU2 firmware expects
|
||||
struct mg_rw612_mbox {
|
||||
uint32_t magic[2]; // Sync pattern: [0] CPU2, [1] us
|
||||
struct mg_rw612_msg q[2][16]; // Message slots: [0] CPU2 -> us, [1] ours
|
||||
};
|
||||
#define MGI_MBOX ((volatile struct mg_rw612_mbox *) 0x443c0000)
|
||||
#define MGI_TXBUF 0x443c1508U // Our IMUMC buffers: 16 x 264 bytes
|
||||
#define MGI_TXBUF_CNT 16
|
||||
#define MGI_TXBUF_LEN 264U
|
||||
#define MGI_SLEEP_FLAG (*(volatile uint32_t *) 0x443c2588)
|
||||
#define MGI_SYNC_MAGIC 0xabcdef89U
|
||||
|
||||
// IMUMC message, carried in IMU payload words. See imumc_std_msg
|
||||
struct mg_rw612_imumc {
|
||||
uint32_t src, dst; // Endpoint addresses
|
||||
uint16_t rfu, idx; // Reserved
|
||||
uint16_t len; // Payload length, bytes
|
||||
uint16_t flags; // Message flags
|
||||
uint32_t data; // Payload buffer address
|
||||
};
|
||||
#define MGI_EPT_LOCAL 10 // Our 802.15.4 endpoint
|
||||
#define MGI_EPT_REMOTE 20 // Firmware 802.15.4 endpoint
|
||||
|
||||
enum { MGI_MSG_CONTROL = 0, MGI_MSG_IMUMC = 8 }; // IMU message types
|
||||
enum { // Control message subtypes
|
||||
MGI_CTL_SYNC = 1,
|
||||
MGI_CTL_SYNC_ACK = 2,
|
||||
MGI_CTL_ACK_FOR_UNLOCK = 3,
|
||||
MGI_CTL_CMD_BUF_ADDR = 6,
|
||||
MGI_CTL_EPT_QUERY = 11,
|
||||
MGI_CTL_EPT_QUERY_RSP = 12,
|
||||
MGI_CTL_BUF_FREE = 13
|
||||
};
|
||||
|
||||
// Spinel commands, properties and statuses we use
|
||||
enum { MGI_CMD_RESET = 1, MGI_CMD_GET = 2, MGI_CMD_SET = 3, MGI_CMD_IS = 6 };
|
||||
enum {
|
||||
MGI_PROP_LAST_STATUS = 0,
|
||||
MGI_PROP_NCP_VERSION = 2,
|
||||
MGI_PROP_PHY_ENABLED = 0x20,
|
||||
MGI_PROP_PHY_CHAN = 0x21,
|
||||
MGI_PROP_PANID = 0x36,
|
||||
MGI_PROP_RAW_STREAM = 0x37,
|
||||
MGI_PROP_STREAM_RAW = 0x71
|
||||
};
|
||||
#define MGI_RESET_STACK 2 // RESET argument: reset the RCP stack only
|
||||
#define MGI_STATUS_RESET_MIN 112 // LAST_STATUS: RCP has reset
|
||||
#define MGI_STATUS_RESET_MAX 127
|
||||
#define MGI_TX_TIMEOUT_MS 200 // Wait for transmit done, incl. retries
|
||||
#define MGI_RSP_TIMEOUT_MS 500
|
||||
#define MGI_RXQ_CNT 16 // A whole Ethernet frame, 15 radio frames
|
||||
|
||||
// Driver state, one radio
|
||||
struct mg_rw612 {
|
||||
bool up; // IMU link synchronised
|
||||
bool ept_ready; // IMUMC endpoints connected
|
||||
bool reset; // RCP reported a reset
|
||||
uint8_t seq; // IMU message sequence number
|
||||
uint16_t free_bufs; // Free IMUMC buffers, bit per buffer
|
||||
uint8_t hdlc[300]; // HDLC frame being received, unescaped
|
||||
size_t hlen; // Bytes in hdlc
|
||||
bool esc; // Previous byte was an escape
|
||||
uint8_t tid; // Spinel transaction ID of the pending request
|
||||
bool rsp; // Response to the pending request received
|
||||
uint32_t rsp_status; // Its status, if LAST_STATUS, else 0
|
||||
char version[64]; // RCP version string
|
||||
uint8_t rxq[MGI_RXQ_CNT][127]; // Received frames, no FCS
|
||||
uint8_t rxlen[MGI_RXQ_CNT]; // Their lengths
|
||||
uint8_t rxhead, rxtail; // Queue indexes
|
||||
};
|
||||
static struct mg_rw612 s_rw612;
|
||||
|
||||
static void mg_rw612_imu_send(uint8_t type, uint8_t subtype,
|
||||
const uint32_t *payload, uint8_t len) {
|
||||
volatile struct mg_rw612_msg *m;
|
||||
uint64_t expire = mg_millis() + 100;
|
||||
uint8_t i;
|
||||
while ((MGI_IMU->STATUS & (MGI_IMU_ALMOST_FULL | MGI_IMU_LOCKED)) &&
|
||||
mg_millis() < expire) {
|
||||
(void) 0;
|
||||
}
|
||||
m = &MGI_MBOX->q[1][MGI_IMU_WR_PTR(MGI_IMU->STATUS)];
|
||||
m->type = type, m->subtype = subtype, m->seq = s_rw612.seq++, m->len = len;
|
||||
for (i = 0; i < len; i++) m->payload[i] = payload[i];
|
||||
MGI_IMU->WR_MSG = (uint32_t) (uintptr_t) m;
|
||||
}
|
||||
|
||||
static void mg_rw612_control(uint8_t subtype, uint32_t a, uint32_t b,
|
||||
uint8_t len) {
|
||||
uint32_t payload[2] = {a, b};
|
||||
mg_rw612_imu_send(MGI_MSG_CONTROL, subtype, payload, len);
|
||||
}
|
||||
|
||||
static void mg_rw612_queue_rx(const uint8_t *frame, size_t len) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
uint8_t next = (uint8_t) ((s->rxhead + 1) % MGI_RXQ_CNT);
|
||||
if (next == s->rxtail || len > sizeof(s->rxq[0])) return; // Full: drop
|
||||
memcpy(s->rxq[s->rxhead], frame, len);
|
||||
s->rxlen[s->rxhead] = (uint8_t) len;
|
||||
s->rxhead = next;
|
||||
}
|
||||
|
||||
// Spinel packed unsigned integer: 7 bits per byte, LSB first
|
||||
static size_t mg_rw612_unpack(const uint8_t *p, size_t len, uint32_t *v) {
|
||||
size_t i;
|
||||
*v = 0;
|
||||
for (i = 0; i < len && i < 4; i++) {
|
||||
*v |= (uint32_t) (p[i] & 0x7f) << (7 * i);
|
||||
if ((p[i] & 0x80) == 0) return i + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle a received Spinel frame: header, command, property, value
|
||||
static void mg_rw612_spinel(const uint8_t *f, size_t len) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
uint32_t cmd, prop, status = 0;
|
||||
size_t n, ofs = 1;
|
||||
uint8_t tid = f[0] & 15;
|
||||
if (len < 3 || (n = mg_rw612_unpack(f + ofs, len - ofs, &cmd)) == 0) return;
|
||||
ofs += n;
|
||||
if ((n = mg_rw612_unpack(f + ofs, len - ofs, &prop)) == 0) return;
|
||||
ofs += n;
|
||||
if (cmd != MGI_CMD_IS) return;
|
||||
if (prop == MGI_PROP_STREAM_RAW && tid == 0 && len - ofs >= 2) {
|
||||
size_t flen = (size_t) (f[ofs] | (f[ofs + 1] << 8)); // Incl. FCS
|
||||
if (flen >= 2 && ofs + 2 + flen <= len) {
|
||||
mg_rw612_queue_rx(f + ofs + 2, flen - 2);
|
||||
}
|
||||
} else if (prop == MGI_PROP_LAST_STATUS) {
|
||||
mg_rw612_unpack(f + ofs, len - ofs, &status);
|
||||
if (tid == 0 && status >= MGI_STATUS_RESET_MIN &&
|
||||
status <= MGI_STATUS_RESET_MAX) {
|
||||
s->reset = true;
|
||||
}
|
||||
} else if (prop == MGI_PROP_NCP_VERSION) {
|
||||
n = len - ofs < sizeof(s->version) - 1 ? len - ofs : sizeof(s->version) - 1;
|
||||
memcpy(s->version, f + ofs, n);
|
||||
s->version[n] = '\0';
|
||||
}
|
||||
if (tid != 0 && tid == s->tid) s->rsp = true, s->rsp_status = status;
|
||||
}
|
||||
|
||||
// HDLC-lite: 0x7e delimits frames, 0x7d escapes, FCS-16 at the end
|
||||
static uint16_t mg_rw612_fcs(uint16_t fcs, uint8_t c) {
|
||||
int i;
|
||||
fcs ^= c;
|
||||
for (i = 0; i < 8; i++) fcs = (fcs & 1) ? (fcs >> 1) ^ 0x8408 : fcs >> 1;
|
||||
return fcs;
|
||||
}
|
||||
|
||||
static void mg_rw612_hdlc_rx(const uint8_t *p, size_t len) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
size_t i, j;
|
||||
for (i = 0; i < len; i++) {
|
||||
uint8_t c = p[i];
|
||||
if (c == 0x7e) {
|
||||
if (s->hlen >= 3) {
|
||||
uint16_t fcs = 0xffff;
|
||||
for (j = 0; j < s->hlen; j++) fcs = mg_rw612_fcs(fcs, s->hdlc[j]);
|
||||
if (fcs == 0xf0b8) mg_rw612_spinel(s->hdlc, s->hlen - 2);
|
||||
}
|
||||
s->hlen = 0, s->esc = false;
|
||||
} else if (c == 0x7d) {
|
||||
s->esc = true;
|
||||
} else if (s->hlen < sizeof(s->hdlc)) {
|
||||
s->hdlc[s->hlen++] = s->esc ? c ^ 0x20 : c;
|
||||
s->esc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mg_rw612_control_rx(volatile struct mg_rw612_msg *m) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
switch (m->subtype) {
|
||||
case MGI_CTL_ACK_FOR_UNLOCK:
|
||||
MGI_IMU->CNTL &= ~MGI_IMU_WAIT_FOR_ACK;
|
||||
break;
|
||||
case MGI_CTL_SYNC: // As HAL_ImuCtrlHandler(): acknowledge twice
|
||||
mg_rw612_control(MGI_CTL_SYNC_ACK, 0, 0, 0);
|
||||
mg_rw612_control(MGI_CTL_SYNC_ACK, 0, 0, 0);
|
||||
s->up = true;
|
||||
break;
|
||||
case MGI_CTL_SYNC_ACK:
|
||||
case MGI_CTL_CMD_BUF_ADDR:
|
||||
s->up = true;
|
||||
break;
|
||||
case MGI_CTL_EPT_QUERY: { // Firmware asks if our endpoint exists
|
||||
bool ours = m->payload[0] == MGI_EPT_LOCAL;
|
||||
mg_rw612_control(MGI_CTL_EPT_QUERY_RSP, m->payload[0], ours, 2);
|
||||
if (ours) s->ept_ready = true;
|
||||
break;
|
||||
}
|
||||
case MGI_CTL_EPT_QUERY_RSP:
|
||||
if (m->payload[0] == MGI_EPT_REMOTE && m->payload[1] != 0) {
|
||||
s->ept_ready = true;
|
||||
}
|
||||
break;
|
||||
case MGI_CTL_BUF_FREE: { // Firmware is done with one of our buffers
|
||||
uint32_t i = (m->payload[0] - MGI_TXBUF) / MGI_TXBUF_LEN;
|
||||
if (i < MGI_TXBUF_CNT) s->free_bufs |= (uint16_t) MG_BIT(i);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Process all received IMU messages. See HAL_ImuReceive()
|
||||
static void mg_rw612_poll_imu(void) {
|
||||
bool unlock = false;
|
||||
while ((MGI_IMU_PEER->STATUS & MGI_IMU_EMPTY) == 0) {
|
||||
struct mg_rw612_msg m;
|
||||
volatile struct mg_rw612_msg *p;
|
||||
uint8_t i;
|
||||
MGI_SLEEP_FLAG &= ~1U;
|
||||
p = (volatile struct mg_rw612_msg *) (uintptr_t) MGI_IMU->RD_MSG;
|
||||
if (MGI_IMU_PEER->STATUS & MGI_IMU_LOCKED) unlock = true;
|
||||
if (p == NULL) continue;
|
||||
m.type = p->type, m.subtype = p->subtype, m.len = p->len;
|
||||
for (i = 0; i < 8; i++) m.payload[i] = p->payload[i];
|
||||
if (m.type == MGI_MSG_CONTROL) {
|
||||
mg_rw612_control_rx(&m);
|
||||
} else if (m.type == MGI_MSG_IMUMC) {
|
||||
struct mg_rw612_imumc im;
|
||||
memcpy(&im, m.payload, sizeof(im));
|
||||
if (im.dst == MGI_EPT_LOCAL) {
|
||||
mg_rw612_hdlc_rx((const uint8_t *) (uintptr_t) im.data, im.len);
|
||||
}
|
||||
mg_rw612_control(MGI_CTL_BUF_FREE, im.data, 0, 1);
|
||||
}
|
||||
}
|
||||
MGI_IMU->CNTL |= MGI_IMU_INT_CLR;
|
||||
MGI_SLEEP_FLAG |= 1U;
|
||||
if (unlock) mg_rw612_control(MGI_CTL_ACK_FOR_UNLOCK, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Send bytes to the firmware endpoint, in IMUMC buffer sized chunks
|
||||
static bool mg_rw612_imumc_send(const uint8_t *p, size_t len) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
while (len > 0) {
|
||||
size_t n = len < MGI_TXBUF_LEN ? len : MGI_TXBUF_LEN;
|
||||
uint64_t expire = mg_millis() + 100;
|
||||
struct mg_rw612_imumc im;
|
||||
uint32_t i;
|
||||
while (s->free_bufs == 0) {
|
||||
mg_rw612_poll_imu();
|
||||
if (mg_millis() > expire) return false;
|
||||
}
|
||||
for (i = 0; (s->free_bufs & MG_BIT(i)) == 0; i++) (void) 0;
|
||||
s->free_bufs &= (uint16_t) ~MG_BIT(i);
|
||||
memset(&im, 0, sizeof(im));
|
||||
im.src = MGI_EPT_LOCAL, im.dst = MGI_EPT_REMOTE, im.len = (uint16_t) n;
|
||||
im.data = MGI_TXBUF + i * MGI_TXBUF_LEN;
|
||||
memcpy((void *) (uintptr_t) im.data, p, n);
|
||||
mg_rw612_imu_send(MGI_MSG_IMUMC, 0, (uint32_t *) &im, sizeof(im) / 4);
|
||||
p += n, len -= n;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send a Spinel frame, HDLC encoded, and wait for the response with the
|
||||
// same transaction ID. Return false on timeout
|
||||
static bool mg_rw612_request(uint8_t *f, size_t len, uint32_t timeout_ms) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
uint8_t buf[2 * 160 + 6];
|
||||
uint16_t fcs = 0xffff;
|
||||
size_t i, n = 0;
|
||||
uint64_t expire = mg_millis() + timeout_ms;
|
||||
s->tid = (uint8_t) (s->tid % 15 + 1);
|
||||
f[0] = (uint8_t) (0x80 | s->tid); // Header: flag, interface 0, TID
|
||||
s->rsp = false;
|
||||
buf[n++] = 0x7e;
|
||||
for (i = 0; i < len + 2 && n + 3 < sizeof(buf); i++) {
|
||||
uint8_t c;
|
||||
if (i < len) {
|
||||
c = f[i], fcs = mg_rw612_fcs(fcs, c);
|
||||
} else {
|
||||
c = (uint8_t) (i == len ? ~fcs & 0xff : ~fcs >> 8);
|
||||
}
|
||||
if (c == 0x7e || c == 0x7d || c == 0x11 || c == 0x13 || c == 0xf8) {
|
||||
buf[n++] = 0x7d, c ^= 0x20;
|
||||
}
|
||||
buf[n++] = c;
|
||||
}
|
||||
buf[n++] = 0x7e;
|
||||
if (!mg_rw612_imumc_send(buf, n)) return false;
|
||||
while (!s->rsp && mg_millis() < expire) mg_rw612_poll_imu();
|
||||
return s->rsp;
|
||||
}
|
||||
|
||||
static bool mg_rw612_set(uint32_t prop, const uint8_t *val, size_t len) {
|
||||
uint8_t f[16];
|
||||
if (len > sizeof(f) - 3) return false;
|
||||
f[1] = MGI_CMD_SET, f[2] = (uint8_t) prop; // Properties used are < 0x80
|
||||
memcpy(f + 3, val, len);
|
||||
return mg_rw612_request(f, len + 3, MGI_RSP_TIMEOUT_MS) &&
|
||||
s_rw612.rsp_status == 0;
|
||||
}
|
||||
|
||||
// Log an init error, return false
|
||||
static bool mg_rw612_fail(const char *msg) {
|
||||
MG_ERROR(("%s", msg));
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mg_rw612_154_init(struct mg_tcpip_if *ifp) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
struct mg_l2_802154_data *d =
|
||||
(struct mg_l2_802154_data *) ifp->driver_data;
|
||||
uint8_t f[8], one = 1, pan[2];
|
||||
uint64_t expire;
|
||||
if (d == NULL || d->channel < 11 || d->channel > 26) {
|
||||
MG_ERROR(("Set driver_data, channel 11..26"));
|
||||
return false;
|
||||
}
|
||||
if (MGI_MBOX->magic[0] != MGI_SYNC_MAGIC) {
|
||||
MG_ERROR(("Radio firmware is not running on CPU2"));
|
||||
return false;
|
||||
}
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->free_bufs = 0xffff;
|
||||
// Reset our send FIFO, drop stale messages. See IMU_Init()
|
||||
MGI_IMU->CNTL |= MGI_IMU_FLUSH;
|
||||
MGI_IMU->CNTL &= ~(MGI_IMU_FLUSH | MGI_IMU_WAIT_FOR_ACK);
|
||||
MGI_IMU->CNTL = (MGI_IMU->CNTL & ~MGI_IMU_WATERMARK_MASK) |
|
||||
MGI_IMU_WATERMARK(15);
|
||||
while ((MGI_IMU_PEER->STATUS & MGI_IMU_EMPTY) == 0) (void) MGI_IMU->RD_MSG;
|
||||
// Synchronise the IMU link, then connect the IMUMC endpoints
|
||||
MGI_MBOX->magic[1] = MGI_SYNC_MAGIC;
|
||||
mg_rw612_control(MGI_CTL_SYNC, 0, 0, 0);
|
||||
expire = mg_millis() + 1000;
|
||||
while (!s->up && mg_millis() < expire) mg_rw612_poll_imu();
|
||||
if (!s->up) return mg_rw612_fail("IMU sync timeout");
|
||||
expire = mg_millis() + 2000;
|
||||
while (!s->ept_ready && mg_millis() < expire) {
|
||||
uint64_t retry = mg_millis() + 100;
|
||||
mg_rw612_control(MGI_CTL_EPT_QUERY, MGI_EPT_REMOTE, 0, 1);
|
||||
while (!s->ept_ready && mg_millis() < retry) mg_rw612_poll_imu();
|
||||
}
|
||||
if (!s->ept_ready) return mg_rw612_fail("IMUMC endpoint timeout");
|
||||
// Reset the RCP stack, wait for its reset status, read its version
|
||||
f[1] = MGI_CMD_RESET, f[2] = MGI_RESET_STACK;
|
||||
mg_rw612_request(f, 3, MGI_RSP_TIMEOUT_MS);
|
||||
expire = mg_millis() + 1000;
|
||||
while (!s->reset && mg_millis() < expire) mg_rw612_poll_imu();
|
||||
if (!s->reset) return mg_rw612_fail("RCP reset timeout");
|
||||
f[1] = MGI_CMD_GET, f[2] = MGI_PROP_NCP_VERSION;
|
||||
mg_rw612_request(f, 3, MGI_RSP_TIMEOUT_MS);
|
||||
MG_INFO(("RCP: %s", s->version));
|
||||
if (!mg_rw612_set(MGI_PROP_PHY_ENABLED, &one, 1)) {
|
||||
return mg_rw612_fail("PHY enable failed");
|
||||
}
|
||||
pan[0] = (uint8_t) d->pan_id, pan[1] = (uint8_t) (d->pan_id >> 8);
|
||||
if (!mg_rw612_set(MGI_PROP_PHY_CHAN, &d->channel, 1) ||
|
||||
!mg_rw612_set(MGI_PROP_PANID, pan, 2)) {
|
||||
return mg_rw612_fail("Channel or PAN ID set failed");
|
||||
}
|
||||
if (!mg_rw612_set(MGI_PROP_RAW_STREAM, &one, 1)) {
|
||||
return mg_rw612_fail("Raw stream enable failed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send one radio frame: MAC header and payload, no FCS
|
||||
static size_t mg_rw612_send(const uint8_t *p, size_t len,
|
||||
struct mg_tcpip_if *ifp) {
|
||||
struct mg_l2_802154_data *d =
|
||||
(struct mg_l2_802154_data *) ifp->driver_data;
|
||||
uint8_t f[3 + 2 + 127 + 4];
|
||||
size_t n = 3;
|
||||
f[1] = MGI_CMD_SET, f[2] = MGI_PROP_STREAM_RAW;
|
||||
f[n++] = (uint8_t) (len + 2), f[n++] = 0; // PSDU length, incl. FCS
|
||||
memcpy(f + n, p, len), n += len;
|
||||
f[n++] = 0, f[n++] = 0; // FCS, filled in by the radio
|
||||
f[n++] = d->channel;
|
||||
f[n++] = 4; // Max CSMA backoffs
|
||||
f[n++] = 0; // Max frame retries: broadcast frames are not acknowledged
|
||||
f[n++] = 1; // CSMA-CA enabled
|
||||
if (!mg_rw612_request(f, n, MGI_TX_TIMEOUT_MS)) {
|
||||
MG_ERROR(("TX timeout"));
|
||||
return 0;
|
||||
}
|
||||
if (s_rw612.rsp_status != 0) {
|
||||
MG_VERBOSE(("TX failed, status %lu", (unsigned long) s_rw612.rsp_status));
|
||||
return 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t mg_rw612_154_tx(const void *buf, size_t len,
|
||||
struct mg_tcpip_if *ifp) {
|
||||
return mg_l2_802154_tx(ifp, buf, len, mg_rw612_send);
|
||||
}
|
||||
|
||||
static size_t mg_rw612_154_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||
struct mg_rw612 *s = &s_rw612;
|
||||
size_t res = 0;
|
||||
mg_rw612_poll_imu();
|
||||
while (s->rxtail != s->rxhead && res == 0) {
|
||||
res = mg_l2_802154_rx(ifp, s->rxq[s->rxtail], s->rxlen[s->rxtail], buf,
|
||||
len);
|
||||
s->rxtail = (uint8_t) ((s->rxtail + 1) % MGI_RXQ_CNT);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool mg_rw612_154_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
(void) ifp, (void) s1;
|
||||
return s_rw612.up;
|
||||
}
|
||||
|
||||
struct mg_tcpip_driver mg_tcpip_driver_rw612_154 = {
|
||||
mg_rw612_154_init, mg_rw612_154_tx, mg_rw612_154_rx, mg_rw612_154_poll};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RW612_154) && \
|
||||
MG_ENABLE_DRIVER_RW612_154
|
||||
|
||||
// NXP RW612 IEEE 802.15.4 radio, as an Ethernet interface: Ethernet frames
|
||||
// are split into radio frames, see mg_l2_802154_tx(). The radio runs on
|
||||
// CPU2: NXP BLE/802.15.4 combo firmware, an OpenThread radio co-processor
|
||||
// (RCP). The firmware must be loaded and running before mg_tcpip_init(), see
|
||||
// the FRDM-RW612 eth_radio_bridge tutorial. The driver talks to it over the
|
||||
// CPU2 <-> CPU3 IMU mailbox: IMUMC messages carrying HDLC framed Spinel.
|
||||
// driver_data: struct mg_l2_802154_data, channel and PAN ID set
|
||||
|
||||
#ifndef MG_TCPIP_DRIVER_INIT
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_l2_802154_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.channel = MG_L2_802154_CHANNEL; \
|
||||
driver_data_.pan_id = MG_L2_802154_PAN_ID; \
|
||||
mif_.driver = &mg_tcpip_driver_rw612_154; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: rw612_154, channel %d", MG_L2_802154_CHANNEL)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -365,7 +365,7 @@ static bool st67w6_init(uint8_t *mac) {
|
||||
}
|
||||
// set clock, who cares ???
|
||||
if (!st67w6_at_cmd("AT+GET_CLOCK\r\n", 14)) return false;
|
||||
MG_DEBUG(("%.*s", s_at_resp_len, at_resp)); // TODO(scaprile): --> VERBOSE
|
||||
MG_VERBOSE(("%.*s", s_at_resp_len, at_resp));
|
||||
// BT-ENABLED DEPENDENCY
|
||||
|
||||
// MODULE DEPENDENCY
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#if MG_ENABLE_TCPIP && (MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN || \
|
||||
MG_ENABLE_DRIVER_STM32N)
|
||||
// STM32C: vendor modded single-queue Synopsys v5.4, same settings as STM32H
|
||||
// STM32H: vendor modded single-queue Synopsys v4.2
|
||||
// STM32N: dual-queue GbE Synopsys v5.2 with no hash table option, 64-bit AXI
|
||||
// MCXNx4x: dual-queue Synopsys v5.2 with no hash table option
|
||||
@@ -310,7 +311,7 @@ static uint32_t s_rxno;
|
||||
#if MG_ENABLE_DRIVER_MCXN
|
||||
void ETHERNET_IRQHandler(void);
|
||||
void ETHERNET_IRQHandler(void) {
|
||||
#elif MG_ENABLE_DRIVER_STM32H
|
||||
#elif MG_ENABLE_DRIVER_STM32H && !MG_ENABLE_DRIVER_STM32C
|
||||
void ETH_IRQHandler(void);
|
||||
void ETH_IRQHandler(void) {
|
||||
#else
|
||||
@@ -339,8 +340,10 @@ void ETH1_IRQHandler(void) {
|
||||
}
|
||||
ETH->DMACSR =
|
||||
MG_BIT(7) | MG_BIT(8); // Clear possible RBU RPS while processing
|
||||
ETH->DMACRDTPR =
|
||||
(uint32_t) (uintptr_t) &s_rxdesc[ETH_DESC_CNT - 1]; // and resume RX
|
||||
// Resume RX: tail is the last descriptor given back to DMA. It must differ
|
||||
// from the DMA current descriptor, or some DMAs, e.g. STM32C5, stay suspended
|
||||
ETH->DMACRDTPR = (uint32_t) (uintptr_t) &s_rxdesc[(s_rxno + ETH_DESC_CNT - 1) %
|
||||
ETH_DESC_CNT];
|
||||
}
|
||||
|
||||
struct mg_tcpip_driver mg_tcpip_driver_stm32h = {
|
||||
|
||||
+11
-2
@@ -4,6 +4,13 @@
|
||||
#if !defined(MG_ENABLE_DRIVER_STM32H)
|
||||
#define MG_ENABLE_DRIVER_STM32H 0
|
||||
#endif
|
||||
#if !defined(MG_ENABLE_DRIVER_STM32C)
|
||||
#define MG_ENABLE_DRIVER_STM32C 0
|
||||
#endif
|
||||
#if MG_ENABLE_DRIVER_STM32C // STM32C5: STM32H5 MAC, the IRQ is ETH1
|
||||
#undef MG_ENABLE_DRIVER_STM32H
|
||||
#define MG_ENABLE_DRIVER_STM32H 1
|
||||
#endif
|
||||
#if !defined(MG_ENABLE_DRIVER_MCXN)
|
||||
#define MG_ENABLE_DRIVER_MCXN 0
|
||||
#endif
|
||||
@@ -43,9 +50,11 @@ struct mg_tcpip_driver_stm32h_data {
|
||||
#define MG_DRIVER_MDC_CR 4
|
||||
#endif
|
||||
|
||||
#if MG_ENABLE_DRIVER_STM32H && MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#if MG_ENABLE_DRIVER_STM32H && !MG_ENABLE_DRIVER_STM32C && \
|
||||
MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH_IRQn)
|
||||
#elif MG_ENABLE_DRIVER_STM32N && MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#elif (MG_ENABLE_DRIVER_STM32N || MG_ENABLE_DRIVER_STM32C) && \
|
||||
MG_ARCH == MG_ARCH_CUBE && !defined(MG_ENABLE_ETH_IRQ)
|
||||
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH1_IRQn)
|
||||
#elif !defined(MG_ENABLE_ETH_IRQ)
|
||||
#define MG_ENABLE_ETH_IRQ()
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
struct mg_health mg_health_record MG_HEALTH_RAM;
|
||||
|
||||
// STM32 H723 support. Needs the _estack symbol from the linker script
|
||||
#if MG_ENABLE_HEALTH && (defined(STM32H7_DEV_ID) || defined(STM32H5))
|
||||
#if MG_ENABLE_HEALTH && (defined(STM32H7_DEV_ID) || defined(STM32H5) || defined(STM32C5))
|
||||
// Fault handler body. Runs in exception context: no printf, no malloc, no
|
||||
// blocking calls. Copies the unwind registers and raw stack into the health
|
||||
// record, then resets.
|
||||
|
||||
+2
-19
@@ -5,32 +5,15 @@
|
||||
#include "arch.h"
|
||||
#include "printf.h"
|
||||
|
||||
// Memory usage in bytes. Override in mongoose_config.h for the target.
|
||||
#ifndef MG_HEALTH_STACK_USED
|
||||
#define MG_HEALTH_STACK_USED 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_STACK_TOTAL
|
||||
#define MG_HEALTH_STACK_TOTAL 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_HEAP_USED
|
||||
#define MG_HEALTH_HEAP_USED 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_HEAP_TOTAL
|
||||
#define MG_HEALTH_HEAP_TOTAL 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_HEALTH_MAGIC
|
||||
#define MG_HEALTH_MAGIC {'M', 'G', 'H', '3'} // '3' is the layout version
|
||||
#endif
|
||||
|
||||
#if !defined(MG_HEALTH_RAM) && (defined(STM32H7_DEV_ID) || defined(STM32H5))
|
||||
#if !defined(MG_HEALTH_RAM) && (defined(STM32H7_DEV_ID) || defined(STM32H5) || defined(STM32C5))
|
||||
#define MG_HEALTH_RAM __attribute__((section(".mg_health")))
|
||||
#endif
|
||||
|
||||
#if !defined(MG_HEALTH_DATA_SIZE) && (defined(STM32H7_DEV_ID) || defined(STM32H5))
|
||||
#if !defined(MG_HEALTH_DATA_SIZE) && (defined(STM32H7_DEV_ID) || defined(STM32H5) || defined(STM32C5))
|
||||
#define MG_HEALTH_DATA_SIZE 250
|
||||
#endif
|
||||
|
||||
|
||||
+43
-33
@@ -879,8 +879,8 @@ void mg_http_serve_upload(struct mg_connection *c, struct mg_http_message *hm,
|
||||
fs->rm(path); // MG_FS_WRITE appends, not truncates: drop any old file
|
||||
if ((fd = mg_fs_open(fs, path, MG_FS_WRITE)) == NULL) {
|
||||
MG_ERROR(("Cannot open %s for upload", path));
|
||||
} else if (!mg_http_stream_body(c, hm, serve_upload_cb, fd)) {
|
||||
mg_fs_close(fd);
|
||||
} else {
|
||||
mg_http_stream_body(c, hm, serve_upload_cb, fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1014,6 +1014,7 @@ struct mg_upload_state {
|
||||
size_t received; // Number of body bytes received so far
|
||||
void *user_data; // Passed to cb, free for cb to use
|
||||
bool failed; // Set when cb returned false
|
||||
bool finished; // End callback has been called
|
||||
};
|
||||
|
||||
// Event handler installed by mg_http_stream_body(). Feeds the body to the
|
||||
@@ -1021,18 +1022,18 @@ struct mg_upload_state {
|
||||
// handler: the connection is closed after the reply.
|
||||
static void mg_stream_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_upload_state *us = (struct mg_upload_state *) c->data;
|
||||
bool (*fn)(struct mg_http_message *, struct mg_str *, void **) =
|
||||
bool (*fn)(struct mg_http_message *, struct mg_str *, void **) =
|
||||
(bool (*)(struct mg_http_message *, struct mg_str *, void **))
|
||||
(ptrdiff_t) c->fn_data;
|
||||
(void) ev_data;
|
||||
if (ev == MG_EV_CLOSE || ev == MG_EV_ERROR) {
|
||||
if (us->received < us->expected) {
|
||||
if (!us->finished) {
|
||||
// Connection dropped mid-upload. Let cb clean up, e.g. call mg_ota_end()
|
||||
us->received = us->expected; // MG_EV_ERROR is followed by MG_EV_CLOSE
|
||||
us->finished = true; // MG_EV_ERROR is followed by MG_EV_CLOSE
|
||||
fn(NULL, NULL, &us->user_data);
|
||||
}
|
||||
} else if (ev == MG_EV_READ && !c->is_draining) {
|
||||
if (c->recv.len > 0 && us->received < us->expected) {
|
||||
} else if (ev == MG_EV_READ && !c->is_draining && !us->finished) {
|
||||
if (!us->failed && c->recv.len > 0 && us->received < us->expected) {
|
||||
// Got some uploaded data. Feed by 512-byte aligned chunks, for OTA
|
||||
size_t left = us->expected - us->received, r = c->recv.len;
|
||||
size_t aligned = r < left ? MG_ROUND_DOWN(r, 512) : left;
|
||||
@@ -1043,10 +1044,13 @@ static void mg_stream_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
us->received += aligned;
|
||||
mg_iobuf_del(&c->recv, 0, aligned); // Shift the unprocessed tail
|
||||
}
|
||||
if (us->received >= us->expected) {
|
||||
if (!us->finished && (us->failed || us->received >= us->expected)) {
|
||||
// Finished upload. Always call cb, even after error, so it can clean up
|
||||
us->finished = true;
|
||||
us->failed |= !fn(NULL, NULL, &us->user_data);
|
||||
if (!c->is_client) {
|
||||
if (c->is_client && us->failed) {
|
||||
mg_error(c, "Body streaming failed");
|
||||
} else if (!c->is_client) {
|
||||
mg_http_reply(c, us->failed ? 500 : 200, NULL, "%zu %s\n",
|
||||
us->received, us->failed ? "fail" : "ok");
|
||||
}
|
||||
@@ -1055,48 +1059,54 @@ static void mg_stream_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
}
|
||||
}
|
||||
|
||||
bool mg_http_stream_body(struct mg_connection *c, struct mg_http_message *hm,
|
||||
void mg_http_stream_body(struct mg_connection *c, struct mg_http_message *hm,
|
||||
bool (*cb)(struct mg_http_message *, struct mg_str *,
|
||||
void **user_data),
|
||||
void **),
|
||||
void *user_data) {
|
||||
struct mg_upload_state *us = (struct mg_upload_state *) c->data;
|
||||
struct mg_str *te = mg_http_get_header(hm, "Transfer-Encoding");
|
||||
bool handled = false;
|
||||
int code = 0;
|
||||
size_t head_len = hm->head.len;
|
||||
|
||||
// Catch upload requests early, without buffering whole body. Called on the
|
||||
// MG_EV_HTTP_HDRS event: we've received all HTTP headers but not necessarily
|
||||
// the full HTTP body
|
||||
if (hm->body.len == (size_t) ~0 ||
|
||||
(te != NULL && mg_strcasecmp(*te, mg_str("chunked")) == 0)) {
|
||||
// Unknown length or chunked, cannot stream. Leave it to the caller
|
||||
} else if (!c->is_client &&
|
||||
mg_strcmp(hm->method, mg_str("POST")) != 0 &&
|
||||
mg_strcmp(hm->method, mg_str("PUT")) != 0) {
|
||||
// Not an upload request. Leave it to the caller
|
||||
if (!c->is_client && mg_strcmp(hm->method, mg_str("POST")) != 0 &&
|
||||
mg_strcmp(hm->method, mg_str("PUT")) != 0) {
|
||||
code = 405;
|
||||
} else if (mg_http_get_header(hm, "Transfer-Encoding") != NULL) {
|
||||
code = 400;
|
||||
} else if (hm->body.len == (size_t) ~0 ||
|
||||
(!c->is_client && mg_http_get_header(hm, "Content-Length") == NULL)) {
|
||||
code = 411;
|
||||
} else if (sizeof(*us) > sizeof(c->data)) {
|
||||
if (!c->is_client) { // Nobody to reply to on a client connection
|
||||
c->pfn = NULL;
|
||||
mg_http_reply(c, 500, NULL, "data too small\n");
|
||||
c->is_draining = 1;
|
||||
cb(NULL, NULL, &user_data); // Let cb release user_data, start skipped
|
||||
handled = true;
|
||||
code = 500;
|
||||
}
|
||||
c->pfn = NULL; // Take ownership even when validation fails
|
||||
if (code != 0) {
|
||||
c->fn = NULL;
|
||||
c->fn_data = NULL;
|
||||
mg_iobuf_del(&c->recv, 0, c->recv.len);
|
||||
cb(NULL, NULL, &user_data); // Release resources even if start was skipped
|
||||
if (c->is_client) {
|
||||
mg_error(c, "%s", mg_http_status_code_str(code));
|
||||
} else {
|
||||
mg_http_reply(c, code, code == 405 ? "Allow: POST, PUT\r\n" : NULL, "");
|
||||
}
|
||||
c->is_draining = 1;
|
||||
} else {
|
||||
c->pfn = NULL; // Silence HTTP protocol handler
|
||||
memset(us, 0, sizeof(*us));
|
||||
us->expected = hm->body.len; // Store number of bytes we expect
|
||||
us->user_data = user_data;
|
||||
c->fn = mg_stream_handler;
|
||||
c->fn_data = (void *) (ptrdiff_t) cb;
|
||||
us->failed = !cb(hm, NULL, &us->user_data); // Call before deleting headers
|
||||
if (mg_http_get_header(hm, "Expect") != NULL) {
|
||||
if (!c->is_client && !us->failed && !us->finished &&
|
||||
mg_http_get_header(hm, "Expect") != NULL) {
|
||||
mg_http_reply(c, 100, NULL, ""); // If curl expects, we continue
|
||||
}
|
||||
mg_iobuf_del(&c->recv, 0, hm->head.len); // Delete HTTP headers
|
||||
c->fn = mg_stream_handler; // We own the connection from now
|
||||
c->fn_data = (void *) (ptrdiff_t) cb;
|
||||
mg_iobuf_del(&c->recv, 0, head_len); // Delete HTTP headers
|
||||
mg_call(c, MG_EV_READ, &c->recv.len); // Process the body bytes we have
|
||||
handled = true;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
static bool is_hex_digit(int c) {
|
||||
|
||||
+14
-11
@@ -205,29 +205,32 @@ int mg_http_status(const struct mg_http_message *hm);
|
||||
|
||||
// Streams a POST/PUT body to a callback as it arrives, without buffering it.
|
||||
// Call it from an MG_EV_HTTP_HDRS handler, after matching the request, e.g.
|
||||
// with mg_match(). Returns true if it took over the connection, false if the
|
||||
// request is not POST/PUT, is chunked, or has no Content-Length.
|
||||
// with mg_match(). Always takes over the connection. Invalid requests receive
|
||||
// an HTTP error; client-side failures call mg_error(). Replies and connection
|
||||
// draining are handled internally, including callback failures.
|
||||
//
|
||||
// Callback upload_fn(hm, data, user_data) is called:
|
||||
// - at start: hm is set. Open the file, set *user_data.
|
||||
// - per chunk: data is set, 512 byte aligned except the last. Not called
|
||||
// again after a failure.
|
||||
// - at end: both NULL. Always called once, also when the connection drops
|
||||
// early, so release resources here. A truncated body looks like a complete
|
||||
// one: validate before committing.
|
||||
// Return true on success, false on error.
|
||||
// - at end: both NULL. Always called exactly once, including validation
|
||||
// failures before start and connections that drop early. Release resources
|
||||
// here. A truncated body looks like a complete one: validate before
|
||||
// committing.
|
||||
// The callback returns true on success, false on error. A failure stops
|
||||
// streaming immediately and calls the end callback before closing.
|
||||
// Example:
|
||||
// if (ev == MG_EV_HTTP_HDRS && mg_match(hm->uri, mg_str("/fs/*"), NULL) {
|
||||
// mg_http_stream_body(c, hm, upload, NULL));
|
||||
// if (ev == MG_EV_HTTP_HDRS && mg_match(hm->uri, mg_str("/fs/*"), NULL)) {
|
||||
// mg_http_stream_body(c, hm, upload, NULL);
|
||||
// }
|
||||
// Full example:
|
||||
// tutorials/http/file-upload-single-post
|
||||
// Related APIs:
|
||||
// mg_http_listen(), mg_http_next_multipart()
|
||||
// Notes:
|
||||
// After it returns true, this function hijacks the connection. Existing event
|
||||
// handler not called, hm is invalid, c->data and c->fn_data are modified
|
||||
bool mg_http_stream_body(struct mg_connection *c, struct mg_http_message *hm,
|
||||
// The existing event handler is no longer called. hm is invalid after this
|
||||
// call; c->data and c->fn_data are reserved for streaming state.
|
||||
void mg_http_stream_body(struct mg_connection *c, struct mg_http_message *hm,
|
||||
bool (*upload_fn)(struct mg_http_message *,
|
||||
struct mg_str *, void **user_data),
|
||||
void *user_data);
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "l2.h"
|
||||
#include "net_builtin.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP
|
||||
|
||||
// Radio frame: 802.15.4 MAC header, 15 bytes: data frame, PAN ID compression,
|
||||
// broadcast destination, our EUI-64 made from MAC as source. Then 2 bytes:
|
||||
// tag, fragment index << 4 | last fragment index. Then data. 125 bytes max,
|
||||
// 127 minus FCS
|
||||
#define MGI_802154_HDR 17
|
||||
#define MGI_802154_DATA (125 - MGI_802154_HDR)
|
||||
|
||||
size_t mg_l2_802154_tx(struct mg_tcpip_if *ifp, const void *buf, size_t len,
|
||||
size_t (*send_fn)(const uint8_t *, size_t,
|
||||
struct mg_tcpip_if *)) {
|
||||
struct mg_l2_802154_data *d =
|
||||
(struct mg_l2_802154_data *) ifp->driver_data;
|
||||
const uint8_t *p = (const uint8_t *) buf, *m = ifp->mac;
|
||||
uint8_t f[MGI_802154_HDR + MGI_802154_DATA];
|
||||
size_t i, n, last = (len - 1) / MGI_802154_DATA;
|
||||
if (len == 0 || last > 15) return 0;
|
||||
d->tag++;
|
||||
for (i = 0; i <= last; i++) {
|
||||
n = i == last ? len - i * MGI_802154_DATA : MGI_802154_DATA;
|
||||
f[0] = 0x41, f[1] = 0xd8, f[2] = d->seq++; // 2006 frame, see above
|
||||
f[3] = (uint8_t) d->pan_id, f[4] = (uint8_t) (d->pan_id >> 8);
|
||||
f[5] = f[6] = 0xff;
|
||||
f[7] = m[5], f[8] = m[4], f[9] = m[3], f[10] = 0xfe, f[11] = 0xff;
|
||||
f[12] = m[2], f[13] = m[1], f[14] = m[0]; // Little endian EUI-64
|
||||
f[15] = d->tag, f[16] = (uint8_t) ((i << 4) | last);
|
||||
memcpy(f + MGI_802154_HDR, p + i * MGI_802154_DATA, n);
|
||||
if (send_fn(f, MGI_802154_HDR + n, ifp) == 0) return 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t mg_l2_802154_rx(struct mg_tcpip_if *ifp, const uint8_t *f, size_t n,
|
||||
void *buf, size_t len) {
|
||||
struct mg_l2_802154_data *d =
|
||||
(struct mg_l2_802154_data *) ifp->driver_data;
|
||||
size_t idx, last;
|
||||
if (n <= MGI_802154_HDR || f[0] != 0x41 || f[1] != 0xd8 ||
|
||||
f[3] != (uint8_t) d->pan_id || f[4] != (uint8_t) (d->pan_id >> 8))
|
||||
return 0; // Not ours
|
||||
idx = f[16] >> 4, last = f[16] & 15;
|
||||
if (idx == 0) d->rxtag = f[15], d->rxnext = 0, d->rxlen = 0;
|
||||
if (idx == 0) memcpy(d->rxsrc, f + 7, sizeof(d->rxsrc));
|
||||
n -= MGI_802154_HDR;
|
||||
if (idx != d->rxnext || idx > last || f[15] != d->rxtag ||
|
||||
memcmp(d->rxsrc, f + 7, sizeof(d->rxsrc)) != 0 ||
|
||||
d->rxlen + n > sizeof(d->rxbuf))
|
||||
return 0; // Missed a fragment, or from another sender
|
||||
memcpy(d->rxbuf + d->rxlen, f + MGI_802154_HDR, n);
|
||||
d->rxlen = (uint16_t) (d->rxlen + n), d->rxnext++;
|
||||
if (idx < last || d->rxlen > len) return 0;
|
||||
memcpy(buf, d->rxbuf, d->rxlen);
|
||||
return d->rxlen;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -105,14 +105,6 @@ static void mg_mdash_rpc_get_info(struct mg_rpc_req *r) {
|
||||
MG_ESC("crash"), mg_print_crash_record);
|
||||
}
|
||||
|
||||
static void mg_mdash_rpc_mem_stats(struct mg_rpc_req *r) {
|
||||
mg_rpc_ok(r, "{%m:%zu,%m:%zu,%m:%zu,%m:%zu}", //
|
||||
MG_ESC("stack_used"), (size_t) MG_HEALTH_STACK_USED, //
|
||||
MG_ESC("stack_total"), (size_t) MG_HEALTH_STACK_TOTAL, //
|
||||
MG_ESC("heap_used"), (size_t) MG_HEALTH_HEAP_USED, //
|
||||
MG_ESC("heap_total"), (size_t) MG_HEALTH_HEAP_TOTAL);
|
||||
}
|
||||
|
||||
static void mg_mdash_rpc_ota_begin(struct mg_rpc_req *r) {
|
||||
size_t total = (size_t) mg_json_get_long(r->frame, "$.params.size", -1);
|
||||
if (mg_ota_begin(total)) {
|
||||
@@ -158,7 +150,6 @@ void mg_mdash_init(struct mg_mgr *mgr) {
|
||||
MG_INFO(("Initialising mdash agent, key [%s]", MG_MDASH_KEY));
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("RPC.List"), mg_rpc_list, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("Sys.GetInfo"), mg_mdash_rpc_get_info, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("Sys.MemStats"), mg_mdash_rpc_mem_stats, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.Begin"), mg_mdash_rpc_ota_begin, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.Write"), mg_mdash_rpc_ota_write, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.End"), mg_mdash_rpc_ota_end, NULL);
|
||||
|
||||
@@ -154,6 +154,41 @@ extern struct mg_tcpip_driver mg_tcpip_driver_nxp_wifi;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_st67w6;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_atcmd;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_netc;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_mcxw71;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_rw612_154;
|
||||
|
||||
// IEEE 802.15.4 radio channel and PAN ID. Settable in mongoose_config.h
|
||||
#ifndef MG_L2_802154_CHANNEL
|
||||
#define MG_L2_802154_CHANNEL 15 // 11..26
|
||||
#endif
|
||||
#ifndef MG_L2_802154_PAN_ID
|
||||
#define MG_L2_802154_PAN_ID 0xabcd
|
||||
#endif
|
||||
|
||||
// driver_data for IEEE 802.15.4 radio drivers. The interface is Ethernet:
|
||||
// each Ethernet frame is split into broadcast radio frames, and reassembled
|
||||
// on the other side, see mg_l2_802154_tx() and mg_l2_802154_rx()
|
||||
struct mg_l2_802154_data {
|
||||
uint8_t channel; // User-set channel, 11..26
|
||||
uint16_t pan_id; // User-set PAN ID
|
||||
uint8_t seq, tag; // MAC sequence number, tag of the last sent frame
|
||||
uint8_t rxtag, rxnext; // Frame being reassembled: tag, next fragment
|
||||
uint8_t rxsrc[8]; // Its sender
|
||||
uint16_t rxlen; // Its bytes received so far
|
||||
uint8_t rxbuf[1514]; // Reassembly buffer, one Ethernet frame
|
||||
};
|
||||
|
||||
// Splits an Ethernet frame into radio frames, sends each by calling send().
|
||||
// Called by radio drivers' tx(). Return len, or 0 on error
|
||||
size_t mg_l2_802154_tx(struct mg_tcpip_if *ifp, const void *buf, size_t len,
|
||||
size_t (*send)(const uint8_t *, size_t,
|
||||
struct mg_tcpip_if *));
|
||||
|
||||
// Adds a received radio frame f of n bytes to the frame being reassembled.
|
||||
// Called by radio drivers' rx(). Return the Ethernet frame length, copied to
|
||||
// buf, when it is complete, otherwise 0
|
||||
size_t mg_l2_802154_rx(struct mg_tcpip_if *ifp, const uint8_t *f, size_t n,
|
||||
void *buf, size_t len);
|
||||
|
||||
// SPI bus abstraction for SPI-attached network chips (e.g. W5500).
|
||||
// Populate and assign to the driver's driver_data field.
|
||||
|
||||
@@ -208,9 +208,7 @@ static void s_firmware_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
(unsigned long) hm->body.len, (unsigned long) s_ota->size);
|
||||
} else {
|
||||
MG_DEBUG(("Beginning OTA (%lu bytes)", (unsigned long) s_ota->size));
|
||||
if (!mg_http_stream_body(c, hm, s_firmware_cb, NULL)) {
|
||||
mg_error(c, "Cannot stream firmware");
|
||||
}
|
||||
mg_http_stream_body(c, hm, s_firmware_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_ERROR) {
|
||||
s_ota->fn((char *) ev_data);
|
||||
@@ -243,6 +241,21 @@ void mg_ota_url_check(struct mg_mgr *mgr, const char *json_url,
|
||||
}
|
||||
}
|
||||
|
||||
// Uses *p as a flag: non-NULL means an OTA session is open and must be
|
||||
// closed by mg_ota_end()
|
||||
bool mg_http_ota_cb(struct mg_http_message *hm, struct mg_str *data, void **p) {
|
||||
if (hm != NULL) { // Start
|
||||
if (!mg_ota_begin(hm->body.len)) return false;
|
||||
*p = (void *) (ptrdiff_t) 1;
|
||||
return true;
|
||||
} else if (data != NULL) { // Next chunk
|
||||
return mg_ota_write(data->buf, data->len);
|
||||
}
|
||||
if (*p == NULL) return false; // End. Begin failed, nothing to finish
|
||||
*p = NULL;
|
||||
return mg_ota_end();
|
||||
}
|
||||
|
||||
void mg_ota_poll(struct mg_mgr *mgr) {
|
||||
static uint64_t t = 5000; // Fire first time 5 sec after boot
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "arch.h"
|
||||
#include "http.h"
|
||||
#include "net.h"
|
||||
|
||||
// Supported OTA targets
|
||||
@@ -34,6 +35,7 @@
|
||||
#define MG_OTA_STM32H7 2 // STM32 H7
|
||||
#define MG_OTA_STM32H7_DUAL_CORE 3 // STM32 H7 dual core
|
||||
#define MG_OTA_STM32F 4 // STM32 F7/F4/F2
|
||||
#define MG_OTA_STM32C5 5 // STM32 C5, same flash controller as H5
|
||||
#define MG_OTA_CH32V307 100 // WCH CH32V307
|
||||
#define MG_OTA_U2A 200 // Renesas U2A16, U2A8, U2A6
|
||||
#define MG_OTA_RT1020 300 // IMXRT1020
|
||||
@@ -43,6 +45,7 @@
|
||||
#define MG_OTA_RT1170 304 // IMXRT1170
|
||||
#define MG_OTA_RT1180 305 // IMXRT1180
|
||||
#define MG_OTA_MCXN 310 // MCXN947
|
||||
#define MG_OTA_MCXW71 311 // MCXW71
|
||||
#define MG_OTA_RW612 320 // FRDM-RW612
|
||||
#define MG_OTA_FLASH 900 // OTA via internal flash
|
||||
#define MG_OTA_ESP32 910 // ESP32 OTA implementation
|
||||
@@ -72,6 +75,18 @@ bool mg_ota_write(const void *buf, size_t len);
|
||||
// Ends the OTA process and commits the written firmware.
|
||||
bool mg_ota_end(void);
|
||||
|
||||
// Push-based OTA: mg_http_stream_body() callback that flashes the request
|
||||
//
|
||||
// ```c
|
||||
// if (ev == MG_EV_HTTP_HDRS) {
|
||||
// struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
// if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
// mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
bool mg_http_ota_cb(struct mg_http_message *hm, struct mg_str *data, void **p);
|
||||
|
||||
// MG_OTA_ROLLBACK: swap firmware banks and reset. On flash-based OTA, the
|
||||
// default calls swap_fn() (no-op on single-bank) then resets. Override in
|
||||
// mongoose_config.h for platforms without mg_flash (ESP32, PicoSDK, etc.).
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "flash.h"
|
||||
#include "log.h"
|
||||
#include "ota.h"
|
||||
|
||||
#if MG_OTA == MG_OTA_MCXW71
|
||||
|
||||
// MCXW71SRM, section 11.2: ROM flash API, 8 KB sectors, 16-byte phrases,
|
||||
// 128-byte pages. Only the CM33 application flash is used; RF flash and IFR
|
||||
// (including the write-once ROM configuration) are left alone.
|
||||
struct mg_mcxw71_flash_config {
|
||||
struct {
|
||||
uint32_t base, size, blocks;
|
||||
uint32_t ifr_base, ifr_size;
|
||||
} mem[2];
|
||||
};
|
||||
|
||||
struct mg_mcxw71_flash_api {
|
||||
uint32_t (*init)(struct mg_mcxw71_flash_config *);
|
||||
uint32_t (*erase)(struct mg_mcxw71_flash_config *, void *, uint32_t, uint32_t,
|
||||
uint32_t);
|
||||
uint32_t (*phrase)(struct mg_mcxw71_flash_config *, void *, uint32_t,
|
||||
uint32_t *, uint32_t);
|
||||
uint32_t (*page)(struct mg_mcxw71_flash_config *, void *, uint32_t,
|
||||
uint32_t *, uint32_t);
|
||||
};
|
||||
|
||||
// The flash API pointer is the second entry in the ROM API table.
|
||||
#define MG_MCXW71_FLASH_API \
|
||||
(*(const struct mg_mcxw71_flash_api *const *) 0x14816fe4U)
|
||||
#define MG_MCXW71_ERASE_KEY 0x6b65666cU // FOUR_CHAR_CODE('l', 'f', 'e', 'k')
|
||||
|
||||
static struct mg_mcxw71_flash_config s_mcxw71_config;
|
||||
static size_t s_mcxw71_size, s_mcxw71_received, s_mcxw71_pending;
|
||||
static uint32_t s_mcxw71_buf[4];
|
||||
static bool s_mcxw71_failed;
|
||||
|
||||
static bool mg_mcxw71_write(void *, const void *, size_t);
|
||||
static bool mg_mcxw71_swap(void);
|
||||
static struct mg_flash s_mg_flash_mcxw71 = {
|
||||
(void *) 0, 0x100000, 8192, 16, mg_mcxw71_write, mg_mcxw71_swap};
|
||||
struct mg_flash *mg_flash = &s_mg_flash_mcxw71;
|
||||
|
||||
// Everything called while flash is busy, or after the application has been
|
||||
// erased, must execute from RAM or ROM. Do not log or call libc here.
|
||||
MG_IRAM static bool mg_mcxw71_write(void *addr, const void *buf, size_t len) {
|
||||
uintptr_t dst = (uintptr_t) addr;
|
||||
const volatile uint8_t *src = (const volatile uint8_t *) buf;
|
||||
uint32_t irq, status = 0;
|
||||
if (dst >= s_mg_flash_mcxw71.size || len > s_mg_flash_mcxw71.size - dst ||
|
||||
(dst % 16) != 0 || (len % 16) != 0)
|
||||
return false;
|
||||
|
||||
irq = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
while (len > 0 && status == 0) {
|
||||
uint32_t words[32]; // ROM needs a word-aligned source in RAM
|
||||
volatile uint8_t *p = (volatile uint8_t *) words;
|
||||
size_t i, n = (dst % 128) == 0 && len >= 128 ? 128 : 16;
|
||||
for (i = 0; i < n; i++) p[i] = src[i];
|
||||
|
||||
// Match the MCUXpresso ROM wrappers' cache maintenance. Interrupts stay
|
||||
// masked until the flash command completes and stale cache data is gone.
|
||||
MCM->CPCR2 |= MCM_CPCR2_CCBC_MASK;
|
||||
__DSB();
|
||||
__ISB();
|
||||
if ((dst % 8192) == 0) {
|
||||
status = MG_MCXW71_FLASH_API->erase(
|
||||
&s_mcxw71_config, FMU0, (uint32_t) dst, 8192, MG_MCXW71_ERASE_KEY);
|
||||
}
|
||||
if (status == 0) {
|
||||
if (n == 128) {
|
||||
status = MG_MCXW71_FLASH_API->page(&s_mcxw71_config, FMU0,
|
||||
(uint32_t) dst, words, 128);
|
||||
} else {
|
||||
status = MG_MCXW71_FLASH_API->phrase(&s_mcxw71_config, FMU0,
|
||||
(uint32_t) dst, words, 16);
|
||||
}
|
||||
}
|
||||
MCM->CPCR2 |= MCM_CPCR2_CCBC_MASK;
|
||||
__DSB();
|
||||
__ISB();
|
||||
dst += n, src += n, len -= n;
|
||||
}
|
||||
__set_PRIMASK(irq);
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
static bool mg_mcxw71_swap(void) {
|
||||
// The common helper verifies the staged image before the RAM copy below.
|
||||
// A failed write must never commit, even if all expected bytes arrived.
|
||||
return !s_mcxw71_failed;
|
||||
}
|
||||
|
||||
MG_IRAM static void mg_mcxw71_apply(size_t size) {
|
||||
size_t ofs, half = s_mg_flash_mcxw71.size / 2;
|
||||
__disable_irq();
|
||||
SysTick->CTRL = 0;
|
||||
for (ofs = 0; ofs < size; ofs += 8192) {
|
||||
if (!mg_mcxw71_write((void *) (uintptr_t) ofs,
|
||||
(const void *) (uintptr_t) (half + ofs), 8192)) {
|
||||
// The application may already be erased. Stay in RAM for debugger
|
||||
// recovery rather than return to partially overwritten flash.
|
||||
for (;;) __NOP();
|
||||
}
|
||||
}
|
||||
__DSB();
|
||||
SCB->AIRCR = 0x05fa0004U;
|
||||
__DSB();
|
||||
for (;;) __NOP();
|
||||
}
|
||||
|
||||
bool mg_ota_begin(size_t new_firmware_size) {
|
||||
uint32_t status;
|
||||
if (s_mcxw71_size != 0 || new_firmware_size == 0) return false;
|
||||
status = MG_MCXW71_FLASH_API->init(&s_mcxw71_config);
|
||||
if (status != 0 || s_mcxw71_config.mem[0].base != 0 ||
|
||||
s_mcxw71_config.mem[0].size < 16384 ||
|
||||
(s_mcxw71_config.mem[0].size % 16384) != 0) {
|
||||
MG_ERROR(("Flash init failed: %lu", (unsigned long) status));
|
||||
return false;
|
||||
}
|
||||
s_mg_flash_mcxw71.size = s_mcxw71_config.mem[0].size;
|
||||
if (!mg_ota_flash_begin(new_firmware_size, &s_mg_flash_mcxw71)) return false;
|
||||
s_mcxw71_size = new_firmware_size;
|
||||
s_mcxw71_received = s_mcxw71_pending = 0;
|
||||
s_mcxw71_failed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mg_ota_write(const void *buf, size_t len) {
|
||||
const uint8_t *p = (const uint8_t *) buf;
|
||||
uint8_t *pending = (uint8_t *) s_mcxw71_buf;
|
||||
if (s_mcxw71_size == 0 || s_mcxw71_failed) return false;
|
||||
if (len > s_mcxw71_size - s_mcxw71_received || (len > 0 && buf == NULL)) {
|
||||
s_mcxw71_failed = true;
|
||||
return false;
|
||||
}
|
||||
s_mcxw71_received += len;
|
||||
if (s_mcxw71_pending > 0) {
|
||||
size_t n = 16 - s_mcxw71_pending;
|
||||
if (n > len) n = len;
|
||||
if (n > 0) memcpy(pending + s_mcxw71_pending, p, n);
|
||||
s_mcxw71_pending += n;
|
||||
if (n > 0) p += n;
|
||||
len -= n;
|
||||
if (s_mcxw71_pending == 16) {
|
||||
s_mcxw71_failed = !mg_ota_flash_write(pending, 16, &s_mg_flash_mcxw71);
|
||||
s_mcxw71_pending = 0;
|
||||
}
|
||||
}
|
||||
if (!s_mcxw71_failed && len >= 16) {
|
||||
size_t n = MG_ROUND_DOWN(len, 16);
|
||||
s_mcxw71_failed = !mg_ota_flash_write(p, n, &s_mg_flash_mcxw71);
|
||||
p += n, len -= n;
|
||||
}
|
||||
if (!s_mcxw71_failed && len > 0) {
|
||||
memcpy(pending + s_mcxw71_pending, p, len);
|
||||
s_mcxw71_pending += len;
|
||||
}
|
||||
return !s_mcxw71_failed;
|
||||
}
|
||||
|
||||
bool mg_ota_end(void) {
|
||||
bool ok;
|
||||
size_t size = s_mcxw71_size;
|
||||
if (size == 0) return false;
|
||||
if (s_mcxw71_received != size) s_mcxw71_failed = true;
|
||||
if (!s_mcxw71_failed && s_mcxw71_pending > 0) {
|
||||
s_mcxw71_failed =
|
||||
!mg_ota_flash_write(s_mcxw71_buf, s_mcxw71_pending, &s_mg_flash_mcxw71);
|
||||
}
|
||||
ok = mg_ota_flash_end(&s_mg_flash_mcxw71);
|
||||
s_mcxw71_size = s_mcxw71_pending = 0;
|
||||
if (ok) {
|
||||
MG_INFO(("Applying %lu bytes from staging flash", (unsigned long) size));
|
||||
mg_mcxw71_apply(size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#include "log.h"
|
||||
#include "ota.h"
|
||||
|
||||
#if MG_OTA == MG_OTA_STM32H5
|
||||
#if MG_OTA == MG_OTA_STM32H5 || MG_OTA == MG_OTA_STM32C5
|
||||
|
||||
static bool mg_stm32h5_write(void *, const void *, size_t);
|
||||
static bool mg_stm32h5_swap(void);
|
||||
|
||||
+3
-2
@@ -261,8 +261,9 @@ uint64_t mg_ntohll(uint64_t net) {
|
||||
}
|
||||
|
||||
void mg_delayms(unsigned int ms) {
|
||||
uint64_t to = mg_millis() + ms + 1;
|
||||
while (mg_millis() < to) (void) 0;
|
||||
uint64_t now, to = mg_millis() + ms + 1;
|
||||
while ((now = mg_millis()) < to)
|
||||
if (now + ms + 1 < to) to = now + ms + 1;
|
||||
}
|
||||
|
||||
#if MG_ENABLE_CUSTOM_CALLOC
|
||||
|
||||
@@ -555,7 +555,6 @@ static void task2(void *args) {
|
||||
DASHBOARD("select_child_write");
|
||||
DASHBOARD("poll_child_write");
|
||||
|
||||
#if 0
|
||||
s_error = false;
|
||||
s_backlog_ready = s_backlog_full = s_backlog_accept = false;
|
||||
ASSERT(xTaskCreate(backlog_task, "backlog", 512, NULL,
|
||||
@@ -570,12 +569,6 @@ static void task2(void *args) {
|
||||
while (!client_done(first, &status)) vTaskDelay(1);
|
||||
check_client(status);
|
||||
DASHBOARD("listen_backlog");
|
||||
#else
|
||||
(void) first;
|
||||
(void) second;
|
||||
(void) status;
|
||||
(void) backlog_task;
|
||||
#endif
|
||||
|
||||
s_error = false;
|
||||
// atask at higher priority than task1
|
||||
|
||||
+108
-6
@@ -3158,8 +3158,6 @@ static bool su_cb(struct mg_http_message *hm, struct mg_str *data, void **p) {
|
||||
static void su(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
mg_http_stream_body(c, (struct mg_http_message *) ev_data, su_cb, NULL);
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // Only for requests that were not streamed
|
||||
mg_http_reply(c, 400, "", "not streamed\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3194,8 +3192,7 @@ static void cr(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_CONNECT) {
|
||||
mg_printf(c, "GET / HTTP/1.0\r\n\r\n");
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
ASSERT(mg_http_stream_body(c, (struct mg_http_message *) ev_data, cr_cb,
|
||||
NULL));
|
||||
mg_http_stream_body(c, (struct mg_http_message *) ev_data, cr_cb, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3208,12 +3205,103 @@ static void cs(struct mg_connection *c, int ev, void *ev_data) {
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
struct stream_test_state {
|
||||
int fail_at, starts, chunks, ends;
|
||||
};
|
||||
|
||||
static bool stream_test_cb(struct mg_http_message *hm, struct mg_str *data,
|
||||
void **p) {
|
||||
struct stream_test_state *s = (struct stream_test_state *) *p;
|
||||
ASSERT(s != NULL);
|
||||
if (hm != NULL) {
|
||||
s->starts++;
|
||||
return s->fail_at != 1;
|
||||
} else if (data != NULL) {
|
||||
s->chunks++;
|
||||
return s->fail_at != 2;
|
||||
}
|
||||
s->ends++;
|
||||
*p = NULL;
|
||||
return s->fail_at != 3;
|
||||
}
|
||||
|
||||
static void stream_test_original(struct mg_connection *c, int ev, void *data) {
|
||||
(void) c, (void) ev, (void) data;
|
||||
ASSERT(false); // Streaming must take ownership even when validation fails
|
||||
}
|
||||
|
||||
static void test_http_stream_errors(void) {
|
||||
static const struct {
|
||||
const char *request;
|
||||
int client, fail_at, body_size, code, starts, chunks;
|
||||
} cases[] = {
|
||||
{"GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n", 0, 0, 0, 405, 0, 0},
|
||||
{"POST / HTTP/1.1\r\n\r\n", 0, 0, 0, 411, 0, 0},
|
||||
{"POST / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n",
|
||||
0, 0, 0, 400, 0, 0},
|
||||
{"POST / HTTP/1.1\r\nContent-Length: 3\r\n\r\nabc", 0, 0, 0, 200, 1, 1},
|
||||
{"PUT / HTTP/1.1\r\nContent-Length: 0\r\n\r\n", 0, 0, 0, 200, 1, 0},
|
||||
// Start failure must reply without waiting for the body or sending 100.
|
||||
{"POST / HTTP/1.1\r\nContent-Length: 1000000\r\nExpect: 100-continue\r\n\r\n",
|
||||
0, 1, 0, 500, 1, 0},
|
||||
// Write failure must also reply before the announced body is complete.
|
||||
{"POST / HTTP/1.1\r\nContent-Length: 1000000\r\n\r\n",
|
||||
0, 2, 512, 500, 1, 1},
|
||||
{"POST / HTTP/1.1\r\nContent-Length: 3\r\n\r\nabc", 0, 3, 0, 500, 1, 1},
|
||||
// Clients close on errors and never send an HTTP error response.
|
||||
{"HTTP/1.1 200 OK\r\n\r\n", 1, 0, 0, 411, 0, 0},
|
||||
{"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n",
|
||||
1, 0, 0, 400, 0, 0},
|
||||
{"HTTP/1.1 200 OK\r\nContent-Length: 1000000\r\n\r\n",
|
||||
1, 1, 0, 500, 1, 0},
|
||||
{"HTTP/1.1 200 OK\r\nContent-Length: 1000000\r\n\r\n",
|
||||
1, 2, 512, 500, 1, 1},
|
||||
{"HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nabc", 1, 3, 0, 500, 1, 1},
|
||||
{"HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nabc", 1, 0, 0, 200, 1, 1},
|
||||
{"HTTP/1.1 204 No Content\r\n\r\n", 1, 0, 0, 200, 1, 0},
|
||||
};
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
struct mg_connection c;
|
||||
struct mg_http_message hm;
|
||||
struct stream_test_state state = {0, 0, 0, 0};
|
||||
char body[512];
|
||||
memset(&c, 0, sizeof(c));
|
||||
memset(body, 'x', sizeof(body));
|
||||
state.fail_at = cases[i].fail_at;
|
||||
c.is_client = cases[i].client != 0;
|
||||
c.fn = c.pfn = stream_test_original;
|
||||
mg_iobuf_add(&c.recv, 0, cases[i].request, strlen(cases[i].request));
|
||||
mg_iobuf_add(&c.recv, c.recv.len, body, (size_t) cases[i].body_size);
|
||||
ASSERT(mg_http_parse((char *) c.recv.buf, c.recv.len, &hm) > 0);
|
||||
mg_http_stream_body(&c, &hm, stream_test_cb, &state);
|
||||
ASSERT(c.pfn == NULL && c.is_draining);
|
||||
ASSERT(state.starts == cases[i].starts && state.chunks == cases[i].chunks);
|
||||
ASSERT(state.ends == 1);
|
||||
if (c.is_client) {
|
||||
ASSERT(c.send.len == 0);
|
||||
ASSERT(c.is_closing == (cases[i].code != 200));
|
||||
} else {
|
||||
ASSERT(mg_http_parse((char *) c.send.buf, c.send.len, &hm) > 0);
|
||||
ASSERT(mg_http_status(&hm) == cases[i].code);
|
||||
ASSERT(hm.message.len == c.send.len); // Exactly one response
|
||||
}
|
||||
mg_call(&c, MG_EV_READ, NULL);
|
||||
mg_error(&c, "stream cleanup test");
|
||||
mg_call(&c, MG_EV_CLOSE, NULL);
|
||||
ASSERT(state.ends == 1); // Error followed by close must not clean up twice
|
||||
mg_iobuf_free(&c.recv);
|
||||
mg_iobuf_free(&c.send);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_http_upload(void) {
|
||||
struct mg_mgr mgr;
|
||||
const char *url = "http://127.0.0.1:12352";
|
||||
int i;
|
||||
const char *s = "ok (8 foo\nbar\n)\n";
|
||||
|
||||
test_http_stream_errors();
|
||||
mg_mgr_init(&mgr);
|
||||
mg_http_listen(&mgr, url, us, NULL);
|
||||
mg_http_connect(&mgr, url, uc, (void *) &s);
|
||||
@@ -3257,7 +3345,7 @@ static void test_http_upload(void) {
|
||||
ASSERT(mgr.conns == NULL);
|
||||
}
|
||||
|
||||
// mg_http_stream_body: chunked request is not streamed, caller replies "400"
|
||||
// mg_http_stream_body: chunked request rejected with "400", cleanup still runs
|
||||
{
|
||||
char buf[FETCH_BUF_SIZE];
|
||||
s_su_done = s_su_end = 0;
|
||||
@@ -3268,7 +3356,7 @@ static void test_http_upload(void) {
|
||||
"POST /su_chunked.txt HTTP/1.1\r\n"
|
||||
"Transfer-Encoding: chunked\r\n\r\n"
|
||||
"3\r\nfoo\r\n0\r\n\r\n") == 400);
|
||||
ASSERT(s_su_done == 0 && s_su_end == 0); // The callback was never called
|
||||
ASSERT(s_su_done == 1 && s_su_end == 1); // End called without start
|
||||
ASSERT(fopen("su_chunked.txt", "r") == NULL);
|
||||
mg_mgr_free(&mgr);
|
||||
ASSERT(mgr.conns == NULL);
|
||||
@@ -5010,6 +5098,20 @@ static void test_dash(void) {
|
||||
"Authorization: Basic YWRtaW46YWRtaW4=\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, login_admin_expected) == 0);
|
||||
|
||||
// OTA uses streaming and enforces the dashboard's authentication.
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"POST /api/ota HTTP/1.0\nContent-Length: 1\n\nx") == 403);
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"GET /api/ota HTTP/1.0\nContent-Length: 0\n"
|
||||
"Authorization: Basic YWRtaW46YWRtaW4=\n\n") == 405);
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"POST /ota HTTP/1.0\nContent-Length: 1\n"
|
||||
"Authorization: Basic YWRtaW46YWRtaW4=\n\nx") == 404);
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"POST /api/ota HTTP/1.0\nContent-Length: 1\n"
|
||||
"Authorization: Basic YWRtaW46YWRtaW4=\n\nx") == 200);
|
||||
ASSERT(cmpbody(buf, "1 ok\n") == 0);
|
||||
|
||||
// set3 is admin-only
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"GET /api/get/set3 HTTP/1.0\n"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
THISDIR = $(realpath $(CURDIR))
|
||||
ROOTDIR = $(realpath $(CURDIR)/../../..)
|
||||
DOCKER ?= docker run --rm $(DA) -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) espressif/idf
|
||||
CMD ?= idf.py build
|
||||
CMD ?= idf.py -DCFLAGS_EXTRA="$(CFLAGS_EXTRA)" build
|
||||
PORT ?= /dev/ttyUSB0
|
||||
|
||||
CFLAGS_EXTRA ?= -DMG_TLS=MG_TLS_BUILTIN
|
||||
|
||||
all: example
|
||||
|
||||
example:
|
||||
|
||||
@@ -12,3 +12,5 @@ idf_component_register(SRCS "main.c"
|
||||
espcoredump
|
||||
nvs_flash
|
||||
app_update)
|
||||
separate_arguments(CFLAGS_EXTRA)
|
||||
component_compile_options(${CFLAGS_EXTRA})
|
||||
@@ -44,6 +44,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
size_t total = heap_caps_get_total_size(MALLOC_CAP_DEFAULT);
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
#define MG_ARCH MG_ARCH_ESP32
|
||||
|
||||
#define MG_TLS MG_TLS_BUILTIN
|
||||
//#define MG_TLS MG_TLS_MBED
|
||||
@@ -9,7 +9,12 @@ static void t_fn(void *arg) { // Tick periodically
|
||||
}
|
||||
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "hi\n");
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "hi\n");
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,12 @@ static void t_fn(void *arg) { // Tick periodically
|
||||
}
|
||||
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "hi\n");
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "hi\n");
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
extern void mgmp_init(void);
|
||||
extern void mgmp_poll(int);
|
||||
|
||||
STATIC mp_obj_t mongoose_init(void) {
|
||||
static mp_obj_t mongoose_init(void) {
|
||||
mgmp_init();
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mongoose_init_obj, mongoose_init);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_0(mongoose_init_obj, mongoose_init);
|
||||
|
||||
STATIC mp_obj_t mongoose_poll(mp_obj_t t_obj) {
|
||||
static mp_obj_t mongoose_poll(mp_obj_t t_obj) {
|
||||
mgmp_poll(mp_obj_get_int(t_obj));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mongoose_poll_obj, mongoose_poll);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(mongoose_poll_obj, mongoose_poll);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mongoose_module_globals_table[] = {
|
||||
static const mp_rom_map_elem_t mongoose_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mongoose) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&mongoose_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mongoose_poll_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mongoose_module_globals, mongoose_module_globals_table);
|
||||
static MP_DEFINE_CONST_DICT(mongoose_module_globals, mongoose_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mongoose_module = {
|
||||
.base = { &mp_type_module },
|
||||
|
||||
@@ -120,7 +120,7 @@ void mg_mqtt_poll(struct mg_mgr *mgr) {
|
||||
|
||||
// Reconnect if connection is closed, and send MQTT PINGs to keep
|
||||
// the connection alive or to detect connection loss
|
||||
if (mg_timer_expired(&timer, MQTT_RECONNECT_PERIOD_MS, mg_now())) {
|
||||
if (mg_timer_expired(&timer, MQTT_RECONNECT_PERIOD_MS, mg_millis())) {
|
||||
if (s_mqtt_conn == NULL) {
|
||||
struct mg_mqtt_opts opts = {
|
||||
.clean = true,
|
||||
|
||||
@@ -65,6 +65,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -89,6 +89,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -97,6 +97,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Environment setup: https://mongoose.ws/documentation/tutorials/tools/
|
||||
|
||||
MGDIR = ../../../..
|
||||
|
||||
CFLAGS = -W -Wall -Wextra -Werror -Wundef -Wshadow
|
||||
CFLAGS += -Wformat-truncation -fno-common -Wno-conversion -Wno-sign-conversion
|
||||
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
|
||||
CFLAGS += -I. -I$(MGDIR) -Icmsis_core/CMSIS/Core/Include
|
||||
CFLAGS += -Icmsis_mcxw71/MCXW/MCXW716C -Icmsis_mcxw71/MCXW/periph2
|
||||
CFLAGS += -DCPU_MCXW716CMFTA
|
||||
CFLAGS += -D__START=main -D__STARTUP_CLEAR_BSS # For startup_MCXW716C.S
|
||||
CFLAGS += -mcpu=cortex-m33 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 $(CFLAGS_EXTRA)
|
||||
|
||||
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs=nano.specs -lc -lm -lgcc -Wl,--gc-sections
|
||||
|
||||
SOURCES = main.c hal.c $(MGDIR)/mongoose.c
|
||||
SOURCES += $(MGDIR)/tutorials/mqtt/mqtt-client/mongoose_mqtt.c
|
||||
SOURCES += cmsis_mcxw71/MCXW/MCXW716C/gcc/startup_MCXW716C.S
|
||||
|
||||
all build: firmware.bin
|
||||
|
||||
firmware.bin: firmware.elf
|
||||
arm-none-eabi-objcopy -O binary $< $@
|
||||
arm-none-eabi-size --format=berkeley $<
|
||||
|
||||
firmware.elf: cmsis_core cmsis_mcxw71 $(SOURCES) $(wildcard *.h) link.ld Makefile
|
||||
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
cmsis_core:
|
||||
git clone -q -c advice.detachedHead=false --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
|
||||
|
||||
# Device headers and startup code from MCUXpresso SDK, only MCXW716C files
|
||||
cmsis_mcxw71:
|
||||
git clone -q --depth 1 --filter=blob:none --sparse https://github.com/nxp-mcuxpresso/mcux-devices-mcx $@
|
||||
cd $@ && git sparse-checkout set MCXW/MCXW716C MCXW/periph2
|
||||
|
||||
# Show all symbols sorted by size
|
||||
show_symbols_sorted_by_size: firmware.bin
|
||||
arm-none-eabi-readelf -sW firmware.elf | sed 1,3d | sed 's,^.*: ,,' | tr -s ' ' | cut -d ' ' -f 2,7 | sort -nk1 | grep -v '^0 '
|
||||
|
||||
flash: firmware.bin
|
||||
LinkServer flash MCXW716C:FRDM-MCXW71 load firmware.elf
|
||||
|
||||
clean:
|
||||
rm -rf firmware.* cmsis_*
|
||||
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2026 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#include "hal.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
// Initialise the transceiver the way NXP XCVR_Init() does it: start the RF
|
||||
// oscillator, wait for the radio to wake up, enable its clocks and load the
|
||||
// 802.15.4 register setup. Then select the legacy 802.15.4 demodulator and
|
||||
// CCA from RX digital. See PhyHwInit() in NXP ieee_802_15_4 PHY sources,
|
||||
// PhyPacketProcessor.c
|
||||
bool hal_radio_init(void) {
|
||||
uint32_t stat = RFMC_RF2P4GHZ_STAT_RST_STAT_MASK |
|
||||
RFMC_RF2P4GHZ_STAT_LP_ACK_STAT_MASK;
|
||||
size_t i, n = 1000000;
|
||||
RFMC->CTRL &= ~RFMC_CTRL_RFMC_RST_MASK; // RFMC out of reset
|
||||
RFMC->RF2P4GHZ_CTRL |= RFMC_RF2P4GHZ_CTRL_XO_EN_MASK; // Start RF oscillator
|
||||
RFMC->RF2P4GHZ_CTRL &=
|
||||
~(RFMC_RF2P4GHZ_CTRL_LP_ENTER_MASK | RFMC_RF2P4GHZ_CTRL_RF_POR_MASK |
|
||||
RFMC_RF2P4GHZ_CTRL_RST_MASK); // Release radio reset, no low power
|
||||
while ((RFMC->RF2P4GHZ_STAT & stat) != 0 ||
|
||||
(RFMC->XO_STAT & RFMC_XO_STAT_XTAL_RDY_MASK) == 0) {
|
||||
if (--n == 0) return false; // Radio did not wake up
|
||||
}
|
||||
RADIO_CTRL->LL_CTRL = RADIO_CTRL_LL_CTRL_ACTIVE_LL_MASK;
|
||||
RFMC->RF2P4GHZ_CTRL |=
|
||||
RFMC_RF2P4GHZ_CTRL_BLE_LP_EN_MASK | RFMC_RF2P4GHZ_CTRL_BLE_WKUP_MASK;
|
||||
for (i = 0; i < sizeof(s_radio_regs) / sizeof(s_radio_regs[0]); i++) {
|
||||
*s_radio_regs[i].reg = s_radio_regs[i].val;
|
||||
}
|
||||
XCVR_MISC->XCVR_CTRL &= ~XCVR_MISC_XCVR_CTRL_DEMOD_SEL_MASK;
|
||||
XCVR_MISC->XCVR_CTRL |= XCVR_MISC_XCVR_CTRL_DEMOD_SEL(2);
|
||||
XCVR_ZBDEMOD->CCA_LQI_SRC |= XCVR_ZBDEMOD_CCA_LQI_SRC_CCA1_FROM_RX_DIG(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Random bytes for Mongoose, MG_ENABLE_CUSTOM_RANDOM. Entropy is radio noise:
|
||||
// receiver RSSI, sampled while the radio receives, mixed with SysTick by
|
||||
// SHA-256. Good enough for random addresses and nonces, not a certified TRNG
|
||||
bool mg_random(void *buf, size_t len) {
|
||||
static uint32_t counter;
|
||||
uint8_t digest[32], *p = (uint8_t *) buf;
|
||||
size_t i, n;
|
||||
while (len > 0) {
|
||||
mg_sha256_ctx ctx;
|
||||
mg_sha256_init(&ctx);
|
||||
counter++;
|
||||
mg_sha256_update(&ctx, (uint8_t *) &counter, sizeof(counter));
|
||||
for (i = 0; i < 64; i++) {
|
||||
uint32_t sample[2] = {XCVR_RX_DIG->NB_RSSI_RES0, SysTick->VAL};
|
||||
mg_sha256_update(&ctx, (uint8_t *) sample, sizeof(sample));
|
||||
for (n = 0; n < 50; n++) __NOP(); // Let the RSSI update
|
||||
}
|
||||
mg_sha256_final(digest, &ctx);
|
||||
n = len < sizeof(digest) ? len : sizeof(digest);
|
||||
memcpy(p, digest, n), p += n, len -= n;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Added to minimise the bin size: avoid pulling printf and friends
|
||||
void __assert_func(const char *s, int line, const char *fn, const char *expr) {
|
||||
(void) s, (void) line, (void) fn, (void) expr;
|
||||
for (;;) (void) 0; // or trigger the fault handler
|
||||
}
|
||||
|
||||
bool hal_timer_expired(volatile uint64_t *t, uint64_t period, uint64_t now) {
|
||||
uint64_t diff = now - *t; // Wrap-safe elapsed time since last expiry
|
||||
if (period == 0) return false; // Avoid division by zero
|
||||
if (diff < period) return false; // Period has not elapsed yet
|
||||
*t += (diff / period) * period; // Preserve cadence, skip missed periods
|
||||
return true;
|
||||
}
|
||||
|
||||
static volatile uint64_t s_ticks; // Milliseconds since boot
|
||||
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
|
||||
s_ticks++;
|
||||
}
|
||||
|
||||
uint64_t hal_get_tick(void) {
|
||||
return s_ticks;
|
||||
}
|
||||
|
||||
uint32_t SystemCoreClock;
|
||||
|
||||
// Called by the startup code before .data and .bss are initialised, so it
|
||||
// must not write any variables. Clock and SysTick setup is in main()
|
||||
void SystemInit(void) {
|
||||
hal_sys_init();
|
||||
}
|
||||
|
||||
struct stat;
|
||||
__attribute__((weak)) int _fstat(int fd, struct stat *st) {
|
||||
(void) fd, (void) st;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern unsigned char _end[]; // End of data section, start of heap. See link.ld
|
||||
static unsigned char *s_current_heap_end = _end;
|
||||
|
||||
size_t hal_ram_used(void) {
|
||||
return (size_t) (s_current_heap_end - _end);
|
||||
}
|
||||
|
||||
size_t hal_ram_free(void) {
|
||||
unsigned char endofstack;
|
||||
return (size_t) (&endofstack - s_current_heap_end);
|
||||
}
|
||||
|
||||
void *_sbrk(int incr) {
|
||||
unsigned char *prev_heap;
|
||||
unsigned char *heap_end = (unsigned char *) ((size_t) &heap_end - 256);
|
||||
prev_heap = s_current_heap_end;
|
||||
// Check how much space we got from the heap end to the stack end
|
||||
if (s_current_heap_end + incr > heap_end) return (void *) -1;
|
||||
s_current_heap_end += incr;
|
||||
return prev_heap;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _open(const char *path) {
|
||||
(void) path;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _close(int fd) {
|
||||
(void) fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _isatty(int fd) {
|
||||
(void) fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _lseek(int fd, int ptr, int dir) {
|
||||
(void) fd, (void) ptr, (void) dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _exit(int status) {
|
||||
(void) status;
|
||||
for (;;) asm volatile("BKPT #0");
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _kill(int pid, int sig) {
|
||||
(void) pid, (void) sig;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _getpid(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _read(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _init(void) {
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
// Copyright (c) 2026 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// FRDM-MCXW71 hardware abstraction layer. MCXW716C reference: MCUXpresso SDK,
|
||||
// https://github.com/nxp-mcuxpresso/mcux-devices-mcx, MCXW/MCXW716C
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MCXW716C.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
uint64_t hal_get_tick(void);
|
||||
bool hal_timer_expired(volatile uint64_t *t, uint64_t period, uint64_t now);
|
||||
size_t hal_ram_used(void);
|
||||
size_t hal_ram_free(void);
|
||||
bool hal_radio_init(void); // Set up the 2.4 GHz transceiver for 802.15.4
|
||||
extern uint32_t SystemCoreClock; // CPU clock, Hz. Set by hal_clock_init()
|
||||
|
||||
|
||||
#define BIT(x) (1UL << (x))
|
||||
#define CLRSET(reg, clear, set) ((reg) = ((reg) & ~(clear)) | (set))
|
||||
#define SIRC_FREQUENCY 6000000UL // Slow IRC (FRO6M), Hz
|
||||
|
||||
// MRCC peripheral clock source, MRCC_xx[MUX], see fsl_clock.h
|
||||
enum { MRCC_SRC_FRO6M = 2, MRCC_SRC_FRO192M = 3 };
|
||||
|
||||
// Fast IRC frequency, Hz, or 0 if FIRC is not running. See CLOCK_GetFircFreq()
|
||||
static inline uint32_t hal_firc_freq(void) {
|
||||
static const uint32_t freqs[] = {48000000, 64000000, 96000000, 192000000};
|
||||
if ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) == 0) return 0;
|
||||
return freqs[SCG0->FIRCCFG & SCG_FIRCCFG_RANGE_MASK];
|
||||
}
|
||||
|
||||
// Switch the system clock: source (2 SIRC, 3 FIRC), core and slow dividers
|
||||
// as divider - 1. Wait until the switch is done. See CLOCK_SetRunModeSysClkConfig
|
||||
static inline void hal_set_sysclk(uint32_t src, uint32_t divcore,
|
||||
uint32_t divslow) {
|
||||
SCG0->RCCR = SCG_RCCR_SCS(src) | SCG_RCCR_DIVCORE(divcore) |
|
||||
SCG_RCCR_DIVSLOW(divslow);
|
||||
while (((SCG0->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT) != src) (void) 0;
|
||||
}
|
||||
|
||||
// Run the core at 96 MHz from FIRC, slow clock 24 MHz. Order as in NXP
|
||||
// BOARD_BootClockRUN(), clock_config.c: raise the core voltage and memory
|
||||
// timing first, then the clock. FIRC can only be changed when not in use
|
||||
static inline void hal_clock_96mhz(void) {
|
||||
while (SPC0->SC & SPC_SC_BUSY_MASK) (void) 0;
|
||||
CLRSET(SPC0->ACTIVE_CFG, SPC_ACTIVE_CFG_CORELDO_VDD_LVL_MASK,
|
||||
SPC_ACTIVE_CFG_CORELDO_VDD_LVL(2)); // Normal voltage
|
||||
while (SPC0->SC & SPC_SC_BUSY_MASK) (void) 0;
|
||||
CLRSET(FMU0->FCTRL, FMU_FCTRL_RWSC_MASK, FMU_FCTRL_RWSC(2)); // Wait states
|
||||
CLRSET(SPC0->SRAMCTL, SPC_SRAMCTL_VSM_MASK, SPC_SRAMCTL_VSM(2)); // 1.1 V
|
||||
SPC0->SRAMCTL |= SPC_SRAMCTL_REQ_MASK;
|
||||
while ((SPC0->SRAMCTL & SPC_SRAMCTL_ACK_MASK) == 0) (void) 0;
|
||||
SPC0->SRAMCTL &= ~SPC_SRAMCTL_REQ_MASK;
|
||||
hal_set_sysclk(2, 0, 3); // Run from SIRC meanwhile
|
||||
SCG0->FIRCCSR &= ~SCG_FIRCCSR_LK_MASK; // Unlock
|
||||
SCG0->FIRCCSR = SCG_FIRCCSR_FIRCERR_MASK; // Disable, clear error
|
||||
SCG0->FIRCCFG = SCG_FIRCCFG_RANGE(2); // 96 MHz
|
||||
SCG0->FIRCCSR |= SCG_FIRCCSR_FIRCEN_MASK;
|
||||
while ((SCG0->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) == 0) (void) 0;
|
||||
hal_set_sysclk(3, 0, 3); // FIRC, core / 1, slow / 4
|
||||
}
|
||||
|
||||
// Set the CPU clock to 96 MHz, then work out SystemCoreClock from the SCG
|
||||
// clock source and core divider
|
||||
static inline void hal_clock_init(void) {
|
||||
uint32_t csr, freq = 0;
|
||||
hal_clock_96mhz();
|
||||
csr = SCG0->CSR;
|
||||
uint32_t src = (csr & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT;
|
||||
uint32_t div = ((csr & SCG_CSR_DIVCORE_MASK) >> SCG_CSR_DIVCORE_SHIFT) + 1;
|
||||
if (src == 2) freq = SIRC_FREQUENCY; // Slow IRC
|
||||
if (src == 3) freq = hal_firc_freq(); // Fast IRC
|
||||
if (freq == 0) freq = SIRC_FREQUENCY; // Unknown source, assume reset value
|
||||
SystemCoreClock = freq / div;
|
||||
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
|
||||
}
|
||||
|
||||
// Enable peripheral clock and take it out of reset, from given clock source.
|
||||
// See CLOCK_SetIpSrc() and CLOCK_EnableClock() in fsl_clock.h
|
||||
static inline void hal_periph_clock(volatile uint32_t *mrcc, uint32_t src) {
|
||||
uint32_t v = (*mrcc & ~(MRCC_CC_MASK | MRCC_MUX_MASK | MRCC_DIV_MASK)) |
|
||||
MRCC_MUX(src);
|
||||
*mrcc = v; // Source, clock still off
|
||||
*mrcc = v | 1U; // CC = 1: clock on
|
||||
if (*mrcc & MRCC_PR_MASK) *mrcc |= MRCC_RSTB_MASK; // Release reset
|
||||
__DSB();
|
||||
}
|
||||
|
||||
// LPUART1 is wired to the MCU-Link debug probe USB serial port.
|
||||
// TX = PTC3, RX = PTC2, both pin mux alternative 3. See board.h, pin_mux.c
|
||||
static inline void hal_uart_init(LPUART_Type *uart, unsigned long baud) {
|
||||
uint32_t src = MRCC_SRC_FRO192M, freq = hal_firc_freq();
|
||||
uint32_t best_osr = 16, best_sbr = 1, best_err = UINT32_MAX, osr;
|
||||
if (freq == 0) src = MRCC_SRC_FRO6M, freq = SIRC_FREQUENCY; // FIRC off
|
||||
hal_periph_clock(&MRCC->MRCC_PORTC, 0);
|
||||
PORTC->PCR[2] = PORT_PCR_MUX(3); // RX
|
||||
PORTC->PCR[3] = PORT_PCR_MUX(3); // TX
|
||||
hal_periph_clock(&MRCC->MRCC_LPUART1, src);
|
||||
// Find the oversampling ratio (4..32) that gives the lowest baud rate error
|
||||
for (osr = 4; osr <= 32; osr++) {
|
||||
uint32_t sbr = (freq + osr * baud / 2) / (osr * baud), actual, err;
|
||||
if (sbr == 0 || sbr > 0x1fff) continue;
|
||||
actual = freq / (osr * sbr);
|
||||
err = actual > baud ? actual - baud : baud - actual;
|
||||
if (err < best_err) best_err = err, best_osr = osr, best_sbr = sbr;
|
||||
}
|
||||
uart->CTRL = 0; // Disable while configuring
|
||||
uart->BAUD = LPUART_BAUD_OSR(best_osr - 1) | LPUART_BAUD_SBR(best_sbr) |
|
||||
(best_osr < 8 ? LPUART_BAUD_BOTHEDGE_MASK : 0);
|
||||
uart->CTRL = LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK;
|
||||
}
|
||||
|
||||
static inline void hal_uart_write_byte(LPUART_Type *uart, uint8_t byte) {
|
||||
while ((uart->STAT & LPUART_STAT_TDRE_MASK) == 0) (void) 0;
|
||||
uart->DATA = byte;
|
||||
}
|
||||
|
||||
static inline void hal_uart_write_buf(LPUART_Type *uart, const char *buf,
|
||||
size_t len) {
|
||||
while (len-- > 0) hal_uart_write_byte(uart, *(const uint8_t *) buf++);
|
||||
}
|
||||
|
||||
// WDOG0 runs after reset: disable it, as SystemInit() in system_MCXW716C.c
|
||||
static inline void hal_wdog_disable(void) {
|
||||
while ((WDOG0->CS & WDOG_CS_RCS_MASK) == 0) (void) 0;
|
||||
if (WDOG0->CS & WDOG_CS_CMD32EN_MASK) {
|
||||
WDOG0->CNT = 0xD928C520U; // Unlock sequence
|
||||
} else {
|
||||
WDOG0->CNT = 0xC520U;
|
||||
WDOG0->CNT = 0xD928U;
|
||||
}
|
||||
while ((WDOG0->CS & WDOG_CS_ULK_MASK) == 0) (void) 0;
|
||||
WDOG0->TOVAL = 0xFFFF;
|
||||
WDOG0->CS = (WDOG0->CS & ~WDOG_CS_EN_MASK) | WDOG_CS_UPDATE_MASK;
|
||||
while ((WDOG0->CS & WDOG_CS_RCS_MASK) == 0) (void) 0;
|
||||
}
|
||||
|
||||
static inline void hal_sys_init(void) {
|
||||
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
|
||||
hal_wdog_disable();
|
||||
}
|
||||
|
||||
// 802.15.4 (O-QPSK 250 kbps) radio register setup for the MCXW71 transceiver.
|
||||
// Values are taken from the NXP XCVR driver, release/25.06.00, configs/gen45:
|
||||
// XCVR_RadioGenRegSetup() and XCVR_RadioGenRBMESetup() with
|
||||
// xcvr_oqpsk_802p15p4_250kbps_full_config and xcvr_ble_uncoded_config.
|
||||
// https://github.com/nxp-mcuxpresso/mcuxsdk-middleware-xcvr
|
||||
// Copyright 2016 Freescale Semiconductor, Inc.
|
||||
// Copyright 2018-2023 NXP
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// One radio register write
|
||||
struct w71_radio_reg {
|
||||
volatile uint32_t *reg; // Register address
|
||||
uint32_t val; // Value to write
|
||||
};
|
||||
|
||||
// Register writes, in the order the NXP driver performs them
|
||||
static const struct w71_radio_reg s_radio_regs[] = {
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[0].DMD_WAVE_REG0, 0x0420b3d3},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[0].DMD_WAVE_REG1, 0x31d78f00},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[0].DMD_WAVE_REG2, 0x00025a6d},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[1].DMD_WAVE_REG0, 0x0420b3d3},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[1].DMD_WAVE_REG1, 0x38d78f00},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[1].DMD_WAVE_REG2, 0x0000403c},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[2].DMD_WAVE_REG0, 0x3c00420b},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[2].DMD_WAVE_REG1, 0x082c8100},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[2].DMD_WAVE_REG2, 0x0003c004},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[3].DMD_WAVE_REG0, 0x3c00420b},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[3].DMD_WAVE_REG1, 0x0f2c8100},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[3].DMD_WAVE_REG2, 0x0001b5d3},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[4].DMD_WAVE_REG0, 0x0403ce35},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[4].DMD_WAVE_REG1, 0x31d78f00},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[4].DMD_WAVE_REG2, 0x00025a6d},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[5].DMD_WAVE_REG0, 0x0403ce35},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[5].DMD_WAVE_REG1, 0x38d78f00},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[5].DMD_WAVE_REG2, 0x0000403c},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[6].DMD_WAVE_REG0, 0x3ce35c6d},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[6].DMD_WAVE_REG1, 0x082c8100},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[6].DMD_WAVE_REG2, 0x0003c004},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[7].DMD_WAVE_REG0, 0x3ce35c6d},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[7].DMD_WAVE_REG1, 0x0f2c8100},
|
||||
{&XCVR_2P4GHZ_PHY->DEMOD_WAVE[7].DMD_WAVE_REG2, 0x0001b5d3},
|
||||
{&XCVR_2P4GHZ_PHY->DMD_CTRL0, 0x6d940101},
|
||||
{&XCVR_2P4GHZ_PHY->DMD_CTRL1, 0xa8049008},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_CFG0, 0x15001502},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_CFG1, 0x0f080020},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_CFG2, 0x40000000},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_FAD_CFG, 0x00000000},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_FAD_CTRL, 0x00000000},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_PD_CFG0, 0x0000ff0c},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_PD_CFG1, 0x00000055},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_PD_CFG2, 0x00f600f6},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_PD_PH[0], 0x00030503},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_PD_PH[1], 0x003d3b3d},
|
||||
{&XCVR_2P4GHZ_PHY->FSK_PT, 0x00000048},
|
||||
{&XCVR_2P4GHZ_PHY->LR_AA_CFG, 0x06020696},
|
||||
{&XCVR_2P4GHZ_PHY->LR_PD_CFG, 0x0001019a},
|
||||
{&XCVR_2P4GHZ_PHY->LR_PD_PH[0], 0x3d383028},
|
||||
{&XCVR_2P4GHZ_PHY->LR_PD_PH[1], 0x20283038},
|
||||
{&XCVR_2P4GHZ_PHY->LR_PD_PH[2], 0x03081018},
|
||||
{&XCVR_2P4GHZ_PHY->LR_PD_PH[3], 0x20181008},
|
||||
{&XCVR_2P4GHZ_PHY->MISC, 0x03ff00a0},
|
||||
{&XCVR_2P4GHZ_PHY->PREPHY_MISC, 0x00000c10},
|
||||
{&XCVR_2P4GHZ_PHY->RTT_CTRL, 0x00004166},
|
||||
{&XCVR_2P4GHZ_PHY->RTT_REF, 0x00806348},
|
||||
{&XCVR_2P4GHZ_PHY->SM_CFG, 0x00a02432},
|
||||
{&RADIO_CTRL->LL_CTRL, 0x00000001},
|
||||
{&XCVR_ANALOG->LDO_0, 0x04440400},
|
||||
{&XCVR_ANALOG->LDO_1, 0x00000005},
|
||||
{&XCVR_ANALOG->PLL, 0x00000040},
|
||||
{&XCVR_ANALOG->RX_0, 0x01000002},
|
||||
{&XCVR_ANALOG->RX_1, 0x00022008},
|
||||
{&XCVR_ANALOG->TX_DAC_PA, 0x01000000},
|
||||
{&XCVR_ANALOG->XO_DIST, 0x00000000},
|
||||
{&XCVR_MISC->IPS_FO_ADDR[0], 0x00000370},
|
||||
{&XCVR_MISC->IPS_FO_ADDR[1], 0x0000002c},
|
||||
{&XCVR_MISC->IPS_FO_DRS0_DATA[0], 0x00000000},
|
||||
{&XCVR_MISC->IPS_FO_DRS0_DATA[1], 0x00000000},
|
||||
{&XCVR_MISC->IPS_FO_DRS1_DATA[0], 0x00000000},
|
||||
{&XCVR_MISC->IPS_FO_DRS1_DATA[1], 0x00000000},
|
||||
{&XCVR_MISC->LDO_TRIM_0, 0x00020000},
|
||||
{&XCVR_MISC->LDO_TRIM_1, 0x00000000},
|
||||
{&XCVR_MISC->XCVR_CTRL, 0x00130180},
|
||||
{&XCVR_PLL_DIG->CHAN_MAP, 0x00040000},
|
||||
{&XCVR_PLL_DIG->CHAN_MAP_EXT, 0x00100000},
|
||||
{&XCVR_PLL_DIG->DATA_RATE_OVRD_CTRL1, 0x00000089},
|
||||
{&XCVR_PLL_DIG->DATA_RATE_OVRD_CTRL2, 0x00180000},
|
||||
{&XCVR_PLL_DIG->DELAY_MATCH, 0x00050102},
|
||||
{&XCVR_PLL_DIG->HPMCAL_CTRL, 0x00002000},
|
||||
{&XCVR_PLL_DIG->HPM_BUMP, 0x00440144},
|
||||
{&XCVR_PLL_DIG->HPM_CAL_TIMING, 0x00000000},
|
||||
{&XCVR_PLL_DIG->HPM_CTRL, 0x00840000},
|
||||
{&XCVR_PLL_DIG->HPM_SDM_RES, 0x00ff0000},
|
||||
{&XCVR_PLL_DIG->LOCK_DETECT, 0x0e1a1800},
|
||||
{&XCVR_PLL_DIG->LPM_CTRL, 0x88880a00},
|
||||
{&XCVR_PLL_DIG->LPM_SDM_CTRL1, 0x00260000},
|
||||
{&XCVR_PLL_DIG->MOD_CTRL, 0x80000000},
|
||||
{&XCVR_PLL_DIG->PLL_DATARATE_CTRL, 0x04126644},
|
||||
{&XCVR_PLL_DIG->TUNING_CAP_RX_CTRL, 0x00000000},
|
||||
{&XCVR_PLL_DIG->TUNING_CAP_TX_CTRL, 0x00ffffa3},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_0_3, 0x737f0502},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_0_3_DRS, 0x0f7f3a01},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_10_11, 0x00ef0061},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_10_11_DRS, 0x012b0021},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_4_7, 0xf8221478},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_4_7_DRS, 0x3c06617f},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_8_9, 0x01d501bc},
|
||||
{&XCVR_RX_DIG->ACQ_FILT_8_9_DRS, 0x019401f3},
|
||||
{&XCVR_RX_DIG->AGC_CTRL, 0x587c8d19},
|
||||
{&XCVR_RX_DIG->AGC_CTRL_STAT, 0x0000872c},
|
||||
{&XCVR_RX_DIG->AGC_IDX0_GAIN_CFG, 0x000000f2},
|
||||
{&XCVR_RX_DIG->AGC_IDX0_GAIN_VAL, 0x000003fd},
|
||||
{&XCVR_RX_DIG->AGC_IDX0_THR, 0x0000001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX10_GAIN_CFG, 0x00004a03},
|
||||
{&XCVR_RX_DIG->AGC_IDX10_GAIN_VAL, 0x000000eb},
|
||||
{&XCVR_RX_DIG->AGC_IDX10_THR, 0x0096001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX11_GAIN_CFG, 0x00007e03},
|
||||
{&XCVR_RX_DIG->AGC_IDX11_GAIN_VAL, 0x000000fa},
|
||||
{&XCVR_RX_DIG->AGC_IDX11_THR, 0x00780000},
|
||||
{&XCVR_RX_DIG->AGC_IDX1_GAIN_CFG, 0x000001b2},
|
||||
{&XCVR_RX_DIG->AGC_IDX1_GAIN_VAL, 0x0000000b},
|
||||
{&XCVR_RX_DIG->AGC_IDX1_THR, 0x015e001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX2_GAIN_CFG, 0x00000123},
|
||||
{&XCVR_RX_DIG->AGC_IDX2_GAIN_VAL, 0x00000026},
|
||||
{&XCVR_RX_DIG->AGC_IDX2_THR, 0x00c8001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX3_GAIN_CFG, 0x00000113},
|
||||
{&XCVR_RX_DIG->AGC_IDX3_GAIN_VAL, 0x0000003c},
|
||||
{&XCVR_RX_DIG->AGC_IDX3_THR, 0x00c8001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX4_GAIN_CFG, 0x00000083},
|
||||
{&XCVR_RX_DIG->AGC_IDX4_GAIN_VAL, 0x00000057},
|
||||
{&XCVR_RX_DIG->AGC_IDX4_THR, 0x00c8001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX5_GAIN_CFG, 0x00000183},
|
||||
{&XCVR_RX_DIG->AGC_IDX5_GAIN_VAL, 0x0000006d},
|
||||
{&XCVR_RX_DIG->AGC_IDX5_THR, 0x00fa001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX6_GAIN_CFG, 0x00000203},
|
||||
{&XCVR_RX_DIG->AGC_IDX6_GAIN_VAL, 0x00000087},
|
||||
{&XCVR_RX_DIG->AGC_IDX6_THR, 0x012c001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX7_GAIN_CFG, 0x00000603},
|
||||
{&XCVR_RX_DIG->AGC_IDX7_GAIN_VAL, 0x000000a0},
|
||||
{&XCVR_RX_DIG->AGC_IDX7_THR, 0x012c001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX8_GAIN_CFG, 0x00000e03},
|
||||
{&XCVR_RX_DIG->AGC_IDX8_GAIN_VAL, 0x000000b7},
|
||||
{&XCVR_RX_DIG->AGC_IDX8_THR, 0x012c001e},
|
||||
{&XCVR_RX_DIG->AGC_IDX9_GAIN_CFG, 0x00002203},
|
||||
{&XCVR_RX_DIG->AGC_IDX9_GAIN_VAL, 0x000000d2},
|
||||
{&XCVR_RX_DIG->AGC_IDX9_THR, 0x0096001e},
|
||||
{&XCVR_RX_DIG->AGC_MIS_GAIN_CFG, 0x00000001},
|
||||
{&XCVR_RX_DIG->AGC_THR_FAST, 0x0190000f},
|
||||
{&XCVR_RX_DIG->AGC_THR_FAST_DRS, 0x0190001e},
|
||||
{&XCVR_RX_DIG->AGC_THR_MIS, 0x00960028},
|
||||
{&XCVR_RX_DIG->AGC_TIMING0, 0x04102398},
|
||||
{&XCVR_RX_DIG->AGC_TIMING0_DRS, 0x40002000},
|
||||
{&XCVR_RX_DIG->AGC_TIMING1, 0x190242a7},
|
||||
{&XCVR_RX_DIG->AGC_TIMING1_DRS, 0x000002a7},
|
||||
{&XCVR_RX_DIG->AGC_TIMING2, 0xe000007f},
|
||||
{&XCVR_RX_DIG->AGC_TIMING2_DRS, 0x0000007f},
|
||||
{&XCVR_RX_DIG->CTRL0, 0x68063083},
|
||||
{&XCVR_RX_DIG->CTRL0_DRS, 0x000030c0},
|
||||
{&XCVR_RX_DIG->CTRL1, 0x00000180},
|
||||
{&XCVR_RX_DIG->DCOC_CTRL0, 0x04332d28},
|
||||
{&XCVR_RX_DIG->DCOC_CTRL0_DRS, 0x00000114},
|
||||
{&XCVR_RX_DIG->DCOC_CTRL1, 0x00000000},
|
||||
{&XCVR_RX_DIG->DEMOD_FILT_0_1, 0x01fe01fd},
|
||||
{&XCVR_RX_DIG->DEMOD_FILT_0_1_DRS, 0x00ff0003},
|
||||
{&XCVR_RX_DIG->DEMOD_FILT_2_4, 0x0ba20824},
|
||||
{&XCVR_RX_DIG->DEMOD_FILT_2_4_DRS, 0x124221ff},
|
||||
{&XCVR_RX_DIG->NB_RSSI_CTRL0, 0xed472234},
|
||||
{&XCVR_RX_DIG->NB_RSSI_CTRL1, 0x00000000},
|
||||
{&XCVR_RX_DIG->RCCAL_CTRL0, 0x0000003a},
|
||||
{&XCVR_RX_DIG->RSSI_GLOBAL_CTRL, 0x80008330},
|
||||
{&XCVR_RX_DIG->WB_RSSI_CTRL, 0x00223342},
|
||||
{&XCVR_TSM->CTRL, 0xff000000},
|
||||
{&XCVR_TSM->END_OF_SEQ, 0x5c5a7270},
|
||||
{&XCVR_TSM->FAST_CTRL1, 0x24006f00},
|
||||
{&XCVR_TSM->FAST_CTRL2, 0x66284208},
|
||||
{&XCVR_TSM->FAST_CTRL3, 0x18001800},
|
||||
{&XCVR_TSM->RECYCLE_COUNT, 0x00001258},
|
||||
{&XCVR_TSM->TIMING00, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING01, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING02, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING03, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING04, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING05, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING06, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING07, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING08, 0xffffffff},
|
||||
{&XCVR_TSM->TIMING09, 0x5700ffff},
|
||||
{&XCVR_TSM->TIMING10, 0x11081108},
|
||||
{&XCVR_TSM->TIMING11, 0x5b137113},
|
||||
{&XCVR_TSM->TIMING12, 0x5b19714f},
|
||||
{&XCVR_TSM->TIMING13, 0x572dffff},
|
||||
{&XCVR_TSM->TIMING14, 0x0000716f},
|
||||
{&XCVR_TSM->TIMING15, 0x5b58716f},
|
||||
{&XCVR_TSM->TIMING16, 0x59580000},
|
||||
{&XCVR_TSM->TIMING17, 0x5b580000},
|
||||
{&XCVR_TSM->TIMING18, 0x5b580000},
|
||||
{&XCVR_TSM->TIMING19, 0x11061106},
|
||||
{&XCVR_TSM->TIMING20, 0x11001100},
|
||||
{&XCVR_TSM->TIMING21, 0x19001100},
|
||||
{&XCVR_TSM->TIMING22, 0x58006f00},
|
||||
{&XCVR_TSM->TIMING23, 0x58006f00},
|
||||
{&XCVR_TSM->TIMING24, 0x5b007100},
|
||||
{&XCVR_TSM->TIMING25, 0x5c007200},
|
||||
{&XCVR_TSM->TIMING26, 0x5c007200},
|
||||
{&XCVR_TSM->TIMING27, 0x5c007200},
|
||||
{&XCVR_TSM->TIMING28, 0x5c007200},
|
||||
{&XCVR_TSM->TIMING29, 0xffff7200},
|
||||
{&XCVR_TSM->TIMING30, 0x5c00ffff},
|
||||
{&XCVR_TSM->TIMING31, 0x5b087108},
|
||||
{&XCVR_TSM->TIMING32, 0x1911ffff},
|
||||
{&XCVR_TSM->TIMING33, 0x23115a11},
|
||||
{&XCVR_TSM->TIMING34, 0x5b117111},
|
||||
{&XCVR_TSM->TIMING35, 0x5b117111},
|
||||
{&XCVR_TSM->TIMING36, 0x5b117111},
|
||||
{&XCVR_TSM->TIMING37, 0x5b117111},
|
||||
{&XCVR_TSM->TIMING38, 0x5b117111},
|
||||
{&XCVR_TSM->TIMING39, 0x5b2b7111},
|
||||
{&XCVR_TSM->TIMING40, 0xffff7111},
|
||||
{&XCVR_TSM->TIMING41, 0xffff7111},
|
||||
{&XCVR_TSM->TIMING42, 0x5b127112},
|
||||
{&XCVR_TSM->TIMING43, 0x5b12ffff},
|
||||
{&XCVR_TSM->TIMING44, 0x5b12ffff},
|
||||
{&XCVR_TSM->TIMING45, 0xffff7112},
|
||||
{&XCVR_TSM->TIMING46, 0xffff716f},
|
||||
{&XCVR_TSM->TIMING47, 0x5b137157},
|
||||
{&XCVR_TSM->TIMING48, 0x5b23715a},
|
||||
{&XCVR_TSM->TIMING49, 0x5b23715a},
|
||||
{&XCVR_TSM->TIMING50, 0x5b2bffff},
|
||||
{&XCVR_TSM->TIMING51, 0x5b2bffff},
|
||||
{&XCVR_TSM->TIMING52, 0xffffffff},
|
||||
{&XCVR_TSM->WU_LATENCY, 0x00060006},
|
||||
{&XCVR_TX_DIG->DATARATE_CONFIG_FILTER_CTRL, 0x00010000},
|
||||
{&XCVR_TX_DIG->DATARATE_CONFIG_FSK_CTRL, 0x08001800},
|
||||
{&XCVR_TX_DIG->DATARATE_CONFIG_GFSK_CTRL, 0x00000804},
|
||||
{&XCVR_TX_DIG->DATA_PADDING_CTRL, 0x00001012},
|
||||
{&XCVR_TX_DIG->DATA_PADDING_CTRL_1, 0x00001600},
|
||||
{&XCVR_TX_DIG->DATA_PADDING_CTRL_2, 0x08001800},
|
||||
{&XCVR_TX_DIG->FSK_CTRL, 0x04001c00},
|
||||
{&XCVR_TX_DIG->GFSK_COEFF_0_1, 0x00040001},
|
||||
{&XCVR_TX_DIG->GFSK_COEFF_2_3, 0x0028000d},
|
||||
{&XCVR_TX_DIG->GFSK_COEFF_4_5, 0x00c00063},
|
||||
{&XCVR_TX_DIG->GFSK_COEFF_6_7, 0x0176012c},
|
||||
{&XCVR_TX_DIG->GFSK_CTRL, 0x000003fd},
|
||||
{&XCVR_TX_DIG->IMAGE_FILTER_CTRL, 0x00000000},
|
||||
{&XCVR_TX_DIG->PA_CTRL, 0x00020126},
|
||||
{&XCVR_TX_DIG->PA_RAMP_TBL0, 0x06040201},
|
||||
{&XCVR_TX_DIG->PA_RAMP_TBL1, 0x14100c09},
|
||||
{&XCVR_TX_DIG->PA_RAMP_TBL2, 0x26211c18},
|
||||
{&XCVR_TX_DIG->PA_RAMP_TBL3, 0x3c38322c},
|
||||
{&XCVR_TX_DIG->SWITCH_TX_CTRL, 0x00000000},
|
||||
{&XCVR_TX_DIG->TXDIG_CTRL, 0x00000007},
|
||||
{&XCVR_2P4GHZ_PHY->DMD_CTRL1, 0x8c049008},
|
||||
{&RBME->CRCW_CFG, 0x00000001},
|
||||
{&RBME->CRCW_CFG2, 0x00000000},
|
||||
{&RBME->CRCW_CFG3, 0x00000403},
|
||||
{&RBME->CRC_INIT, 0x55555500},
|
||||
{&RBME->CRC_PHR_SZ, 0x00000002},
|
||||
{&RBME->CRC_POLY, 0x00065b00},
|
||||
{&RBME->CRC_XOR_OUT, 0x00000000},
|
||||
{&RBME->FCP_CFG, 0x00000000},
|
||||
{&RBME->FEC_BSZ_OV_B4SP, 0x00000000},
|
||||
{&RBME->FEC_CFG1, 0x00000000},
|
||||
{&RBME->FEC_CFG2, 0x00000000},
|
||||
{&RBME->FRAME_OVER_SZ, 0x00000000},
|
||||
{&RBME->NPAYL_OVER_SZ, 0x00000000},
|
||||
{&RBME->PKT_SZ, 0x00244000},
|
||||
{&RBME->SPREAD_CFG, 0x00000000},
|
||||
{&RBME->WHITEN_CFG, 0x00410705},
|
||||
{&RBME->WHITEN_POLY, 0x00000004},
|
||||
{&RBME->WHITEN_SZ_THR, 0x00000000},
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
/* MCXW716C memory map, see MCUXpresso SDK gcc/mcxw716_flash.ld */
|
||||
ENTRY(Reset_Handler);
|
||||
MEMORY {
|
||||
flash(rx) : ORIGIN = 0x00000000, LENGTH = 512k /* Upper half: OTA staging */
|
||||
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 112k
|
||||
}
|
||||
__StackTop = ORIGIN(sram) + LENGTH(sram); /* Stack points here */
|
||||
__StackLimit = __StackTop - 8192; /* MSPLIM, see startup */
|
||||
|
||||
SECTIONS {
|
||||
.vectors : { KEEP(*(.isr_vector)) . = ALIGN(4); } > flash
|
||||
.text : { *(.text* .text.*) } > flash
|
||||
.rodata : { *(.rodata*) . = ALIGN(4); } > flash
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
_sdata = .;
|
||||
*(.first_data)
|
||||
*(.iram .iram.*) /* OTA flash operations, copied to RAM by startup */
|
||||
*(.data SORT(.data.*))
|
||||
. = ALIGN(4);
|
||||
__data_end__ = .;
|
||||
_edata = .;
|
||||
} > sram AT > flash
|
||||
__etext = LOADADDR(.data); /* Startup copies .data from here */
|
||||
|
||||
.bss : {
|
||||
__bss_start__ = .;
|
||||
_sbss = .;
|
||||
*(.bss SORT(.bss.*) COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .;
|
||||
} > sram
|
||||
|
||||
. = ALIGN(8);
|
||||
_end = .; /* Start of heap, see _sbrk() in hal.c */
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2026 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// IPv4 over IEEE 802.15.4 on FRDM-MCXW71, Mongoose built-in TCP/IP stack.
|
||||
// The radio carries Ethernet frames, channel 15, PAN ID 0xabcd. With the
|
||||
// FRDM-RW612 eth_radio_bridge tutorial, gets an address from the LAN's DHCP
|
||||
// server and is reachable from the LAN. Serves pages on ports 80 and 443
|
||||
|
||||
#include "hal.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
#define UART_DEBUG LPUART1 // MCU-Link USB serial port
|
||||
|
||||
static void log_fn(char ch, void *param) {
|
||||
hal_uart_write_buf(param, &ch, 1);
|
||||
}
|
||||
|
||||
uint64_t mg_millis(void) {
|
||||
return hal_get_tick();
|
||||
}
|
||||
|
||||
// Self-signed P-256 certificate and key for the HTTPS listener. Created by:
|
||||
// openssl ecparam -genkey -name prime256v1 -noout -out key.pem
|
||||
// openssl req -x509 -key key.pem -out cert.pem -days 3650 -subj /CN=mg
|
||||
#define TLS_CERT \
|
||||
"-----BEGIN CERTIFICATE-----\n" \
|
||||
"MIIBgjCCASegAwIBAgIUIJOq77Qn7lHbH6WseMemeqorR50wCgYIKoZIzj0EAwIw\n" \
|
||||
"FjEUMBIGA1UEAwwLbnVjbGVvLWg3MjMwHhcNMjYxMDEyMTUwMjE5WhcNMzYxMDA5\n" \
|
||||
"MTUwMjE5WjAWMRQwEgYDVQQDDAtudWNsZW8taDcyMzBZMBMGByqGSM49AgEGCCqG\n" \
|
||||
"SM49AwEHA0IABB6IQJNmzrsdQL+2BnZYS7GYOaj7sz8f6cjBmz3n8D9Em19XodlU\n" \
|
||||
"uy4ybIvyhr766lL0ERoTmMUivb/lGmzx9C+jUzBRMB0GA1UdDgQWBBQqxMuc4gj7\n" \
|
||||
"MTMzreWlRMNI3QMqTzAfBgNVHSMEGDAWgBQqxMuc4gj7MTMzreWlRMNI3QMqTzAP\n" \
|
||||
"BgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQDY4xaJpuxq6b3rHK3b\n" \
|
||||
"lOIQyfkQX+orCRqQUkseplqpqwIhAKswZFNn+2zUNRRNY8+cHmdIwmdpsmxtoWYP\n" \
|
||||
"BCjX++LI\n" \
|
||||
"-----END CERTIFICATE-----\n"
|
||||
|
||||
#define TLS_KEY \
|
||||
"-----BEGIN EC PRIVATE KEY-----\n" \
|
||||
"MHcCAQEEIJ/GBl0TlD52q9PMg1KWaNIdXqp8b/HyIsABmBpqC+O1oAoGCCqGSM49\n" \
|
||||
"AwEHoUQDQgAEHohAk2bOux1Av7YGdlhLsZg5qPuzPx/pyMGbPefwP0SbX1eh2VS7\n" \
|
||||
"LjJsi/KGvvrqUvQRGhOYxSK9v+UabPH0Lw==\n" \
|
||||
"-----END EC PRIVATE KEY-----\n"
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_ACCEPT && c->is_tls) { // Accepted on the https:// listener
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
mg_http_reply(c, 200, "", "{%m:%llu}\n", MG_ESC("tick"), hal_get_tick());
|
||||
} else if (mg_match(hm->uri, mg_str("/api/crash"), NULL)) {
|
||||
__asm volatile("udf #0"); // Trigger HardFault
|
||||
} else {
|
||||
mg_http_reply(c, 200, "",
|
||||
"Hi from Mongoose!\n"
|
||||
"tick: %llu\n"
|
||||
"ram used: %zu\n"
|
||||
"ram free: %zu\n",
|
||||
hal_get_tick(), hal_ram_used(), hal_ram_free());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
hal_clock_init();
|
||||
hal_uart_init(UART_DEBUG, 115200);
|
||||
mg_log_set_fn(log_fn, UART_DEBUG);
|
||||
|
||||
if (!hal_radio_init()) MG_ERROR(("Radio init failed"));
|
||||
|
||||
struct mg_mgr mgr;
|
||||
mg_mgr_init(&mgr);
|
||||
mg_http_listen(&mgr, "http://0.0.0.0:80", http_ev_handler, NULL);
|
||||
mg_http_listen(&mgr, "https://0.0.0.0:443", http_ev_handler, NULL);
|
||||
mg_mqtt_init(&mgr);
|
||||
|
||||
MG_INFO(("Initialised. CPU clock: %lu MHz", SystemCoreClock / 1000000));
|
||||
MG_INFO(("RAM used: %zu, free: %zu", hal_ram_used(), hal_ram_free()));
|
||||
MG_INFO(("Crash record: %M", mg_print_crash_record));
|
||||
|
||||
for (;;) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
mg_mqtt_poll(&mgr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "MCXW716C.h"
|
||||
|
||||
// See https://mongoose.ws/docs/getting-started/build-environment/
|
||||
#define MG_ARCH MG_ARCH_ARMGCC
|
||||
#define MG_TLS MG_TLS_BUILTIN
|
||||
#define MG_OTA MG_OTA_MCXW71
|
||||
|
||||
#define MG_ENABLE_TCPIP 1
|
||||
#define MG_ENABLE_DRIVER_MCXW71 1
|
||||
#define MG_ENABLE_CUSTOM_MILLIS 1
|
||||
#define MG_ENABLE_CUSTOM_RANDOM 1
|
||||
#define MG_ENABLE_TCPIP_TCPRTX 1 // Link can be lossy, enable retransmit
|
||||
|
||||
// Stable MAC, so the DHCP address stays the same across reboots: a hash of
|
||||
// the 128-bit chip unique ID, MSCM UID, locally administered
|
||||
#define MG_SET_MAC_ADDRESS(mac) \
|
||||
do { \
|
||||
uint8_t b_[32]; \
|
||||
mg_sha256(b_, (uint8_t *) MSCM->UID, sizeof(MSCM->UID)); \
|
||||
(mac)[0] = 2, (mac)[1] = b_[1], (mac)[2] = b_[2], (mac)[3] = b_[3]; \
|
||||
(mac)[4] = b_[4], (mac)[5] = b_[5]; \
|
||||
} while (0)
|
||||
@@ -0,0 +1,63 @@
|
||||
# Environment setup: https://mongoose.ws/documentation/tutorials/tools/
|
||||
|
||||
MGDIR = ../../../..
|
||||
|
||||
CFLAGS = -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion
|
||||
CFLAGS += -Wformat-truncation -fno-common -Wno-conversion -Wno-sign-conversion
|
||||
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
|
||||
CFLAGS += -Wno-cast-function-type -Wno-old-style-declaration
|
||||
CFLAGS += -Wno-unused-parameter
|
||||
CFLAGS += -I. -I$(MGDIR) -Imongoose -Icmsis_core/CMSIS/Core/Include/
|
||||
CFLAGS += $(addprefix -Icmsis_rw612/devices/RW612/drivers/romapi/,bootloader nboot otp iap flexspi)
|
||||
CFLAGS += -Icmsis_rw612/devices/RW612/ -Icmsis_rw612/devices/RW612/periph/ -Icmsis_rw612/devices/RW612/drivers/
|
||||
CFLAGS += -DCPU_RW612ETA2I -DCPU_RW612ETA2I_cm33_no_dsp
|
||||
CFLAGS += -DBOOT_HEADER_ENABLE=1
|
||||
CFLAGS += -DRADIO_FW='"$(RADIO_FW)"'
|
||||
CFLAGS += -mcpu=cortex-m33+nodsp -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 $(CFLAGS_EXTRA)
|
||||
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs=nano.specs -lc -lgcc -Wl,--gc-sections
|
||||
|
||||
SOURCES = main.c hal.c radio.c startup.c flexspi.c flash_config.c $(MGDIR)/mongoose.c
|
||||
SOURCES += cmsis_rw612/devices/RW612/drivers/fsl_clock.c
|
||||
SOURCES += cmsis_rw612/devices/RW612/drivers/fsl_trng.c
|
||||
SOURCES += cmsis_rw612/devices/RW612/drivers/fsl_reset.c
|
||||
SOURCES += $(addprefix cmsis_rw612/devices/RW612/drivers/,fsl_power.c fsl_ocotp.c \
|
||||
romapi/bootloader/fsl_romapi.c romapi/nboot/fsl_romapi_nboot.c romapi/otp/fsl_romapi_otp.c)
|
||||
|
||||
# NXP BLE/802.15.4 combo firmware for CPU2, linked into our image. NXP license:
|
||||
# https://github.com/NXP/wifi_nb_fw/blob/nxp-v4.4.3/LICENSE.txt
|
||||
RADIO_FW = rw61x_sb_ble_15d4_combo_a2.bin
|
||||
RADIO_FW_URL = https://github.com/NXP/wifi_nb_fw/raw/nxp-v4.4.3/rw61x/$(RADIO_FW)
|
||||
RADIO_FW_SHA256 = 2efac0d771e371377d57159c40f0909c7ecc6f6b950ce69ed2a3e02ac7eb686a
|
||||
|
||||
all build: firmware.bin
|
||||
|
||||
firmware.bin: firmware.elf
|
||||
arm-none-eabi-objcopy -O binary $< $@
|
||||
arm-none-eabi-size --format=berkeley $<
|
||||
|
||||
firmware.elf: cmsis_core cmsis_rw612 $(RADIO_FW) $(SOURCES) $(wildcard *.h) link.ld Makefile mongoose_config.h
|
||||
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
cmsis_core:
|
||||
git clone -q -c advice.detachedHead=false --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
|
||||
|
||||
$(RADIO_FW):
|
||||
curl -sL $(RADIO_FW_URL) -o $@.tmp
|
||||
echo "$(RADIO_FW_SHA256) $@.tmp" | shasum -a 256 -c - >/dev/null
|
||||
mv $@.tmp $@
|
||||
|
||||
cmsis_rw612:
|
||||
curl -sL https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.RW612_DFP.25.12.00.pack -o NXP.RW612_DFP.25.12.00.pack
|
||||
unzip -q NXP.RW612_DFP.25.12.00.pack -d $@
|
||||
rm NXP.RW612_DFP.25.12.00.pack
|
||||
|
||||
# Show all symbols sorted by size
|
||||
show_symbols_sorted_by_size: firmware.bin
|
||||
arm-none-eabi-readelf -sW firmware.elf | sed 1,3d | sed 's,^.*: ,,' | tr -s ' ' | cut -d ' ' -f 2,7 | sort -nk1 | grep -v '^0 '
|
||||
|
||||
flash: firmware.bin
|
||||
(echo 'loadfile firmware.elf'; echo 'reset'; echo 'exit';) | JLinkExe -device RW612 -if SWD -speed 4000 -autoconnect 1 -NoGui 1 -ExitOnError 1
|
||||
# JRun --nogui --device RW612 --if SWD firmware.elf
|
||||
|
||||
clean:
|
||||
rm -rf firmware.* cmsis_* mongoose/mongoose.* $(RADIO_FW)
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2021-2024 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include "flash_config.h"
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.flash_config"
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
#if defined(BOOT_HEADER_ENABLE) && (BOOT_HEADER_ENABLE == 1)
|
||||
#if defined(__ARMCC_VERSION) || defined(__GNUC__)
|
||||
__attribute__((section(".flash_conf"), used))
|
||||
#elif defined(__ICCARM__)
|
||||
#pragma location = ".flash_conf"
|
||||
#endif
|
||||
const fc_flexspi_nor_config_t flexspi_config = {
|
||||
.memConfig =
|
||||
{
|
||||
.tag = FC_BLOCK_TAG,
|
||||
.version = FC_BLOCK_VERSION,
|
||||
.readSampleClkSrc = 1,
|
||||
.csHoldTime = 3,
|
||||
.csSetupTime = 3,
|
||||
.deviceModeCfgEnable = 1,
|
||||
.deviceModeSeq = {.seqNum = 1, .seqId = 2},
|
||||
.deviceModeArg = 0x02,
|
||||
.configCmdEnable = 0,
|
||||
.deviceType = 0x1,
|
||||
.sflashPadType = kSerialFlash_4Pads,
|
||||
.serialClkFreq = 5,
|
||||
.sflashA1Size = 0x4000000U,
|
||||
.sflashA2Size = 0,
|
||||
.sflashB1Size = 0,
|
||||
.sflashB2Size = 0,
|
||||
.lookupTable =
|
||||
{
|
||||
/* Read */
|
||||
[0] = FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0xEC, FC_RADDR_SDR, FC_FLEXSPI_4PAD, 0x20),
|
||||
[1] = FC_FLEXSPI_LUT_SEQ(FC_MODE8_SDR, FC_FLEXSPI_4PAD, 0xF0, FC_DUMMY_SDR, FC_FLEXSPI_4PAD, 0x04),
|
||||
[2] = FC_FLEXSPI_LUT_SEQ(FC_READ_SDR, FC_FLEXSPI_4PAD, 0x04, FC_STOP_EXE, FC_FLEXSPI_1PAD, 0x00),
|
||||
|
||||
/* Read Status */
|
||||
[4 * 1 + 0] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0x05, FC_READ_SDR, FC_FLEXSPI_1PAD, 0x04),
|
||||
|
||||
/* Write Status */
|
||||
[4 * 2 + 0] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0x31, FC_WRITE_SDR, FC_FLEXSPI_1PAD, 0x01),
|
||||
|
||||
/* Write Enable */
|
||||
[4 * 3 + 0] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0x06, FC_STOP_EXE, FC_FLEXSPI_1PAD, 0x00),
|
||||
|
||||
/* Sector erase */
|
||||
[4 * 5 + 0] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0x21, FC_RADDR_SDR, FC_FLEXSPI_1PAD, 0x20),
|
||||
|
||||
/* Block erase */
|
||||
[4 * 8 + 0] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0xDC, FC_RADDR_SDR, FC_FLEXSPI_1PAD, 0x20),
|
||||
|
||||
/* Page program */
|
||||
[4 * 9 + 0] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0x34, FC_RADDR_SDR, FC_FLEXSPI_1PAD, 0x20),
|
||||
[4 * 9 + 1] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_WRITE_SDR, FC_FLEXSPI_4PAD, 0x00, FC_STOP_EXE, FC_FLEXSPI_1PAD, 0x00),
|
||||
|
||||
/* chip erase */
|
||||
[4 * 11 + 0] =
|
||||
FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, FC_FLEXSPI_1PAD, 0xC7, FC_STOP_EXE, FC_FLEXSPI_1PAD, 0x00),
|
||||
},
|
||||
},
|
||||
.pageSize = 0x100,
|
||||
.sectorSize = 0x1000,
|
||||
.ipcmdSerialClkFreq = 0,
|
||||
.blockSize = 0x10000,
|
||||
.fcb_fill[0] = 0xFFFFFFFF,
|
||||
};
|
||||
#endif /* BOOT_HEADER_ENABLE */
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright 2021-2023 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __FLASH_CONFIG__
|
||||
#define __FLASH_CONFIG__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief FLASH_CONFIG driver version 2.0.0. */
|
||||
#define FSL_FLASH_CONFIG_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definition
|
||||
******************************************************************************/
|
||||
|
||||
/* FLEXSPI memory config block related defintions */
|
||||
#define FC_BLOCK_TAG (0x42464346)
|
||||
#define FC_BLOCK_VERSION (0x00000000)
|
||||
|
||||
#define FC_CMD_SDR 0x01
|
||||
#define FC_CMD_DDR 0x21
|
||||
#define FC_RADDR_SDR 0x02
|
||||
#define FC_RADDR_DDR 0x22
|
||||
#define FC_CADDR_SDR 0x03
|
||||
#define FC_CADDR_DDR 0x23
|
||||
#define FC_MODE1_SDR 0x04
|
||||
#define FC_MODE1_DDR 0x24
|
||||
#define FC_MODE2_SDR 0x05
|
||||
#define FC_MODE2_DDR 0x25
|
||||
#define FC_MODE4_SDR 0x06
|
||||
#define FC_MODE4_DDR 0x26
|
||||
#define FC_MODE8_SDR 0x07
|
||||
#define FC_MODE8_DDR 0x27
|
||||
#define FC_WRITE_SDR 0x08
|
||||
#define FC_WRITE_DDR 0x28
|
||||
#define FC_READ_SDR 0x09
|
||||
#define FC_READ_DDR 0x29
|
||||
#define FC_LEARN_SDR 0x0A
|
||||
#define FC_LEARN_DDR 0x2A
|
||||
#define FC_DATSZ_SDR 0x0B
|
||||
#define FC_DATSZ_DDR 0x2B
|
||||
#define FC_DUMMY_SDR 0x0C
|
||||
#define FC_DUMMY_DDR 0x2C
|
||||
#define FC_DUMMY_RWDS_SDR 0x0D
|
||||
#define FC_DUMMY_RWDS_DDR 0x2D
|
||||
#define FC_JMP_ON_CS 0x1F
|
||||
#define FC_STOP_EXE 0
|
||||
|
||||
#define FC_FLEXSPI_1PAD 0
|
||||
#define FC_FLEXSPI_2PAD 1
|
||||
#define FC_FLEXSPI_4PAD 2
|
||||
#define FC_FLEXSPI_8PAD 3
|
||||
|
||||
#define FC_FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \
|
||||
(FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | \
|
||||
FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
|
||||
|
||||
/* !@brief Data pad used in Read command */
|
||||
enum
|
||||
{
|
||||
kSerialFlash_1Pads = 1,
|
||||
kSerialFlash_2Pads = 2,
|
||||
kSerialFlash_4Pads = 4,
|
||||
kSerialFlash_8Pads = 8,
|
||||
};
|
||||
|
||||
/* !@brief FLEXSPI clock configuration - In High speed boot mode mode */
|
||||
enum
|
||||
{
|
||||
kFlexSpiSerialClk_30MHz = 1,
|
||||
kFlexSpiSerialClk_50MHz = 2,
|
||||
kFlexSpiSerialClk_60MHz = 3,
|
||||
kFlexSpiSerialClk_80MHz = 4,
|
||||
kFlexSpiSerialClk_100MHz = 5,
|
||||
kFlexSpiSerialClk_120MHz = 6,
|
||||
kFlexSpiSerialClk_133MHz = 7,
|
||||
kFlexSpiSerialClk_166MHz = 8,
|
||||
kFlexSpiSerialClk_200MHz = 9,
|
||||
};
|
||||
|
||||
/* !@brief FLEXSPI clock configuration - In Normal boot SDR mode */
|
||||
enum
|
||||
{
|
||||
kFlexSpiSerialClk_SDR_24MHz = 1,
|
||||
kFlexSpiSerialClk_SDR_48MHz = 2,
|
||||
};
|
||||
|
||||
/* !@brief FLEXSPI clock configuration - In Normal boot DDR mode */
|
||||
enum
|
||||
{
|
||||
kFlexSpiSerialClk_DDR_48MHz = 1,
|
||||
};
|
||||
|
||||
/* !@brief Misc feature bit definitions */
|
||||
enum
|
||||
{
|
||||
kFlexSpiMiscOffset_DiffClkEnable = 0, /* !< Bit for Differential clock enable */
|
||||
kFlexSpiMiscOffset_WordAddressableEnable = 3, /* !< Bit for Word Addressable enable */
|
||||
kFlexSpiMiscOffset_SafeConfigFreqEnable = 4, /* !< Bit for Safe Configuration Frequency enable */
|
||||
kFlexSpiMiscOffset_DdrModeEnable = 6, /* !< Bit for DDR clock confiuration indication. */
|
||||
};
|
||||
|
||||
/* !@brief Flash Configuration Command Type */
|
||||
enum
|
||||
{
|
||||
kDeviceConfigCmdType_Generic, /* !< Generic command, for example: configure dummy cycles, drive strength, etc */
|
||||
kDeviceConfigCmdType_QuadEnable, /* !< Quad Enable command */
|
||||
kDeviceConfigCmdType_Spi2Xpi, /* !< Switch from SPI to DPI/QPI/OPI mode */
|
||||
kDeviceConfigCmdType_Xpi2Spi, /* !< Switch from DPI/QPI/OPI to SPI mode */
|
||||
kDeviceConfigCmdType_Spi2NoCmd, /* !< Switch to 0-4-4/0-8-8 mode */
|
||||
kDeviceConfigCmdType_Reset, /* !< Reset device command */
|
||||
};
|
||||
|
||||
typedef struct _fc_flexspi_dll_time
|
||||
{
|
||||
uint8_t time_100ps; /* !< Data valid time, in terms of 100ps */
|
||||
uint8_t delay_cells; /* !< Data valid time, in terms of delay cells */
|
||||
} fc_flexspi_dll_time_t;
|
||||
|
||||
/* !@brief FlexSPI LUT Sequence structure */
|
||||
typedef struct _fc_flexspi_lut_seq
|
||||
{
|
||||
uint8_t seqNum; /* !< Sequence Number, valid number: 1-16 */
|
||||
uint8_t seqId; /* !< Sequence Index, valid number: 0-15 */
|
||||
uint16_t reserved;
|
||||
} fc_flexspi_lut_seq_t;
|
||||
|
||||
/* !@brief FlexSPI Memory Configuration Block */
|
||||
typedef struct _fc_flexspi_mem_config
|
||||
{
|
||||
uint32_t tag; /* !< [0x000-0x003] Tag, fixed value 0x42464346UL */
|
||||
uint32_t version; /* !< [0x004-0x007] Version,[31:24] -'V', [23:16] - Major, [15:8] - Minor, [7:0] - bugfix */
|
||||
uint32_t reserved0; /* !< [0x008-0x00b] Reserved for future use */
|
||||
uint8_t readSampleClkSrc; /* !< [0x00c-0x00c] Read Sample Clock Source, valid value: 0/1/3 */
|
||||
uint8_t csHoldTime; /* !< [0x00d-0x00d] CS hold time, default value: 3 */
|
||||
uint8_t csSetupTime; /* !< [0x00e-0x00e] CS setup time, default value: 3 */
|
||||
uint8_t columnAddressWidth; /* !< [0x00f-0x00f] Column Address with, for HyperBus protocol, it is fixed to 3, For
|
||||
Serial NAND, need to refer to datasheet */
|
||||
uint8_t deviceModeCfgEnable; /* !< [0x010-0x010] Device Mode Configure enable flag, 1 - Enable, 0 - Disable */
|
||||
uint8_t deviceModeType; /* !< [0x011-0x011] Specify the configuration command type:Quad Enable, DPI/QPI/OPI switch,
|
||||
Generic configuration, etc. */
|
||||
uint16_t waitTimeCfgCommands; /* !< [0x012-0x013] Wait time for all configuration commands, unit: 100us, Used for
|
||||
DPI/QPI/OPI switch or reset command */
|
||||
fc_flexspi_lut_seq_t deviceModeSeq; /* !< [0x014-0x017] Device mode sequence info, [7:0] - LUT sequence id, [15:8] -
|
||||
LUt sequence number, [31:16] Reserved */
|
||||
uint32_t deviceModeArg; /* !< [0x018-0x01b] Argument/Parameter for device configuration */
|
||||
uint8_t configCmdEnable; /* !< [0x01c-0x01c] Configure command Enable Flag, 1 - Enable, 0 - Disable */
|
||||
uint8_t configModeType[3]; /* !< [0x01d-0x01f] Configure Mode Type, similar as deviceModeTpe */
|
||||
fc_flexspi_lut_seq_t configCmdSeqs[3]; /* !< [0x020-0x02b] Sequence info for Device Configuration command, similar
|
||||
as deviceModeSeq */
|
||||
uint32_t reserved1; /* !< [0x02c-0x02f] Reserved for future use */
|
||||
uint32_t configCmdArgs[3]; /* !< [0x030-0x03b] Arguments/Parameters for device Configuration commands */
|
||||
uint32_t reserved2; /* !< [0x03c-0x03f] Reserved for future use */
|
||||
uint32_t controllerMiscOption; /* !< [0x040-0x043] Controller Misc Options, see Misc feature bit definitions for
|
||||
more details */
|
||||
uint8_t deviceType; /* !< [0x044-0x044] Device Type: See Flash Type Definition for more details */
|
||||
uint8_t sflashPadType; /* !< [0x045-0x045] Serial Flash Pad Type: 1 - Single, 2 - Dual, 4 - Quad, 8 - Octal */
|
||||
uint8_t serialClkFreq; /* !< [0x046-0x046] Serial Flash Frequencey, device specific definitions, See System Boot
|
||||
Chapter for more details */
|
||||
uint8_t lutCustomSeqEnable; /* !< [0x047-0x047] LUT customization Enable, it is required if the program/erase cannot
|
||||
be done using 1 LUT sequence, currently, only applicable to HyperFLASH */
|
||||
uint32_t reserved3[2]; /* !< [0x048-0x04f] Reserved for future use */
|
||||
uint32_t sflashA1Size; /* !< [0x050-0x053] Size of Flash connected to A1 */
|
||||
uint32_t sflashA2Size; /* !< [0x054-0x057] Size of Flash connected to A2 */
|
||||
uint32_t sflashB1Size; /* !< [0x058-0x05b] Size of Flash connected to B1 */
|
||||
uint32_t sflashB2Size; /* !< [0x05c-0x05f] Size of Flash connected to B2 */
|
||||
uint32_t csPadSettingOverride; /* !< [0x060-0x063] CS pad setting override value */
|
||||
uint32_t sclkPadSettingOverride; /* !< [0x064-0x067] SCK pad setting override value */
|
||||
uint32_t dataPadSettingOverride; /* !< [0x068-0x06b] data pad setting override value */
|
||||
uint32_t dqsPadSettingOverride; /* !< [0x06c-0x06f] DQS pad setting override value */
|
||||
uint32_t timeoutInMs; /* !< [0x070-0x073] Timeout threshold for read status command */
|
||||
uint32_t commandInterval; /* !< [0x074-0x077] CS deselect interval between two commands */
|
||||
fc_flexspi_dll_time_t dataValidTime[2]; /* !< [0x078-0x07b] CLK edge to data valid time for PORT A and PORT B */
|
||||
uint16_t busyOffset; /* !< [0x07c-0x07d] Busy offset, valid value: 0-31 */
|
||||
uint16_t busyBitPolarity; /* !< [0x07e-0x07f] Busy flag polarity, 0 - busy flag is 1 when flash device is busy, 1 -
|
||||
busy flag is 0 when flash device is busy */
|
||||
uint32_t lookupTable[64]; /* !< [0x080-0x17f] Lookup table holds Flash command sequences */
|
||||
fc_flexspi_lut_seq_t lutCustomSeq[12]; /* !< [0x180-0x1af] Customizable LUT Sequences */
|
||||
uint32_t reserved4[4]; /* !< [0x1b0-0x1bf] Reserved for future use */
|
||||
} fc_flexspi_mem_config_t;
|
||||
/*
|
||||
* Serial NOR configuration block
|
||||
*/
|
||||
typedef struct _fc_flexspi_nor_config
|
||||
{
|
||||
#if defined(__ARMCC_VERSION) || defined(__ICCARM__)
|
||||
uint8_t padding[0x400]; /* !< Padding for MDK and IAR */
|
||||
#endif
|
||||
fc_flexspi_mem_config_t memConfig; /* !< Common memory configuration info via FlexSPI */
|
||||
uint32_t pageSize; /* !< Page size of Serial NOR */
|
||||
uint32_t sectorSize; /* !< Sector size of Serial NOR */
|
||||
uint8_t ipcmdSerialClkFreq; /* !< Clock frequency for IP command */
|
||||
uint8_t isUniformBlockSize; /* !< Sector/Block size is the same */
|
||||
uint8_t isDataOrderSwapped; /* !< Data order (D0, D1, D2, D3) is swapped (D1,D0, D3, D2) */
|
||||
uint8_t reserved0[1]; /* !< Reserved for future use */
|
||||
uint8_t serialNorType; /* !< Serial NOR Flash type: 0/1/2/3 */
|
||||
uint8_t needExitNoCmdMode; /* !< Need to exit NoCmd mode before other IP command */
|
||||
uint8_t halfClkForNonReadCmd; /* !< Half the Serial Clock for non-read command: true/false */
|
||||
uint8_t needRestoreNoCmdMode; /* !< Need to Restore NoCmd mode after IP commmand execution */
|
||||
uint32_t blockSize; /* !< Block size */
|
||||
uint32_t flashStateCtx; /* !< Flash State Context */
|
||||
uint32_t reserve2[10]; /* !< Reserved for future use */
|
||||
uint32_t fcb_fill[0x280]; /* !< Fill */
|
||||
} fc_flexspi_nor_config_t;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __FLASH_CONFIG__ */
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "RW612.h"
|
||||
#include "fsl_flexspi.h" // peripheral structures
|
||||
|
||||
__attribute__((section(".iram"))) static void deinit_flash(FLEXSPI_Type *base) {
|
||||
CLKCTL0->PSCCTL0_SET =
|
||||
CLKCTL0_PSCCTL0_SET_FLEXSPI0_MASK; // Enable FLEXSPI clock again
|
||||
base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; // Enable FLEXSPI module
|
||||
// Wait until FLEXSPI is not busy
|
||||
while (!((base->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) &&
|
||||
(base->STS0 & FLEXSPI_STS0_SEQIDLE_MASK)))
|
||||
(void)0;
|
||||
base->MCR0 |=
|
||||
FLEXSPI_MCR0_MDIS_MASK; // Disable module during the reset procedure
|
||||
}
|
||||
|
||||
__attribute__((section(".iram"))) static void init_flash(FLEXSPI_Type *base) {
|
||||
uint32_t status;
|
||||
uint32_t lastStatus;
|
||||
uint32_t retry;
|
||||
|
||||
// Loopback from DQS pad can maximize RD board flash speed.
|
||||
if ((base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) != FLEXSPI_MCR0_RXCLKSRC(1)) {
|
||||
base->MCR0 =
|
||||
(base->MCR0 & ~FLEXSPI_MCR0_RXCLKSRC_MASK) | FLEXSPI_MCR0_RXCLKSRC(1);
|
||||
}
|
||||
base->DLLCR[0] = 0x1U;
|
||||
base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; // Enable FLEXSPI module
|
||||
base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
|
||||
while (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK)
|
||||
(void)0;
|
||||
|
||||
// Need to wait DLL locked if DLL enabled
|
||||
if (0U != (base->DLLCR[0] & FLEXSPI_DLLCR_DLLEN_MASK)) {
|
||||
lastStatus = base->STS2;
|
||||
retry = 10;
|
||||
// Wait slave delay line locked and slave reference delay line locked.
|
||||
do {
|
||||
status = base->STS2;
|
||||
if ((status &
|
||||
(FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK)) ==
|
||||
(FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK)) {
|
||||
// Locked
|
||||
retry = 100;
|
||||
break;
|
||||
} else if (status == lastStatus) {
|
||||
retry--;
|
||||
} else {
|
||||
retry = 10;
|
||||
lastStatus = status;
|
||||
}
|
||||
} while (retry > 0);
|
||||
// According to ERR011377, need to delay at least 100 NOPs to ensure the DLL
|
||||
// is locked
|
||||
for (; retry > 0U; retry--)
|
||||
(void)0;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((section(".iram"))) void
|
||||
set_flexspi_clock(FLEXSPI_Type *base, uint32_t src, uint32_t divider) {
|
||||
if ((CLKCTL0->FLEXSPIFCLKSEL != CLKCTL0_FLEXSPIFCLKSEL_SEL(src)) ||
|
||||
((CLKCTL0->FLEXSPIFCLKDIV & CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK) !=
|
||||
(divider - 1))) {
|
||||
// Always deinit FLEXSPI and init FLEXSPI for the flash to make sure the
|
||||
// flash works correctly after the FLEXSPI root clock changed as the default
|
||||
// FLEXSPI configuration may does not work for the new root clock frequency.
|
||||
deinit_flash(base);
|
||||
|
||||
// Disable clock before changing clock source
|
||||
CLKCTL0->PSCCTL0_CLR = CLKCTL0_PSCCTL0_CLR_FLEXSPI0_MASK;
|
||||
// Update flexspi clock.
|
||||
CLKCTL0->FLEXSPIFCLKSEL = CLKCTL0_FLEXSPIFCLKSEL_SEL(src);
|
||||
CLKCTL0->FLEXSPIFCLKDIV |=
|
||||
CLKCTL0_FLEXSPIFCLKDIV_RESET_MASK; // Reset the divider counter
|
||||
CLKCTL0->FLEXSPIFCLKDIV = CLKCTL0_FLEXSPIFCLKDIV_DIV(divider - 1);
|
||||
while ((CLKCTL0->FLEXSPIFCLKDIV) & CLKCTL0_FLEXSPIFCLKDIV_REQFLAG_MASK)
|
||||
(void)0;
|
||||
// Enable FLEXSPI clock again
|
||||
CLKCTL0->PSCCTL0_SET = CLKCTL0_PSCCTL0_SET_FLEXSPI0_MASK;
|
||||
init_flash(base);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright (c) 2026 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
// Added to minimise the bin size: avoid pulling printf and friends
|
||||
void __assert_func(const char *s, int line, const char *fn, const char *expr) {
|
||||
(void) s, (void) line, (void) fn, (void) expr;
|
||||
for (;;) (void) 0; // or trigger the fault handler
|
||||
}
|
||||
|
||||
bool hal_timer_expired(volatile uint64_t *t, uint64_t period, uint64_t now) {
|
||||
uint64_t diff = now - *t; // Wrap-safe elapsed time since last expiry
|
||||
if (period == 0) return false; // Avoid division by zero
|
||||
if (diff < period) return false; // Period has not elapsed yet
|
||||
*t += (diff / period) * period; // Preserve cadence, skip missed periods
|
||||
return true;
|
||||
}
|
||||
|
||||
static volatile uint64_t s_ticks; // Milliseconds since boot
|
||||
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
|
||||
s_ticks++;
|
||||
}
|
||||
|
||||
uint64_t hal_get_tick(void) {
|
||||
return s_ticks;
|
||||
};
|
||||
|
||||
uint32_t SystemCoreClock = SYS_FREQUENCY;
|
||||
int hal_radio_err; // Result of hal_radio_init()
|
||||
void SystemInit(void) { // Called automatically by startup code
|
||||
hal_system_init(); // Enable FPU
|
||||
hal_radio_err = hal_radio_init(); // At the boot clock, see radio.c
|
||||
hal_clock_init();
|
||||
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
|
||||
}
|
||||
|
||||
void ExitRun0Mode(void) {
|
||||
}
|
||||
|
||||
struct stat;
|
||||
__attribute__((weak)) int _fstat(int fd, struct stat *st) {
|
||||
(void) fd, (void) st;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern unsigned char _end[]; // End of data section, start of heap. See link.ld
|
||||
static unsigned char *s_current_heap_end = _end;
|
||||
|
||||
size_t hal_ram_used(void) {
|
||||
return (size_t) (s_current_heap_end - _end);
|
||||
}
|
||||
|
||||
size_t hal_ram_free(void) {
|
||||
unsigned char endofstack;
|
||||
return (size_t) (&endofstack - s_current_heap_end);
|
||||
}
|
||||
|
||||
void *_sbrk(int incr) {
|
||||
unsigned char *prev_heap;
|
||||
unsigned char *heap_end = (unsigned char *) ((size_t) &heap_end - 256);
|
||||
prev_heap = s_current_heap_end;
|
||||
// Check how much space we got from the heap end to the stack end
|
||||
if (s_current_heap_end + incr > heap_end) return (void *) -1;
|
||||
s_current_heap_end += incr;
|
||||
return prev_heap;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _open(const char *path) {
|
||||
(void) path;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _close(int fd) {
|
||||
(void) fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _isatty(int fd) {
|
||||
(void) fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _lseek(int fd, int ptr, int dir) {
|
||||
(void) fd, (void) ptr, (void) dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _exit(int status) {
|
||||
(void) status;
|
||||
for (;;) asm volatile("BKPT #0");
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _kill(int pid, int sig) {
|
||||
(void) pid, (void) sig;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _getpid(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _read(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _link(const char *a, const char *b) {
|
||||
(void) a, (void) b;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _unlink(const char *a) {
|
||||
(void) a;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _stat(const char *path, struct stat *st) {
|
||||
(void) path, (void) st;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int mkdir(const char *path, int mode) {
|
||||
(void) path, (void) mode;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _init(void) {
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
// Copyright (c) 2023 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "RW612.h"
|
||||
#include "fsl_clock.h"
|
||||
#include "fsl_ocotp.h"
|
||||
#include "fsl_power.h"
|
||||
#include "fsl_io_mux.h"
|
||||
#include "fsl_reset.h"
|
||||
#include "fsl_trng.h"
|
||||
|
||||
int hal_radio_init(void); // Start the 802.15.4 radio firmware. 0: success
|
||||
extern int hal_radio_err; // hal_radio_init() result, called by SystemInit()
|
||||
|
||||
#define BIT(x) (1UL << (x))
|
||||
#define CLRSET(reg, clear, set) ((reg) = ((reg) & ~(clear)) | (set))
|
||||
#define PIN(bank, num) ((bank << 8) | (num))
|
||||
#define PINNO(pin) (pin & 255)
|
||||
#define PINBANK(pin) (pin >> 8)
|
||||
|
||||
void hal_init(void);
|
||||
size_t hal_ram_free(void);
|
||||
size_t hal_ram_used(void);
|
||||
bool hal_timer_expired(volatile uint64_t *t, uint64_t period, uint64_t now);
|
||||
uint64_t hal_get_tick(void);
|
||||
|
||||
static inline void spin(volatile uint32_t count) {
|
||||
while (count--)
|
||||
(void)0;
|
||||
}
|
||||
|
||||
#define SYS_FREQUENCY 260000000UL
|
||||
#define FRG_PLL_CLKDIV 13
|
||||
|
||||
enum { HAL_GPIO_MODE_INPUT, HAL_GPIO_MODE_OUTPUT };
|
||||
enum {
|
||||
HAL_GPIO_TYPE_NOPULL_WEAKEST = 0x0,
|
||||
HAL_GPIO_TYPE_NOPULL_WEAK = 0x4,
|
||||
HAL_GPIO_TYPE_NOPULL_STRONG = 0x8,
|
||||
HAL_GPIO_TYPE_NOPULL_STRONGEST = 0xC,
|
||||
HAL_GPIO_TYPE_PULLUP_WEAKEST = 0x1,
|
||||
HAL_GPIO_TYPE_PULLUP_WEAK = 0x5,
|
||||
HAL_GPIO_TYPE_PULLUP_STRONG = 0x9,
|
||||
HAL_GPIO_TYPE_PULLUP_STRONGEST = 0xD,
|
||||
HAL_GPIO_TYPE_PULLDOWN_WEAKEST = 0x2,
|
||||
HAL_GPIO_TYPE_PULLDOWN_WEAK = 0x6,
|
||||
HAL_GPIO_TYPE_PULLDOWN_STRONG = 0xA,
|
||||
HAL_GPIO_TYPE_PULLDOWN_STRONGEST = 0xE,
|
||||
HAL_GPIO_TYPE_NOPULL = HAL_GPIO_TYPE_NOPULL_STRONGEST,
|
||||
HAL_GPIO_TYPE_PULLUP = HAL_GPIO_TYPE_PULLUP_STRONGEST,
|
||||
HAL_GPIO_TYPE_PULLDOWN = HAL_GPIO_TYPE_PULLDOWN_STRONGEST,
|
||||
};
|
||||
|
||||
// Wrapper structure over the IO_MUX_* macros in fsl_io_mux.h
|
||||
// To use those macros with our gpio functions,
|
||||
// wrap them inside this structure as shown in the example from the
|
||||
// ethernet_init function.
|
||||
typedef struct
|
||||
{
|
||||
uint32_t pinLowMask, pinHighMask, gpioFcSetMask,
|
||||
gpioFcClrMask, fselSetMask, fselClrMask, ctimerSetMask,
|
||||
ctimerClrMask, sctimerSetMask, sctimerClrMask;
|
||||
} io_mux_config_t;
|
||||
|
||||
static inline void hal_gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
|
||||
io_mux_config_t *mux_config) {
|
||||
uint8_t bank = PINBANK(pin);
|
||||
uint8_t pin_no = PINNO(pin);
|
||||
if (mode == HAL_GPIO_MODE_INPUT) {
|
||||
GPIO->DIR[bank] &= ~(1 << pin_no);
|
||||
} else {
|
||||
GPIO->DIR[bank] |= (1 << pin_no);
|
||||
}
|
||||
|
||||
// configure pull
|
||||
pin_no += bank * 32;
|
||||
uint32_t shift = (pin_no % 16) * 2;
|
||||
uint32_t pull_val = (uint32_t)type & 3;
|
||||
uint32_t drive_val = ((uint32_t)type >> 2) & 3;
|
||||
volatile uint32_t *pull_reg, *drive_reg;
|
||||
if (pin_no < 22 || pin_no > 27) {
|
||||
pull_reg = &SOCCTRL->PAD_PU_PD_EN0 + pin_no / 16;
|
||||
drive_reg = &SOCCTRL->SR_CONFIG0 + pin_no / 16;
|
||||
} else {
|
||||
pull_reg = &AON_SOC_CIU->PAD_PU_PD_EN1;
|
||||
drive_reg = &AON_SOC_CIU->SR_CONFIG1;
|
||||
}
|
||||
*pull_reg = (*pull_reg & ~(3 << shift)) | (pull_val << shift);
|
||||
*drive_reg = (*drive_reg & ~(3 << shift)) | (drive_val << shift);
|
||||
|
||||
if (mux_config) {
|
||||
IO_MUX_SetPinMux(mux_config->pinLowMask, mux_config->pinHighMask,
|
||||
mux_config->gpioFcSetMask, mux_config->gpioFcClrMask,
|
||||
mux_config->fselSetMask, mux_config->fselClrMask,
|
||||
mux_config->ctimerSetMask, mux_config->ctimerClrMask,
|
||||
mux_config->sctimerSetMask, mux_config->sctimerClrMask
|
||||
);
|
||||
} else {
|
||||
// if no mux config is specified, assume default gpio settings and
|
||||
// no special function and just enable the IO
|
||||
IO_MUX_SetPinMux(bank ? 0 : BIT(PINNO(pin)), !bank ? 0 : BIT(PINNO(pin)),
|
||||
1 << 16, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hal_gpio_input(uint16_t pin) {
|
||||
hal_gpio_init(pin, HAL_GPIO_MODE_INPUT, HAL_GPIO_TYPE_PULLUP_STRONGEST, NULL);
|
||||
}
|
||||
static inline void hal_gpio_output(uint16_t pin) {
|
||||
hal_gpio_init(pin, HAL_GPIO_MODE_OUTPUT, HAL_GPIO_TYPE_NOPULL_STRONGEST, NULL);
|
||||
}
|
||||
|
||||
static inline bool hal_gpio_read(uint16_t pin) {
|
||||
return GPIO->PIN[PINBANK(pin)] & (1 << PINNO(pin));
|
||||
}
|
||||
|
||||
static inline void hal_gpio_write(uint16_t pin, bool value) {
|
||||
if (value) {
|
||||
GPIO->SET[PINBANK(pin)] |= (1 << PINNO(pin));
|
||||
} else {
|
||||
GPIO->CLR[PINBANK(pin)] |= (1 << PINNO(pin));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hal_gpio_toggle(uint16_t pin) {
|
||||
hal_gpio_read(pin) ? hal_gpio_write(pin, false) : hal_gpio_write(pin, true);
|
||||
}
|
||||
|
||||
#if defined(__ZEPHYR__)
|
||||
#undef MG_HAL_DISABLE_SYSTEM_INIT
|
||||
#define MG_HAL_DISABLE_SYSTEM_INIT 1
|
||||
#undef MG_HAL_DISABLE_NEWLIB
|
||||
#define MG_HAL_DISABLE_NEWLIB 1
|
||||
#undef MG_HAL_DISABLE_CLOCK
|
||||
#define MG_HAL_DISABLE_CLOCK 1
|
||||
#undef MG_HAL_DISABLE_RANDOM
|
||||
#define MG_HAL_DISABLE_RANDOM 1
|
||||
#undef MG_HAL_DISABLE_MILLIS
|
||||
#define MG_HAL_DISABLE_MILLIS 1
|
||||
#undef MG_HAL_DISABLE_UART
|
||||
#define MG_HAL_DISABLE_UART 1
|
||||
#undef MG_HAL_DISABLE_ETHERNET
|
||||
#define MG_HAL_DISABLE_ETHERNET 1
|
||||
#undef MG_HAL_SYSTICK
|
||||
#define MG_HAL_SYSTICK MG_HAL_SYSTICK_NONE
|
||||
#endif
|
||||
|
||||
static inline void hal_uart_init(USART_Type *uart, unsigned long baud) {
|
||||
if (uart == USART0) {
|
||||
IO_MUX_SetPinMux(IO_MUX_FC0_USART_DATA);
|
||||
} else if (uart == USART1) {
|
||||
IO_MUX_SetPinMux(IO_MUX_FC1_USART_DATA);
|
||||
} else if (uart == USART2) {
|
||||
IO_MUX_SetPinMux(IO_MUX_FC2_USART_DATA);
|
||||
} else if (uart == USART3) {
|
||||
IO_MUX_SetPinMux(IO_MUX_FC3_USART_DATA);
|
||||
} else if (uart == USART14) {
|
||||
IO_MUX_SetPinMux(IO_MUX_FC14_USART_DATA);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t uart_index = ((uint32_t)uart - USART0_BASE) / 0x1000;
|
||||
|
||||
// set FRG clk
|
||||
CLKCTL1->FLEXCOMM[uart_index].FRGCLKSEL = kCLOCK_FrgPllDiv;
|
||||
CLKCTL1->FLEXCOMM[uart_index].FRGCTL =
|
||||
(CLKCTL1_FRGCTL_MULT(0) | CLKCTL1_FRGCTL_DIV(255));
|
||||
CLOCK_AttachClk(CLKCTL1_TUPLE_MUXA(0x508 + uart_index * 0x20, 4));
|
||||
|
||||
// set FLEXCOMM to USART mode
|
||||
CLOCK_EnableClock(CLK_GATE_DEFINE(CLK_CTL1_PSCCTL0, uart_index + 8));
|
||||
uint32_t mask = BIT(uart_index + 8);
|
||||
RSTCTL1->PRSTCTL0_SET = mask;
|
||||
while ((RSTCTL1->PRSTCTL0 & mask) == 0)
|
||||
spin(1);
|
||||
RSTCTL1->PRSTCTL0_CLR = mask;
|
||||
while ((RSTCTL1->PRSTCTL0 & mask) == mask)
|
||||
spin(1);
|
||||
((FLEXCOMM_Type *)uart)->PSELID = 1;
|
||||
|
||||
uart->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK |
|
||||
USART_FIFOCFG_ENABLETX_MASK; // empty and enable txFIFO
|
||||
uart->CFG = BIT(2) | BIT(0); // 8 bit data length and enable
|
||||
|
||||
// compute baud
|
||||
uint32_t uart_freq = SYS_FREQUENCY / FRG_PLL_CLKDIV;
|
||||
uint32_t best_diff = (uint32_t)-1, best_osr = 0xF, best_brg = (uint32_t)-1;
|
||||
uint32_t osr, brg, diff, current_baud;
|
||||
for (osr = 15; osr >= 4; osr--) {
|
||||
brg = (((uart_freq * 10) / ((osr + 1) * baud)) - 5) / 10;
|
||||
if (brg > 0xFFFF)
|
||||
continue;
|
||||
current_baud = uart_freq / ((osr + 1) * (brg + 1));
|
||||
diff =
|
||||
(baud < current_baud) ? (current_baud - baud) : (baud - current_baud);
|
||||
if (diff < best_diff) {
|
||||
best_diff = diff;
|
||||
best_osr = osr;
|
||||
best_brg = brg;
|
||||
}
|
||||
}
|
||||
uart->OSR = best_osr;
|
||||
uart->BRG = best_brg;
|
||||
}
|
||||
|
||||
static inline void hal_uart_write_byte(USART_Type *uart, uint8_t byte) {
|
||||
while ((uart->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) == 0)
|
||||
spin(1);
|
||||
uart->FIFOWR = byte;
|
||||
}
|
||||
static inline void hal_uart_write_buf(USART_Type *uart, char *buf, size_t len) {
|
||||
while (len-- > 0)
|
||||
hal_uart_write_byte(uart, *(uint8_t *)buf++);
|
||||
}
|
||||
|
||||
static inline void hal_rng_init(void) {
|
||||
trng_config_t config;
|
||||
TRNG_GetDefaultConfig(&config);
|
||||
TRNG_Init(TRNG, &config);
|
||||
}
|
||||
|
||||
static inline uint32_t hal_rng_read(void) {
|
||||
uint32_t value;
|
||||
TRNG_GetRandomData(TRNG, &value, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void hal_ethernet_init(void) {
|
||||
CLOCK_EnableClock(kCLOCK_TddrMciEnetClk);
|
||||
hal_gpio_init(PIN(0, 25), HAL_GPIO_MODE_OUTPUT, IO_MUX_PinConfigPullUpDriveWeak,
|
||||
&(io_mux_config_t){ IO_MUX_ENET_CLK }); // ENET_CLK on GPIO_25
|
||||
IO_MUX_SetPinMux(
|
||||
IO_MUX_ENET_RX); // ENET_RX on pin GPIO_62, GPIO_63, GPIO_22, GPIO_23
|
||||
IO_MUX_SetPinMux(IO_MUX_ENET_TX); // ENET_TX on pin GPIO_58, GPIO_59, GPIO_60
|
||||
IO_MUX_SetPinMux(IO_MUX_ENET_MDIO); // ENET_MDIO on pin GPIO_56, GPIO_57
|
||||
|
||||
// reset ENET peripheral
|
||||
RSTCTL0->PRSTCTL1_SET = BIT(25);
|
||||
while ((RSTCTL0->PRSTCTL1 & BIT(25)) == 0)
|
||||
spin(1);
|
||||
RSTCTL0->PRSTCTL1_CLR = BIT(25);
|
||||
while ((RSTCTL0->PRSTCTL1 & BIT(25)) == BIT(25))
|
||||
spin(1);
|
||||
RSTCTL0->PRSTCTL1_SET = BIT(26);
|
||||
while ((RSTCTL0->PRSTCTL1 & BIT(26)) == 0)
|
||||
spin(1);
|
||||
RSTCTL0->PRSTCTL1_CLR = BIT(26);
|
||||
while ((RSTCTL0->PRSTCTL1 & BIT(26)) == BIT(26))
|
||||
spin(1);
|
||||
|
||||
// Enable clocks
|
||||
CLOCK_EnableClock(kCLOCK_EnetIpg);
|
||||
CLOCK_EnableClock(kCLOCK_EnetIpgS);
|
||||
|
||||
NVIC_EnableIRQ(ENET_IRQn);
|
||||
}
|
||||
extern void set_flexspi_clock(FLEXSPI_Type *base, uint32_t src,
|
||||
uint32_t divider);
|
||||
static inline void hal_clock_init(void) {
|
||||
const clock_avpll_config_t avpllConfig_BOARD_BootClockRUN = {
|
||||
.ch1Freq =
|
||||
kCLOCK_AvPllChFreq12p288m, // AVPLL channel frequency 12.288 MHz
|
||||
.ch2Freq = kCLOCK_AvPllChFreq64m, // AVPLL channel frequency 64 MHz
|
||||
.enableCali = true, // AVPLL calibration is enabled
|
||||
};
|
||||
// As NXP BOARD_BootClockRUN(): the ROM leaves the ELS glitch detector and
|
||||
// voltage sensors armed, trimmed for the boot clock. Disable them before
|
||||
// changing the clock, or the ROM resets the chip when it next uses ELS
|
||||
POWER_DisableGDetVSensors();
|
||||
if ((PMU->CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0) {
|
||||
CLOCK_EnableClock(
|
||||
kCLOCK_RefClkCauSlp); // Enable the CAU sleep clock for PMU
|
||||
}
|
||||
if ((SYSCTL2->SOURCE_CLK_GATE & SYSCTL2_SOURCE_CLK_GATE_REFCLK_SYS_CG_MASK) !=
|
||||
0) {
|
||||
CLOCK_EnableClock(kCLOCK_RefClkSys); // Enable the REFCLK_SYS clock
|
||||
}
|
||||
CLOCK_InitT3RefClk(kCLOCK_T3MciIrc48m); // Initialize T3 PLL and enable
|
||||
// outputs that are not clock gated
|
||||
CLOCK_EnableClock(
|
||||
kCLOCK_T3PllMciIrcClk); // Enable FFRO - T3 PLL 48/60 MHz IRC clock output
|
||||
CLOCK_EnableClock(
|
||||
kCLOCK_T3PllMci256mClk); // Enable T3 PLL 256 MHz clock output
|
||||
|
||||
// Move FLEXSPI clock source to T3 256M / 4 to avoid instruction/data fetch
|
||||
// issue in XIP when updating PLL and main clock.
|
||||
set_flexspi_clock(FLEXSPI, 6, 4);
|
||||
CLOCK_AttachClk(kSYSOSC_to_MAIN_CLK); // Set core clock to safe system
|
||||
// oscillator for initialization
|
||||
CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk,
|
||||
1); // Set system CPU AHB clock divider to 1
|
||||
CLOCK_InitTcpuRefClk(
|
||||
3120000000UL,
|
||||
kCLOCK_TcpuFlexspiDiv10); // Initialize TCPU PLL and enable outputs
|
||||
CLOCK_EnableClock(kCLOCK_TcpuMciClk); // Enable TCPU PLL MCI clock output
|
||||
CLOCK_InitTddrRefClk(
|
||||
kCLOCK_TddrFlexspiDiv10); // Initialize TDDR PLL and enable outputs
|
||||
CLOCK_EnableClock(
|
||||
kCLOCK_TddrMciFlexspiClk); // Enable TDDR PLL FlexSPI clock output
|
||||
CLOCK_InitAvPll(&avpllConfig_BOARD_BootClockRUN); // Initialize AVPLL and
|
||||
// enable both channels
|
||||
CLOCK_AttachClk(kRC32K_to_CLK32K); // Switch CLK32K to RC32K
|
||||
CLOCK_AttachClk(
|
||||
kSYSTICK_DIV_to_SYSTICK_CLK); // Switch SYSTICK_CLK to SYSTICK_DIV
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 1U); // Set AUDIOPLLCLKDIV divider to 1
|
||||
CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk,
|
||||
FRG_PLL_CLKDIV); // Set FRGPLLCLKDIV divider
|
||||
CLOCK_SetClkDiv(kCLOCK_DivMainPllClk, 1U); // Set MAINPLLCLKDIV divider to 1
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAux0PllClk, 1U); // Set AUX0PLLCLKDIV divider to 1
|
||||
CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U); // Set SYSTICKFCLKDIV divider to 1
|
||||
CLOCK_SetClkDiv(kCLOCK_DivPmuFclk, 5U); // Set PMUFCLKDIV divider to 5
|
||||
CLOCK_AttachClk(
|
||||
kMAIN_PLL_to_MAIN_CLK); // Select the main clock source for system clock
|
||||
set_flexspi_clock(FLEXSPI, 2U, 2U); // set_flexspi_clock
|
||||
|
||||
CLOCK_EnableClock(kCLOCK_HsGpio0);
|
||||
RSTCTL1->PRSTCTL1_SET = BIT(0); // Reset GPIO_0
|
||||
while ((RSTCTL1->PRSTCTL1 & BIT(0)) == 0)
|
||||
spin(1);
|
||||
RSTCTL1->PRSTCTL1_CLR = BIT(0);
|
||||
while ((RSTCTL1->PRSTCTL1 & BIT(0)) == BIT(0))
|
||||
spin(1);
|
||||
|
||||
CLOCK_EnableClock(kCLOCK_HsGpio1);
|
||||
RSTCTL1->PRSTCTL1_SET = BIT(1); // Reset GPIO_1
|
||||
while ((RSTCTL1->PRSTCTL1 & BIT(1)) == 0)
|
||||
spin(1);
|
||||
RSTCTL1->PRSTCTL1_CLR = BIT(1);
|
||||
while ((RSTCTL1->PRSTCTL1 & BIT(1)) == BIT(1))
|
||||
spin(1);
|
||||
}
|
||||
|
||||
#if defined(__MCUXPRESSO)
|
||||
#undef MG_HAL_DISABLE_SYSTEM_INIT
|
||||
#define MG_HAL_DISABLE_SYSTEM_INIT 1
|
||||
#undef MG_HAL_SBRK_NONE
|
||||
#define MG_HAL_SBRK_NONE 1
|
||||
#endif
|
||||
|
||||
static inline void hal_system_init(void) {
|
||||
SCB->CPACR |=
|
||||
(3UL << 0 * 2) | (3UL << 1 * 2) | // Enable PowerQuad (CPO/CP1)
|
||||
(3UL << 10 * 2) | (3UL << 11 * 2); // Enable FPU
|
||||
SCB->NSACR |= ((3UL << 0) | (3UL << 10));
|
||||
CACHE64_CTRL0->CCR = CACHE64_CTRL_CCR_INVW1_MASK | CACHE64_CTRL_CCR_INVW0_MASK;
|
||||
CACHE64_CTRL0->CCR |= CACHE64_CTRL_CCR_GO_MASK;
|
||||
while ((CACHE64_CTRL0->CCR & CACHE64_CTRL_CCR_GO_MASK) != 0) spin(1);
|
||||
// Enable cache, enable write buffer
|
||||
CACHE64_CTRL0->CCR = (CACHE64_CTRL_CCR_ENWRBUF_MASK | CACHE64_CTRL_CCR_ENCACHE_MASK);
|
||||
|
||||
// Set whole FlexSPI0 space to write through
|
||||
CACHE64_POLSEL0->REG0_TOP = 0x07FFFC00U;
|
||||
CACHE64_POLSEL0->REG1_TOP = 0x0U;
|
||||
CACHE64_POLSEL0->POLSEL = 0x1U;
|
||||
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
ENTRY(Reset_Handler);
|
||||
MEMORY {
|
||||
flash(rx) : ORIGIN = 0x08000000, LENGTH = 0x4000000
|
||||
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 0x123000 /* Top is reserved, as in NXP wireless linker scripts */
|
||||
}
|
||||
__StackTop = ORIGIN(sram) + LENGTH(sram);
|
||||
|
||||
SECTIONS {
|
||||
.boot_hdr : ALIGN(4) { FILL(0xFF); . = 0x400; __FLASH_BASE = .; KEEP(*(.flash_conf)) . = 0x1000; } > flash
|
||||
.vectors : { FILL(256) KEEP(*(.isr_vector)) } > flash
|
||||
.text : { *(.text.* *.text.*) } > flash
|
||||
.rodata : { *(.rodata*) } > flash
|
||||
|
||||
.iram : {
|
||||
_siram = .;
|
||||
*(.iram)
|
||||
*(CodeQuickAccess) /* NXP SDK drivers, e.g. fsl_power.c */
|
||||
*(DataQuickAccess)
|
||||
_eiram = .;
|
||||
} > sram AT > flash
|
||||
_siiram = LOADADDR(.iram);
|
||||
|
||||
.data : {
|
||||
_sdata = .;
|
||||
*(.first_data)
|
||||
*(.data SORT(.data.*))
|
||||
_edata = .;
|
||||
} > sram AT > flash
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
.bss : { _sbss = .; *(.bss SORT(.bss.*) COMMON) _ebss = .; } > sram
|
||||
. = ALIGN(8);
|
||||
_end = .;
|
||||
|
||||
_image_start = LOADADDR(.text);
|
||||
_image_end = LOADADDR(.data) + SIZEOF(.data);
|
||||
_image_size = _image_end - _image_start;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2026 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// Ethernet <-> IEEE 802.15.4 radio bridge. Radio frames carry Ethernet frames
|
||||
// split into pieces, see mg_l2_802154_tx(). Radio nodes, e.g. the
|
||||
// FRDM-MCXW71 minimal tutorial, are on the Ethernet LAN: they get IPv4
|
||||
// addresses from its DHCP server. The bridge itself has no IP address.
|
||||
// Everything from the radio goes to Ethernet. From Ethernet, only broadcasts
|
||||
// and frames to radio nodes go to the radio, it is much slower
|
||||
|
||||
#include "hal.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
#define UART_DEBUG USART3
|
||||
|
||||
static void log_fn(char ch, void *param) {
|
||||
hal_uart_write_buf(param, &ch, 1);
|
||||
}
|
||||
|
||||
uint64_t mg_millis(void) {
|
||||
return hal_get_tick();
|
||||
}
|
||||
|
||||
// MAC addresses of radio nodes, learned from frames they send
|
||||
static uint8_t s_nodes[8][6];
|
||||
static size_t s_next;
|
||||
|
||||
// Remember a radio node's MAC address, if new
|
||||
static void learn(const uint8_t *mac) {
|
||||
size_t i, n = sizeof(s_nodes) / sizeof(s_nodes[0]);
|
||||
for (i = 0; i < n && memcmp(s_nodes[i], mac, 6) != 0; i++) (void) 0;
|
||||
if (i < n) return;
|
||||
memcpy(s_nodes[s_next], mac, 6);
|
||||
s_next = (s_next + 1) % n;
|
||||
MG_INFO(("Radio node %M", mg_print_mac, mac));
|
||||
}
|
||||
|
||||
// Is an Ethernet frame for the radio: broadcast, or to a radio node
|
||||
static bool for_radio(const uint8_t *dst) {
|
||||
size_t i, n = sizeof(s_nodes) / sizeof(s_nodes[0]);
|
||||
if (memcmp(dst, "\xff\xff\xff\xff\xff\xff", 6) == 0) return true;
|
||||
for (i = 0; i < n && memcmp(s_nodes[i], dst, 6) != 0; i++) (void) 0;
|
||||
return i < n;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
static struct mg_tcpip_driver_rw612_data eth_data = {
|
||||
.mdc_cr = MG_DRIVER_MDC_CR, .phy_addr = MG_TCPIP_PHY_ADDR};
|
||||
static struct mg_l2_802154_data radio_data = {
|
||||
.channel = MG_L2_802154_CHANNEL, .pan_id = MG_L2_802154_PAN_ID};
|
||||
static struct mg_tcpip_if eth = {.driver = &mg_tcpip_driver_rw612,
|
||||
.driver_data = ð_data};
|
||||
static struct mg_tcpip_if radio = {.driver = &mg_tcpip_driver_rw612_154,
|
||||
.driver_data = &radio_data};
|
||||
static char eth_queue[8192]; // Filled by the Ethernet IRQ handler
|
||||
static uint8_t frame[1540];
|
||||
uint8_t uid[FSL_OCOTP_UID_LENGTH], digest[32];
|
||||
uint32_t uid_len = sizeof(uid);
|
||||
uint64_t timer = 0;
|
||||
char *p;
|
||||
size_t n;
|
||||
|
||||
hal_clock_init();
|
||||
hal_uart_init(UART_DEBUG, 115200);
|
||||
mg_log_set_fn(log_fn, UART_DEBUG);
|
||||
if (hal_radio_err) {
|
||||
MG_ERROR(("Radio firmware failed to start, step %d", hal_radio_err));
|
||||
}
|
||||
|
||||
// MAC addresses made from the chip unique ID
|
||||
memset(uid, 0, sizeof(uid));
|
||||
OCOTP_ReadUniqueID(uid, &uid_len);
|
||||
mg_sha256(digest, uid, sizeof(uid));
|
||||
memcpy(eth.mac, digest, 6);
|
||||
memcpy(radio.mac, digest + 6, 6);
|
||||
eth.mac[0] = radio.mac[0] = 0x02; // Locally administered, unicast
|
||||
|
||||
hal_ethernet_init();
|
||||
mg_queue_init(ð.recv_queue, eth_queue, sizeof(eth_queue));
|
||||
if (!eth.driver->init(ð)) MG_ERROR(("Ethernet init failed"));
|
||||
if (!radio.driver->init(&radio)) MG_ERROR(("Radio init failed"));
|
||||
ENET->RCR |= ENET_RCR_PROM_MASK; // Receive frames for radio nodes, too
|
||||
MG_INFO(("Bridge started, radio channel %d", radio_data.channel));
|
||||
|
||||
for (;;) {
|
||||
if ((n = mg_queue_next(ð.recv_queue, &p)) > 0) { // Ethernet -> radio
|
||||
if (n >= 14 && for_radio((uint8_t *) p)) radio.driver->tx(p, n, &radio);
|
||||
mg_queue_del(ð.recv_queue, n);
|
||||
}
|
||||
if ((n = radio.driver->rx(frame, sizeof(frame), &radio)) >= 14) {
|
||||
learn(frame + 6); // Radio -> Ethernet
|
||||
eth.driver->tx(frame, n, ð);
|
||||
}
|
||||
if (mg_timer_expired(&timer, 1000, mg_millis())) { // Ethernet link
|
||||
bool up = eth.driver->poll(ð, true);
|
||||
eth.state = up ? MG_TCPIP_STATE_UP : MG_TCPIP_STATE_DOWN;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
// See https://mongoose.ws/docs/getting-started/build-environment/
|
||||
#define MG_ARCH MG_ARCH_ARMGCC
|
||||
|
||||
#define MG_ENABLE_TCPIP 1
|
||||
#define MG_ENABLE_DRIVER_RW612 1 // Ethernet
|
||||
#define MG_ENABLE_DRIVER_RW612_154 1 // 802.15.4 radio
|
||||
#define MG_ENABLE_TCPIP_DRIVER_INIT 0 // main.c drives both, no TCP/IP stack
|
||||
#define MG_ENABLE_CUSTOM_MILLIS 1
|
||||
@@ -0,0 +1,236 @@
|
||||
// Load NXP BLE/802.15.4 combo firmware to CPU2 and start it.
|
||||
// Port of NXP mcux-component conn_fwloader: fsl_loader_utils.c (SB3 loader,
|
||||
// load_service_monolithic) and nboot_hal.c (manifest parameters).
|
||||
// Copyright 2024 NXP
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "hal.h"
|
||||
#include "fsl_ocotp.h"
|
||||
#include "fsl_power.h"
|
||||
#include "fsl_romapi_nboot.h"
|
||||
#include "fsl_romapi_otp.h"
|
||||
#include "fsl_kb_api.h"
|
||||
#include "fsl_sbloader_v3.h"
|
||||
|
||||
// The firmware image, linked into our flash. Signed SB3 container, see
|
||||
// https://github.com/NXP/wifi_nb_fw, rw61x/rw61x_sb_ble_15d4_combo_a2.bin
|
||||
__asm__(
|
||||
".section .rodata.radio_fw,\"a\"\n"
|
||||
".balign 16\n"
|
||||
"radio_fw:\n"
|
||||
".incbin \"" RADIO_FW "\"\n"
|
||||
".balign 4\n"
|
||||
"radio_fw_end:\n"
|
||||
".previous\n");
|
||||
extern const uint8_t radio_fw[], radio_fw_end[];
|
||||
|
||||
#define CIU2_RST_SW3 (*(volatile uint32_t *) 0x4424011cU)
|
||||
#define CIU2_RST_SW3_CPU2_RST BIT(4)
|
||||
#define CPU2_MAGIC (*(volatile uint32_t *) 0x443c0000U) // Set by firmware
|
||||
#define CPU2_MAGIC_VALUE 0xabcdef89U
|
||||
#define OTP_LCS_FUSE_IDX 45U // Life cycle state, and its redundant copy
|
||||
#define OTP_PCK_BLOB_FUSE_IDX 116U // Part common key blob, 48 bytes
|
||||
|
||||
// SB3 loader state. See fsl_ldr_Context_v3_t
|
||||
struct sb3 {
|
||||
nboot_context_t nboot; // ROM nboot context
|
||||
uint8_t buf[MAX(NBOOT_SB3_MANIFEST_MAX_SIZE_IN_BYTES,
|
||||
NBOOT_SB3_BLOCK_MAX_SIZE_IN_BYTES)]; // Block being read
|
||||
uint32_t buf_size; // Bytes needed for the current block
|
||||
uint32_t buf_pos; // Bytes in buf so far
|
||||
bool header_done; // Manifest (block 0) processed
|
||||
uint32_t data_offset; // Data offset within a block
|
||||
uint32_t blocks; // Data blocks processed
|
||||
uint8_t *data; // Data of the current block
|
||||
uint32_t pos; // Position in data
|
||||
bool in_section; // Inside a data section
|
||||
uint32_t section_done; // Bytes of the section handled
|
||||
sb3_section_header_t section;
|
||||
bool in_range; // Inside a data range
|
||||
uint32_t range_gap; // Padding after the range, 16 byte alignment
|
||||
sb3_data_range_header_t range;
|
||||
bool has_expansion; // Range expansion read
|
||||
bool executed; // Execute command seen: firmware loaded
|
||||
};
|
||||
static struct sb3 s_sb3;
|
||||
|
||||
static uint32_t antipole(uint32_t v) {
|
||||
return (v & 0xffffU) | (~(v & 0xffffU) << 16);
|
||||
}
|
||||
|
||||
// Manifest parameters: root of trust for NXP signed images, rev A2 chips.
|
||||
// See nboot_hal_get_sb3_manifest_params(), nboot_hal.c
|
||||
static bool manifest_params(nboot_sb3_load_manifest_parms_t *p) {
|
||||
static const uint32_t rkh_a2[8] = {0xE7C7E9BB, 0x12C8C535, 0x37E61148,
|
||||
0x2BE7F18C, 0x8F0E3094, 0xB2BA7F32,
|
||||
0xEC9B4ECB, 0xAD9FC941};
|
||||
uint32_t i, lcs = OCOTP->OTP_SHADOW[OTP_LCS_FUSE_IDX];
|
||||
memset(p, 0, sizeof(*p));
|
||||
if ((lcs & 0xff) != ((lcs >> 8) & 0xff)) return false; // Corrupt LCS
|
||||
for (i = 0; i < NBOOT_ROOT_CERT_COUNT; i++) {
|
||||
p->soc_RoTNVM.soc_rootKeyRevocation[i] = kNBOOT_RootKey_Enabled;
|
||||
}
|
||||
memcpy(p->soc_RoTNVM.soc_rkh, rkh_a2, sizeof(rkh_a2));
|
||||
p->soc_RoTNVM.soc_numberOfRootKeys = 1;
|
||||
for (i = 1; i < NBOOT_ROOT_CERT_COUNT; i++) {
|
||||
p->soc_RoTNVM.soc_rootKeyUsage[i] = kNBOOT_RootKeyUsage_Unused;
|
||||
}
|
||||
p->soc_RoTNVM.soc_rootKeyTypeAndLength = kNBOOT_RootKey_Ecdsa_P256;
|
||||
p->soc_RoTNVM.soc_lifecycle = (nboot_soc_lifecycle_t) antipole(lcs & 0xff);
|
||||
for (i = 0; i < sizeof(p->pckBlob) / 4; i++) {
|
||||
if (OCOTP_OtpFuseRead(OTP_PCK_BLOB_FUSE_IDX + i,
|
||||
(uint32_t *) &p->pckBlob[4 * i]) != kStatus_Success) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Manifest (block 0): verify, learn the block layout. See ldr_DoHeader_v3()
|
||||
static bool sb3_header(struct sb3 *s) {
|
||||
nboot_sb3_header_t *h = (nboot_sb3_header_t *) s->buf;
|
||||
nboot_sb3_load_manifest_parms_t parms;
|
||||
if (s->buf_size == sizeof(nboot_sb3_header_t)) { // Header only so far
|
||||
s->buf_size = h->imageTotalLength;
|
||||
s->buf_pos = sizeof(nboot_sb3_header_t);
|
||||
return s->buf_size <= sizeof(s->buf);
|
||||
}
|
||||
if (!manifest_params(&parms)) return false;
|
||||
// Protected status: the status code is in the low 32 bits
|
||||
if ((nboot_status_t) nboot_sb3_load_manifest(&s->nboot, (uint32_t *) h,
|
||||
&parms) != kStatus_NBOOT_Success) {
|
||||
return false;
|
||||
}
|
||||
s->data_offset = 4 + h->certificateBlockOffset - sizeof(nboot_sb3_header_t);
|
||||
s->buf_size = s->data_offset + NBOOT_SB3_CHUNK_SIZE_IN_BYTES;
|
||||
s->header_done = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copy (part of) the current load range to its destination
|
||||
static void sb3_load(struct sb3 *s) {
|
||||
uint32_t avail = NBOOT_SB3_CHUNK_SIZE_IN_BYTES - s->pos;
|
||||
uint32_t n = s->range.length < avail ? s->range.length : avail;
|
||||
memcpy((void *) s->range.startAddress, &s->data[s->pos], n);
|
||||
s->pos += n, s->section_done += n;
|
||||
s->range.startAddress += n, s->range.length -= n;
|
||||
if (s->range.length == 0) { // Range done, skip alignment padding
|
||||
s->in_range = false;
|
||||
s->pos += s->range_gap, s->section_done += s->range_gap;
|
||||
}
|
||||
}
|
||||
|
||||
// Process one decrypted data block. See ldr_DoBlock()
|
||||
static bool sb3_block(struct sb3 *s) {
|
||||
while (s->pos < NBOOT_SB3_CHUNK_SIZE_IN_BYTES) {
|
||||
if (!s->in_section) { // New section
|
||||
memcpy(&s->section, &s->data[s->pos], sizeof(s->section));
|
||||
if (s->section.sectionType == kSectionNone) break; // Rest is unused
|
||||
if (s->section.sectionType != kSectionDataRange) return false;
|
||||
s->in_section = true, s->section_done = 0, s->in_range = false;
|
||||
s->pos += sizeof(sb3_section_header_t);
|
||||
}
|
||||
if (!s->in_range) { // New range
|
||||
memcpy(&s->range, &s->data[s->pos], sizeof(s->range));
|
||||
if (s->range.tag != SB3_DATA_RANGE_HEADER_TAG) return false;
|
||||
s->in_range = true, s->has_expansion = false, s->range_gap = 0;
|
||||
s->pos += sizeof(sb3_data_range_header_t);
|
||||
s->section_done += sizeof(sb3_data_range_header_t);
|
||||
if (s->range.cmd == kSB3_CmdLoad) {
|
||||
s->range_gap = (SB3_DATA_ALIGNMENT_SIZE_IN_BYTE -
|
||||
(s->range.length & 15U)) & 15U;
|
||||
}
|
||||
}
|
||||
if (s->range.cmd == kSB3_CmdLoad) {
|
||||
if (!s->has_expansion) {
|
||||
if (s->pos == NBOOT_SB3_CHUNK_SIZE_IN_BYTES) break; // Next block
|
||||
s->has_expansion = true;
|
||||
s->pos += sizeof(sb3_data_range_expansion_t);
|
||||
s->section_done += sizeof(sb3_data_range_expansion_t);
|
||||
}
|
||||
if (s->pos < NBOOT_SB3_CHUNK_SIZE_IN_BYTES) sb3_load(s);
|
||||
} else if (s->range.cmd == kSB3_CmdExecute) {
|
||||
s->executed = true;
|
||||
return true;
|
||||
} else {
|
||||
s->in_range = false; // Other commands: nothing to do
|
||||
}
|
||||
if (s->section_done == s->section.length) s->in_section = false;
|
||||
if (s->section_done > s->section.length) return false;
|
||||
}
|
||||
s->pos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Feed image bytes, process complete blocks. See fsl_sbloader_pump()
|
||||
static bool sb3_pump(struct sb3 *s, const uint8_t *p, uint32_t len) {
|
||||
while (len > 0 && !s->executed) {
|
||||
uint32_t n = s->buf_size - s->buf_pos;
|
||||
if (n > len) n = len;
|
||||
memcpy(&s->buf[s->buf_pos], p, n);
|
||||
s->buf_pos += n, p += n, len -= n;
|
||||
if (s->buf_pos < s->buf_size) break;
|
||||
s->buf_pos = 0;
|
||||
if (!s->header_done) {
|
||||
if (!sb3_header(s)) return false;
|
||||
} else {
|
||||
if (s->blocks >= s->nboot.totalBlocks) return false;
|
||||
if ((nboot_status_t) nboot_sb3_load_block(
|
||||
&s->nboot, (uint32_t *) s->buf) != kStatus_NBOOT_Success) {
|
||||
return false;
|
||||
}
|
||||
s->blocks++;
|
||||
s->data = &s->buf[s->data_offset];
|
||||
if (!sb3_block(s)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Authenticate the image with the ROM, copy it to CPU2 memory.
|
||||
// See loader_process_sb_file()
|
||||
static bool sb3_process(const uint8_t *img, size_t len) {
|
||||
struct sb3 *s = &s_sb3;
|
||||
bool ok = false;
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->buf_size = sizeof(nboot_sb3_header_t);
|
||||
// Start ELS only if it is off: the ROM keeps keys in it after boot
|
||||
if ((CLKCTL0->PSCCTL0 & CLKCTL0_PSCCTL0_ELS_MASK) == 0 ||
|
||||
(CLKCTL0->PSCCTL1 & CLKCTL0_PSCCTL1_ELS_APB_MASK) == 0 ||
|
||||
(RSTCTL0->PRSTCTL0 & RSTCTL0_PRSTCTL0_ELS_MASK) != 0) {
|
||||
CLOCK_EnableClock(kCLOCK_Els);
|
||||
CLOCK_EnableClock(kCLOCK_ElsApb);
|
||||
RESET_PeripheralReset(kELS_RST_SHIFT_RSTn);
|
||||
}
|
||||
if (nboot_context_init(&s->nboot) == kStatus_NBOOT_Success) {
|
||||
ok = sb3_pump(s, img, (uint32_t) len) && s->executed;
|
||||
(void) nboot_context_deinit(&s->nboot);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Load the radio firmware to CPU2 and start it. See sb3_fw_reset() and
|
||||
// load_service_monolithic(), fsl_loader_utils.c. Call before changing the
|
||||
// boot clock: the ROM trims the ELS glitch detector for it, and after the
|
||||
// clock change ELS reports glitch events. Interrupts may be off.
|
||||
// Return 0 on success, or the failed step: 1 chip revision, 2 OTP, 3 image
|
||||
// load, 4 firmware start
|
||||
int hal_radio_init(void) {
|
||||
uint32_t n = 100000000; // Firmware start timeout, loop iterations
|
||||
bool ok;
|
||||
if ((SOCCTRL->CHIP_INFO & 15U) != 2U) return 1; // Image is for rev A2
|
||||
POWER_PowerOffBle();
|
||||
spin(100000);
|
||||
if (otp_init(0) != kStatus_Success) return 2;
|
||||
POWER_PowerOnBle();
|
||||
spin(100000);
|
||||
CPU2_MAGIC = 0;
|
||||
ok = sb3_process(radio_fw, (size_t) (radio_fw_end - radio_fw));
|
||||
(void) otp_deinit();
|
||||
if (!ok) return 3;
|
||||
CIU2_RST_SW3 |= CIU2_RST_SW3_CPU2_RST;
|
||||
while (CPU2_MAGIC != CPU2_MAGIC_VALUE) {
|
||||
if (--n == 0) return 4; // Firmware did not start
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
#include "RW612.h"
|
||||
|
||||
void Reset_Handler(void); // Defined below
|
||||
void Dummy_Handler(void); // Defined below
|
||||
void SysTick_Handler(void); // Defined in main.c
|
||||
void SystemInit(void); // Defined in main.c, called by reset handler
|
||||
void __StackTop(void); // Defined in link.ld
|
||||
void _image_size(void);
|
||||
|
||||
#define WEAK __attribute__((weak, alias("Default_Handler")))
|
||||
|
||||
void Default_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 SecureFault_Handler(void);
|
||||
WEAK void SVC_Handler(void);
|
||||
WEAK void DebugMon_Handler(void);
|
||||
WEAK void PendSV_Handler(void);
|
||||
WEAK void SysTick_Handler(void);
|
||||
WEAK void IntDefaultHandler(void);
|
||||
WEAK void WDT0_IRQHandler(void);
|
||||
WEAK void DMA0_IRQHandler(void);
|
||||
WEAK void GPIO_INTA_IRQHandler(void);
|
||||
WEAK void GPIO_INTB_IRQHandler(void);
|
||||
WEAK void PIN_INT0_IRQHandler(void);
|
||||
WEAK void PIN_INT1_IRQHandler(void);
|
||||
WEAK void PIN_INT2_IRQHandler(void);
|
||||
WEAK void PIN_INT3_IRQHandler(void);
|
||||
WEAK void UTICK_IRQHandler(void);
|
||||
WEAK void MRT_IRQHandler(void);
|
||||
WEAK void CTIMER0_IRQHandler(void);
|
||||
WEAK void CTIMER1_IRQHandler(void);
|
||||
WEAK void SCT0_IRQHandler(void);
|
||||
WEAK void CTIMER3_IRQHandler(void);
|
||||
WEAK void FLEXCOMM0_IRQHandler(void);
|
||||
WEAK void FLEXCOMM1_IRQHandler(void);
|
||||
WEAK void FLEXCOMM2_IRQHandler(void);
|
||||
WEAK void FLEXCOMM3_IRQHandler(void);
|
||||
WEAK void Reserved34_IRQHandler(void);
|
||||
WEAK void Reserved35_IRQHandler(void);
|
||||
WEAK void FLEXCOMM14_IRQHandler(void);
|
||||
WEAK void Reserved37_IRQHandler(void);
|
||||
WEAK void Reserved38_IRQHandler(void);
|
||||
WEAK void GFMRT_IRQHandler(void);
|
||||
WEAK void Reserved40_IRQHandler(void);
|
||||
WEAK void DMIC_IRQHandler(void);
|
||||
WEAK void WKDEEPSLEEP_IRQHandler(void);
|
||||
WEAK void HYPERVISOR_IRQHandler(void);
|
||||
WEAK void SECUREVIOLATION_IRQHandler(void);
|
||||
WEAK void HWVAD_IRQHandler(void);
|
||||
WEAK void Reserved46_IRQHandler(void);
|
||||
WEAK void Reserved47_IRQHandler(void);
|
||||
WEAK void RTC_IRQHandler(void);
|
||||
WEAK void Reserved49_IRQHandler(void);
|
||||
WEAK void Reserved50_IRQHandler(void);
|
||||
WEAK void PIN_INT4_IRQHandler(void);
|
||||
WEAK void PIN_INT5_IRQHandler(void);
|
||||
WEAK void PIN_INT6_IRQHandler(void);
|
||||
WEAK void PIN_INT7_IRQHandler(void);
|
||||
WEAK void CTIMER2_IRQHandler(void);
|
||||
WEAK void CTIMER4_IRQHandler(void);
|
||||
WEAK void OS_EVENT_TIMER_IRQHandler(void);
|
||||
WEAK void FLEXSPI_IRQHandler(void);
|
||||
WEAK void Reserved59_IRQHandler(void);
|
||||
WEAK void Reserved60_IRQHandler(void);
|
||||
WEAK void Reserved61_IRQHandler(void);
|
||||
WEAK void SDIO_IRQHandler(void);
|
||||
WEAK void SGPIO_INTA_IRQHandler(void);
|
||||
WEAK void SGPIO_INTB_IRQHandler(void);
|
||||
WEAK void Reserved65_IRQHandler(void);
|
||||
WEAK void USB_IRQHandler(void);
|
||||
WEAK void Reserved67_IRQHandler(void);
|
||||
WEAK void Reserved68_IRQHandler(void);
|
||||
WEAK void Reserved69_IRQHandler(void);
|
||||
WEAK void DMA1_IRQHandler(void);
|
||||
WEAK void PUF_IRQHandler(void);
|
||||
WEAK void POWERQUAD_IRQHandler(void);
|
||||
WEAK void Reserved73_IRQHandler(void);
|
||||
WEAK void Reserved74_IRQHandler(void);
|
||||
WEAK void Reserved75_IRQHandler(void);
|
||||
WEAK void Reserved76_IRQHandler(void);
|
||||
WEAK void LCD_IRQHandler(void);
|
||||
WEAK void CAPTIMER_IRQHandler(void);
|
||||
WEAK void Reserved79_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE0_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE1_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE2_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE3_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE4_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE5_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE6_IRQHandler(void);
|
||||
WEAK void W2MWKUP_DONE7_IRQHandler(void);
|
||||
WEAK void W2MWKUP0_IRQHandler(void);
|
||||
WEAK void W2MWKUP1_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT0_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT1_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT2_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT3_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT4_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT5_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT6_IRQHandler(void);
|
||||
WEAK void WL_MCI_INT7_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE0_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE1_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE2_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE3_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE4_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE5_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE6_IRQHandler(void);
|
||||
WEAK void B2MWKUP_DONE7_IRQHandler(void);
|
||||
WEAK void B2MWKUP0_IRQHandler(void);
|
||||
WEAK void B2MWKUP1_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT0_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT1_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT2_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT3_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT4_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT5_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT6_IRQHandler(void);
|
||||
WEAK void BLE_MCI_INT7_IRQHandler(void);
|
||||
WEAK void PIN0_INT_IRQHandler(void);
|
||||
WEAK void PIN1_INT_IRQHandler(void);
|
||||
WEAK void ELS_IRQHandler(void);
|
||||
WEAK void ELS_GDET_IRQHandler(void);
|
||||
WEAK void ELS_GDET_UM_IRQHandler(void);
|
||||
WEAK void PKC_INT_IRQHandler(void);
|
||||
WEAK void PKC_ERR_IRQHandler(void);
|
||||
WEAK void CDOG_INT_IRQHandler(void);
|
||||
WEAK void GAU_DAC_IRQHandler(void);
|
||||
WEAK void GAU_ACOMP_WKUP_IRQHandler(void);
|
||||
WEAK void GAU_ACOMP_IRQHandler(void);
|
||||
WEAK void GAU_ADC1_IRQHandler(void);
|
||||
WEAK void GAU_ADC0_IRQHandler(void);
|
||||
WEAK void USIM_IRQHandler(void);
|
||||
WEAK void OTP_IRQHandler(void);
|
||||
WEAK void ENET_IRQHandler(void);
|
||||
WEAK void ENET_TIMER_IRQHandler(void);
|
||||
WEAK void PMIP_IRQHandler(void);
|
||||
WEAK void PMIP_CHANGE_IRQHandler(void);
|
||||
WEAK void ITRC_IRQHandler(void);
|
||||
WEAK void Reserved136_IRQHandler(void);
|
||||
WEAK void Reserved137_IRQHandler(void);
|
||||
WEAK void Reserved138_IRQHandler(void);
|
||||
WEAK void TRNG_IRQHandler(void);
|
||||
WEAK void ACC_C_INT_IRQHandler(void);
|
||||
WEAK void ACC_S_INT_IRQHandler(void);
|
||||
WEAK void WACC_IRQHandler(void);
|
||||
WEAK void BACC_IRQHandler(void);
|
||||
WEAK void GDMA_IRQHandler(void);
|
||||
|
||||
|
||||
#define WEAK_ALIAS __attribute__((weak, alias("Default_Handler")))
|
||||
|
||||
|
||||
__attribute__((section(".vectors"))) void (*const tab[16 + 156])(void) = {
|
||||
&__StackTop, // The initial stack pointer
|
||||
Reset_Handler, // The reset handler
|
||||
NMI_Handler, // NMI Handler
|
||||
HardFault_Handler, // Hard Fault Handler
|
||||
MemManage_Handler, // MPU Fault Handler
|
||||
BusFault_Handler, // Bus Fault Handler
|
||||
UsageFault_Handler, // Usage Fault Handler
|
||||
SecureFault_Handler, // Secure Fault Handler
|
||||
&_image_size, // Image size
|
||||
0, // Image type
|
||||
0, // Reserved
|
||||
SVC_Handler, // SVCall Handler
|
||||
DebugMon_Handler, // Debug Monitor Handler
|
||||
(void (*)())tab, // Image load address
|
||||
PendSV_Handler, // PendSV Handler
|
||||
SysTick_Handler, // SysTick Handler
|
||||
|
||||
// Chip Level - RW612
|
||||
WDT0_IRQHandler, // 16 : Windowed watchdog timer 0 (WDT0)(Cortex-M33 watchdog)
|
||||
DMA0_IRQHandler, // 17 : Direct memory access (DMA) controller 0 (secure or Cortex-M33 DMA)
|
||||
GPIO_INTA_IRQHandler, // 18 : GPIO interrupt A
|
||||
GPIO_INTB_IRQHandler, // 19 : GPIO interrupt B
|
||||
PIN_INT0_IRQHandler, // 20 : Pin interrupt 0 or pattern match engine slice 0
|
||||
PIN_INT1_IRQHandler, // 21 : Pin interrupt 1 or pattern match engine slice 1
|
||||
PIN_INT2_IRQHandler, // 22 : Pin interrupt 2 or pattern match engine slice 2
|
||||
PIN_INT3_IRQHandler, // 23 : Pin interrupt 3 or pattern match engine slice 3
|
||||
UTICK_IRQHandler, // 24 : Micro-tick Timer (UTICK)
|
||||
MRT_IRQHandler, // 25 : Multi-Rate Timer (MRT). Global MRT interrupts
|
||||
CTIMER0_IRQHandler, // 26 : Standard counter/timer CTIMER0
|
||||
CTIMER1_IRQHandler, // 27 : Standard counter/timer CTIMER1
|
||||
SCT0_IRQHandler, // 28 : SCTimer/PWM
|
||||
CTIMER3_IRQHandler, // 29 : Standard counter/timer CTIMER3
|
||||
FLEXCOMM0_IRQHandler, // 30 : Flexcomm Interface 0 (USART, SPI, I2C, I2S)
|
||||
FLEXCOMM1_IRQHandler, // 31 : Flexcomm Interface 1 (USART, SPI, I2C, I2S)
|
||||
FLEXCOMM2_IRQHandler, // 32 : Flexcomm Interface 2 (USART, SPI, I2C, I2S)
|
||||
FLEXCOMM3_IRQHandler, // 33 : Flexcomm Interface 3 (USART, SPI, I2C, I2S)
|
||||
Reserved34_IRQHandler, // 34 : Reserved interrupt
|
||||
Reserved35_IRQHandler, // 35 : Reserved interrupt
|
||||
FLEXCOMM14_IRQHandler, // 36 : Flexcomm Interface 14 (USART, SPI, I2C, I2S)
|
||||
Reserved37_IRQHandler, // 37 : Reserved interrupt
|
||||
Reserved38_IRQHandler, // 38 : Reserved interrupt
|
||||
GFMRT_IRQHandler, // 39 : Free Multi-rate timer (GFMRT). Global MRT interrupts
|
||||
Reserved40_IRQHandler, // 40 : Reserved interrupt
|
||||
DMIC_IRQHandler, // 41 : Digital microphone (DMIC) and DMIC subsystem
|
||||
WKDEEPSLEEP_IRQHandler, // 42 : Wake-up from deep sleep
|
||||
HYPERVISOR_IRQHandler, // 43 : Hypervisor service software interrupt
|
||||
SECUREVIOLATION_IRQHandler, // 44 : Secure violation
|
||||
HWVAD_IRQHandler, // 45 : Hardware Voice Activity Detector
|
||||
Reserved46_IRQHandler, // 46 : Reserved interrupt
|
||||
Reserved47_IRQHandler, // 47 : Reserved interrupt
|
||||
RTC_IRQHandler, // 48 : RTC alarm and wake-up
|
||||
Reserved49_IRQHandler, // 49 : Reserved interrupt
|
||||
Reserved50_IRQHandler, // 50 : Reserved interrupt
|
||||
PIN_INT4_IRQHandler, // 51 : Pin interrupt 4 or pattern match engine slice 4
|
||||
PIN_INT5_IRQHandler, // 52 : Pin interrupt 5 or pattern match engine slice 5
|
||||
PIN_INT6_IRQHandler, // 53 : Pin interrupt 6 or pattern match engine slice 6
|
||||
PIN_INT7_IRQHandler, // 54 : Pin interrupt 7 or pattern match engine slice 7
|
||||
CTIMER2_IRQHandler, // 55 : Standard counter/timer CTIMER2
|
||||
CTIMER4_IRQHandler, // 56 : Standard counter/timer CTIMER4
|
||||
OS_EVENT_TIMER_IRQHandler, // 57 : OS event timer 0
|
||||
FLEXSPI_IRQHandler, // 58 : FLEXSPI interface
|
||||
Reserved59_IRQHandler, // 59 : Reserved interrupt
|
||||
Reserved60_IRQHandler, // 60 : Reserved interrupt
|
||||
Reserved61_IRQHandler, // 61 : Reserved interrupt
|
||||
SDIO_IRQHandler, // 62 : The secure digital interface
|
||||
SGPIO_INTA_IRQHandler, // 63 : Secure GPIO interrupt A
|
||||
SGPIO_INTB_IRQHandler, // 64 : Secure GPIO interrupt B
|
||||
Reserved65_IRQHandler, // 65 : Reserved interrupt
|
||||
USB_IRQHandler, // 66 : High-speed USB device/host
|
||||
Reserved67_IRQHandler, // 67 : Reserved interrupt
|
||||
Reserved68_IRQHandler, // 68 : Reserved interrupt
|
||||
Reserved69_IRQHandler, // 69 : Reserved interrupt
|
||||
DMA1_IRQHandler, // 70 : DMA controller 1 (non-secure or HiFi 4 DMA)
|
||||
PUF_IRQHandler, // 71 : Physical Unclonable Function
|
||||
POWERQUAD_IRQHandler, // 72 : PowerQuad math coprocessor
|
||||
Reserved73_IRQHandler, // 73 : Reserved interrupt
|
||||
Reserved74_IRQHandler, // 74 : Reserved interrupt
|
||||
Reserved75_IRQHandler, // 75 : Reserved interrupt
|
||||
Reserved76_IRQHandler, // 76 : Reserved interrupt
|
||||
LCD_IRQHandler, // 77 : LCDIC
|
||||
CAPTIMER_IRQHandler, // 78 : Capture timer
|
||||
Reserved79_IRQHandler, // 79 : Reserved interrupt
|
||||
W2MWKUP_DONE0_IRQHandler, // 80 : Wi-Fi to MCU, wakeup done 0
|
||||
W2MWKUP_DONE1_IRQHandler, // 81 : Wi-Fi to MCU, wakeup done 1
|
||||
W2MWKUP_DONE2_IRQHandler, // 82 : Wi-Fi to MCU, wakeup done 2
|
||||
W2MWKUP_DONE3_IRQHandler, // 83 : Wi-Fi to MCU, wakeup done 3
|
||||
W2MWKUP_DONE4_IRQHandler, // 84 : Wi-Fi to MCU, wakeup done 4
|
||||
W2MWKUP_DONE5_IRQHandler, // 85 : Wi-Fi to MCU, wakeup done 5
|
||||
W2MWKUP_DONE6_IRQHandler, // 86 : Wi-Fi to MCU, wakeup done 6
|
||||
W2MWKUP_DONE7_IRQHandler, // 87 : Wi-Fi to MCU, wakeup done 7
|
||||
W2MWKUP0_IRQHandler, // 88 : Wi-Fi to MCU, wakeup signal 0
|
||||
W2MWKUP1_IRQHandler, // 89 : Wi-Fi to MCU, wakueup signal 1
|
||||
WL_MCI_INT0_IRQHandler, // 90 : Wi-Fi to MCU interrupt 0
|
||||
WL_MCI_INT1_IRQHandler, // 91 : Reserved for Wi-Fi to MCU
|
||||
WL_MCI_INT2_IRQHandler, // 92 : Reserved for Wi-Fi to MCU
|
||||
WL_MCI_INT3_IRQHandler, // 93 : Reserved for Wi-Fi to MCU
|
||||
WL_MCI_INT4_IRQHandler, // 94 : Reserved for Wi-Fi to MCU
|
||||
WL_MCI_INT5_IRQHandler, // 95 : Reserved for Wi-Fi to MCU
|
||||
WL_MCI_INT6_IRQHandler, // 96 : Reserved for Wi-Fi to MCU
|
||||
WL_MCI_INT7_IRQHandler, // 97 : Reserved for Wi-Fi to MCU
|
||||
B2MWKUP_DONE0_IRQHandler, // 98 : Bluetooth LE/802.15.4 radio to MCU, wakeup done 0
|
||||
B2MWKUP_DONE1_IRQHandler, // 99 : Bluetooth LE/802.15.4 radio to MCU, wakeup done 1
|
||||
B2MWKUP_DONE2_IRQHandler, // 100: Bluetooth LE/802.15.4 radio to MCU, wakeup done 2
|
||||
B2MWKUP_DONE3_IRQHandler, // 101: Bluetooth LE/802.15.4 radio to MCU, wakeup done 3
|
||||
B2MWKUP_DONE4_IRQHandler, // 102: Bluetooth LE/802.15.4 radio to MCU, wakeup done 4
|
||||
B2MWKUP_DONE5_IRQHandler, // 103: Bluetooth LE/802.15.4 radio to MCU, wakeup done 5
|
||||
B2MWKUP_DONE6_IRQHandler, // 104: Bluetooth LE/802.15.4 radio to MCU, wakeup done 6
|
||||
B2MWKUP_DONE7_IRQHandler, // 105: Bluetooth LE/802.15.4 radio to MCU, wakeup done 7
|
||||
B2MWKUP0_IRQHandler, // 106: Bluetooth LE/802.15.4 radio to MCU, wakeup signal 0
|
||||
B2MWKUP1_IRQHandler, // 107: Bluetooth LE/802.15.4 radio to MCU, wakeup signal 1
|
||||
BLE_MCI_INT0_IRQHandler, // 108: Bluetooth LE/802.15.4 radio to MCU interrupt 0
|
||||
BLE_MCI_INT1_IRQHandler, // 109: Reserved for Bluetooth LE/802.15.4 radio to MCU
|
||||
BLE_MCI_INT2_IRQHandler, // 110: Reserved for Bluetooth LE/802.15.4 radio to MCU
|
||||
BLE_MCI_INT3_IRQHandler, // 111: Reserved for Bluetooth LE/802.15.4 radio to MCU
|
||||
BLE_MCI_INT4_IRQHandler, // 112: Reserved for Bluetooth LE/802.15.4 radio to MCU
|
||||
BLE_MCI_INT5_IRQHandler, // 113: Reserved for Bluetooth LE/802.15.4 radio to MCU
|
||||
BLE_MCI_INT6_IRQHandler, // 114: Reserved for Bluetooth LE/802.15.4 radio to MCU
|
||||
BLE_MCI_INT7_IRQHandler, // 115: Reserved for Bluetooth LE/802.15.4 radio to MCU
|
||||
PIN0_INT_IRQHandler, // 116: From AON GPIO
|
||||
PIN1_INT_IRQHandler, // 117: From AON GPIO
|
||||
ELS_IRQHandler, // 118: EdgeLock subsystem (ELS)
|
||||
ELS_GDET_IRQHandler, // 119: ELS IRQ line for GDET error
|
||||
ELS_GDET_UM_IRQHandler, // 120: ELS un-gated latched error
|
||||
PKC_INT_IRQHandler, // 121: Public key crypto-processor (PKC) interrupt
|
||||
PKC_ERR_IRQHandler, // 122: PKC error
|
||||
CDOG_INT_IRQHandler, // 123: Code watch dog timmer interrupt
|
||||
GAU_DAC_IRQHandler, // 124: General analog unit (GAU) digital to analog converter (DAC)
|
||||
GAU_ACOMP_WKUP_IRQHandler, // 125: GAU analog comparator (ACOMP) wake-up
|
||||
GAU_ACOMP_IRQHandler, // 126: GAU analog comparator
|
||||
GAU_ADC1_IRQHandler, // 127: GAU analog to digital converter 1 (ADC1)
|
||||
GAU_ADC0_IRQHandler, // 128: GAU analog to digital converter 0 (ADC0)
|
||||
USIM_IRQHandler, // 129: Universal subscriber identity module (USIM) interface
|
||||
OTP_IRQHandler, // 130: One time programmable (OTP) memory interrupt
|
||||
ENET_IRQHandler, // 131: Etheret interrupt
|
||||
ENET_TIMER_IRQHandler, // 132: Ethernet timer interrupt
|
||||
PMIP_IRQHandler, // 133: Power management IP (PMIP)
|
||||
PMIP_CHANGE_IRQHandler, // 134: PMIP change from 1 to 0
|
||||
ITRC_IRQHandler, // 135: Intrusion and tamper response controller (ITRC) interrupt request
|
||||
Reserved136_IRQHandler, // 136: Reserved interrupt
|
||||
Reserved137_IRQHandler, // 137: Reserved interrupt
|
||||
Reserved138_IRQHandler, // 138: Reserved interrupt
|
||||
TRNG_IRQHandler, // 139: TRNG interrupt request
|
||||
ACC_C_INT_IRQHandler, // 140: AHB memory access checker - Cortex-M33 code bus
|
||||
ACC_S_INT_IRQHandler, // 141: AHB memory access checker - Cortex-M33 sys bus
|
||||
WACC_IRQHandler, // 142: Wi-Fi accessed during power off
|
||||
BACC_IRQHandler, // 143: Bluetooth LE/802.15.4 radio accessed during power off
|
||||
GDMA_IRQHandler, // 144: General purpose direct memory access (GDMA) interrupt
|
||||
};
|
||||
|
||||
extern unsigned char _end[]; // End of data section, start of heap. See link.ld
|
||||
__attribute__((naked, noreturn)) void Reset_Handler(void) {
|
||||
__asm("cpsid i"); // Disable interrupts
|
||||
// Config VTOR & MSPLIM register
|
||||
__asm("LDR R0, =0xE000ED08 \n"
|
||||
"STR %0, [R0] \n"
|
||||
"LDR R1, [%0] \n"
|
||||
"MSR MSP, R1 \n"
|
||||
"MSR MSPLIM, %1 \n"
|
||||
:
|
||||
: "r"(tab), "r"(_end)
|
||||
: "r0", "r1");
|
||||
extern long _sbss, _ebss, _sdata, _edata, _sidata, _siram, _siiram, _eiram;
|
||||
for (long *dst = &_sbss; dst < &_ebss; dst++) *dst = 0;
|
||||
for (long *dst = &_sdata, *src = &_sidata; dst < &_edata;) *dst++ = *src++;
|
||||
for (long *dst = &_siram, *src = &_siiram; dst < &_eiram;) *dst++ = *src++;
|
||||
SystemInit();
|
||||
__asm("cpsie i"); // Reenable interrupts
|
||||
// Call main()
|
||||
extern void main(void);
|
||||
main();
|
||||
for (;;) (void) 0; // Infinite loop
|
||||
}
|
||||
|
||||
void SystemCoreClockUpdate (void) {
|
||||
|
||||
}
|
||||
|
||||
void Default_Handler(void) {
|
||||
for (;;) (void) 0;
|
||||
}
|
||||
@@ -65,6 +65,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -61,6 +61,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -65,6 +65,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -5,7 +5,12 @@
|
||||
#include "mongoose.h"
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
uint64_t tick = to_ms_since_boot(get_absolute_time());
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -33,7 +33,12 @@ static void driver_init(struct mg_mgr *mgr) {
|
||||
}
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
uint64_t tick = to_ms_since_boot(get_absolute_time());
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -58,7 +58,12 @@ static void driver_init(struct mg_mgr *mgr) {
|
||||
}
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
uint64_t tick = to_ms_since_boot(get_absolute_time());
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -39,6 +39,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
uint64_t tick = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
@@ -82,6 +82,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
uint64_t tick = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
@@ -195,6 +195,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
uint64_t tick = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Nucleo-C5A3ZI Mongoose Integration
|
||||
|
||||
The `.ioc2` file in this directory is pre-configured. Note that after the
|
||||
project generation, you should do the following to complete integraion:
|
||||
|
||||
1. Edit the linker script `.ld` file and increase heap and stack sizes to
|
||||
0x20000 and 0x4000 respectively
|
||||
2. Add Mongoose to the `main.c`, see https://mongoose.ws/docs/guides/stm32-tcpip-stack/#modify-mainc
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,46 @@
|
||||
# Copyright (c) 2026 Cesanta Software Limited
|
||||
# Environment setup: https://mongoose.ws/docs/getting-started/build-environment/
|
||||
|
||||
MGDIR = ../../../..
|
||||
|
||||
CFLAGS = -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion
|
||||
CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion
|
||||
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
|
||||
CFLAGS += -I. -I$(MGDIR) -Icmsis_core/CMSIS/Core/Include -Icmsis_c5/Include -DSTM32C5A3xx
|
||||
CFLAGS += -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard $(CFLAGS_EXTRA)
|
||||
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs nano.specs -lc -lgcc -Wl,--gc-sections
|
||||
|
||||
SOURCES = main.c hal.c
|
||||
SOURCES += cmsis_c5/Source/startup_stm32c5a3xx.c
|
||||
SOURCES += $(MGDIR)/mongoose.c
|
||||
|
||||
all build example: firmware.bin
|
||||
|
||||
firmware.elf: cmsis_core cmsis_c5 hal.h link.ld Makefile $(SOURCES) $(MGDIR)/mongoose.h mongoose_config.h
|
||||
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(CFLAGS_EXTRA) $(LDFLAGS) -o $@
|
||||
|
||||
firmware.bin: firmware.elf
|
||||
arm-none-eabi-objcopy -O binary $< $@
|
||||
@echo
|
||||
@echo "To flash, run 'make flash', or use STM32CubeProgrammer"
|
||||
|
||||
firmware.signed.bin: firmware.bin
|
||||
test -f private.pem || node $(MGDIR)/resources/sign.js keygen
|
||||
node $(MGDIR)/resources/sign.js sign firmware.bin
|
||||
|
||||
# Show all symbols sorted by size
|
||||
show_symbols_sorted_by_size: firmware.bin
|
||||
arm-none-eabi-readelf -sW firmware.elf | sed 1,3d | sed 's,^.*: ,,' | tr -s ' ' | cut -d ' ' -f 2,7 | sort -nk1 | grep -v '^0 '
|
||||
|
||||
# If the board gets stuck: STM32_Programmer_CLI -c port=swd -e all mode=UR
|
||||
flash: firmware.bin
|
||||
STM32_Programmer_CLI -c port=swd -w firmware.elf mode=UR -rst
|
||||
|
||||
cmsis_core:
|
||||
git clone -q -c advice.detachedHead=false --depth 1 -b v6.4.0 https://github.com/ARM-software/CMSIS_6 $@
|
||||
|
||||
cmsis_c5:
|
||||
git clone -q -c advice.detachedHead=false --depth 1 -b 2.1.0 https://github.com/STMicroelectronics/stm32c5xx-dfp $@
|
||||
|
||||
clean:
|
||||
rm -rf firmware.* cmsis_*
|
||||
@@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2026 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
// Added to minimise the bin size: avoid pulling printf and friends
|
||||
void __assert_func(const char *s, int line, const char *fn, const char *expr) {
|
||||
(void) s, (void) line, (void) fn, (void) expr;
|
||||
for (;;) (void) 0; // or trigger the fault handler
|
||||
}
|
||||
|
||||
bool hal_timer_expired(volatile uint64_t *t, uint64_t period, uint64_t now) {
|
||||
uint64_t diff = now - *t; // Wrap-safe elapsed time since last expiry
|
||||
if (period == 0) return false; // Avoid division by zero
|
||||
if (diff < period) return false; // Period has not elapsed yet
|
||||
*t += (diff / period) * period; // Preserve cadence, skip missed periods
|
||||
return true;
|
||||
}
|
||||
|
||||
static volatile uint64_t s_ticks; // Milliseconds since boot
|
||||
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
|
||||
s_ticks++;
|
||||
}
|
||||
|
||||
uint64_t hal_get_tick(void) {
|
||||
return s_ticks;
|
||||
};
|
||||
|
||||
uint32_t SystemCoreClock = 160000000;
|
||||
void SystemInit(void) { // Called automatically by startup code
|
||||
hal_system_init(); // Enable FPU
|
||||
hal_clock_init();
|
||||
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
|
||||
}
|
||||
|
||||
void ExitRun0Mode(void) {
|
||||
}
|
||||
|
||||
// C library entry, called by the CMSIS startup code after it copies .data
|
||||
// and clears .bss. See __cmsis_start() in cmsis_gcc_m.h
|
||||
extern int main(void);
|
||||
extern void __libc_init_array(void);
|
||||
__attribute__((noreturn)) void _start(void) {
|
||||
__libc_init_array();
|
||||
main();
|
||||
for (;;) (void) 0;
|
||||
}
|
||||
|
||||
struct stat;
|
||||
__attribute__((weak)) int _fstat(int fd, struct stat *st) {
|
||||
(void) fd, (void) st;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern unsigned char _end[]; // End of data section, start of heap. See link.ld
|
||||
static unsigned char *s_current_heap_end = _end;
|
||||
|
||||
size_t hal_ram_used(void) {
|
||||
return (size_t) (s_current_heap_end - _end);
|
||||
}
|
||||
|
||||
size_t hal_ram_free(void) {
|
||||
unsigned char endofstack;
|
||||
return (size_t) (&endofstack - s_current_heap_end);
|
||||
}
|
||||
|
||||
void *_sbrk(int incr) {
|
||||
unsigned char *prev_heap;
|
||||
unsigned char *heap_end = (unsigned char *) ((size_t) &heap_end - 256);
|
||||
prev_heap = s_current_heap_end;
|
||||
// Check how much space we got from the heap end to the stack end
|
||||
if (s_current_heap_end + incr > heap_end) return (void *) -1;
|
||||
s_current_heap_end += incr;
|
||||
return prev_heap;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _open(const char *path) {
|
||||
(void) path;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _close(int fd) {
|
||||
(void) fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _isatty(int fd) {
|
||||
(void) fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _lseek(int fd, int ptr, int dir) {
|
||||
(void) fd, (void) ptr, (void) dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _exit(int status) {
|
||||
(void) status;
|
||||
for (;;) asm volatile("BKPT #0");
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _kill(int pid, int sig) {
|
||||
(void) pid, (void) sig;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _getpid(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _read(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _link(const char *a, const char *b) {
|
||||
(void) a, (void) b;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _unlink(const char *a) {
|
||||
(void) a;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _stat(const char *path, struct stat *st) {
|
||||
(void) path, (void) st;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int mkdir(const char *path, int mode) {
|
||||
(void) path, (void) mode;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _init(void) {
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
// Copyright (c) 2013-2026 Cesanta Software Limited
|
||||
// Datasheet: RM0522, devboard manual: UM3616
|
||||
// https://www.st.com/resource/en/reference_manual/rm0522-stm32c5-series-armbased-32bit-mcus-stmicroelectronics.pdf
|
||||
// https://www.st.com/resource/en/user_manual/um3616-stm32c5-nucleo144-board-mb2310-stmicroelectronics.pdf
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stm32c5xx.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
extern bool hal_timer_expired(volatile uint64_t *t, uint64_t prd, uint64_t now);
|
||||
extern uint64_t hal_get_tick(void);
|
||||
extern size_t hal_ram_free(void);
|
||||
extern size_t hal_ram_used(void);
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
#define BIT(x) (1UL << (x))
|
||||
#define CLRSET(reg, clear, set) ((reg) = ((reg) & ~(clear)) | (set))
|
||||
#define PIN(bank, num) ((((bank) - 'A') << 8) | (num))
|
||||
#define PINNO(pin) (pin & 255)
|
||||
#define PINBANK(pin) (pin >> 8)
|
||||
|
||||
// Ethernet RMII pins and their alternate functions. UM3616 7.11, Table 9
|
||||
#define HAL_ETH_PINS \
|
||||
{PIN('A', 1), 10}, /* REF_CLK */ \
|
||||
{PIN('C', 1), 10}, /* MDC */ \
|
||||
{PIN('E', 12), 10}, /* MDIO */ \
|
||||
{PIN('D', 1), 10}, /* CRS_DV */ \
|
||||
{PIN('C', 4), 12}, /* RXD0 */ \
|
||||
{PIN('C', 5), 13}, /* RXD1 */ \
|
||||
{PIN('G', 11), 10}, /* TX_EN */ \
|
||||
{PIN('G', 13), 10}, /* TXD0 */ \
|
||||
{PIN('G', 12), 10} /* TXD1 */
|
||||
|
||||
// System clock (9.4.2, 9.4.8). HSI runs at 144 MHz, the maximum system clock:
|
||||
// SYSCLK = HSIS, no PLL. hclk = SYSCLK, APB clocks = hclk. After reset, the
|
||||
// system runs on HSIDIV3, 48 MHz. Flash latency for 144 MHz: 6.3.6, Table 20
|
||||
#define SYS_FREQUENCY 144000000
|
||||
#define AHB_FREQUENCY SYS_FREQUENCY
|
||||
#define APB2_FREQUENCY AHB_FREQUENCY
|
||||
#define APB1_FREQUENCY AHB_FREQUENCY
|
||||
#define HAL_FLASH_LATENCY (4 | FLASH_ACR_WRHIGHFREQ_1) // 4 WS, WRHIGHFREQ 2
|
||||
|
||||
enum { HAL_GPIO_MODE_INPUT, HAL_GPIO_MODE_OUTPUT, HAL_GPIO_MODE_AF, HAL_GPIO_MODE_ANALOG };
|
||||
enum { HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_OTYPE_OPEN_DRAIN };
|
||||
enum { HAL_GPIO_SPEED_LOW, HAL_GPIO_SPEED_MEDIUM, HAL_GPIO_SPEED_HIGH, HAL_GPIO_SPEED_INSANE };
|
||||
enum { HAL_GPIO_PULL_NONE, HAL_GPIO_PULL_UP, HAL_GPIO_PULL_DOWN };
|
||||
|
||||
#define HAL_GPIO(N) ((GPIO_TypeDef *) (GPIOA_BASE + 0x400 * (N)))
|
||||
|
||||
static GPIO_TypeDef *hal_gpio_bank(uint16_t pin) {
|
||||
return HAL_GPIO(PINBANK(pin));
|
||||
}
|
||||
static inline void hal_gpio_toggle(uint16_t pin) {
|
||||
GPIO_TypeDef *gpio = hal_gpio_bank(pin);
|
||||
uint32_t mask = BIT(PINNO(pin));
|
||||
gpio->BSRR = mask << (gpio->ODR & mask ? 16 : 0);
|
||||
}
|
||||
static inline int hal_gpio_read(uint16_t pin) {
|
||||
return hal_gpio_bank(pin)->IDR & BIT(PINNO(pin)) ? 1 : 0;
|
||||
}
|
||||
static inline void hal_gpio_write(uint16_t pin, bool val) {
|
||||
GPIO_TypeDef *gpio = hal_gpio_bank(pin);
|
||||
gpio->BSRR = BIT(PINNO(pin)) << (val ? 0 : 16);
|
||||
}
|
||||
static inline void hal_gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
|
||||
uint8_t speed, uint8_t pull, uint8_t af) {
|
||||
GPIO_TypeDef *gpio = hal_gpio_bank(pin);
|
||||
uint8_t n = (uint8_t) (PINNO(pin));
|
||||
RCC->AHB2ENR |= BIT(PINBANK(pin)); // Enable GPIO clock
|
||||
CLRSET(gpio->OTYPER, 1UL << n, ((uint32_t) type) << n);
|
||||
CLRSET(gpio->OSPEEDR, 3UL << (n * 2), ((uint32_t) speed) << (n * 2));
|
||||
CLRSET(gpio->PUPDR, 3UL << (n * 2), ((uint32_t) pull) << (n * 2));
|
||||
CLRSET(gpio->AFR[n >> 3], 15UL << ((n & 7) * 4),
|
||||
((uint32_t) af) << ((n & 7) * 4));
|
||||
CLRSET(gpio->MODER, 3UL << (n * 2), ((uint32_t) mode) << (n * 2));
|
||||
}
|
||||
static inline void hal_gpio_input(uint16_t pin) {
|
||||
hal_gpio_init(pin, HAL_GPIO_MODE_INPUT, HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_SPEED_HIGH,
|
||||
HAL_GPIO_PULL_NONE, 0);
|
||||
}
|
||||
static inline void hal_gpio_output(uint16_t pin) {
|
||||
hal_gpio_init(pin, HAL_GPIO_MODE_OUTPUT, HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_SPEED_HIGH,
|
||||
HAL_GPIO_PULL_NONE, 0);
|
||||
}
|
||||
|
||||
// USART1 kernel clock defaults to pclk2 (APB2), USART2,3 default to pclk1
|
||||
// (APB1), see RCC_CCIPR1
|
||||
static inline void hal_uart_init(USART_TypeDef *uart, uint16_t tx,
|
||||
uint16_t rx, unsigned long baud) {
|
||||
uint8_t af = 7; // Alternate function
|
||||
uint32_t freq = 0; // Bus frequency. UART1 is on APB2, rest on APB1
|
||||
|
||||
if (uart == USART1) freq = APB2_FREQUENCY, RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||
if (uart == USART2) freq = APB1_FREQUENCY, RCC->APB1LENR |= RCC_APB1LENR_USART2EN;
|
||||
if (uart == USART3) freq = APB1_FREQUENCY, RCC->APB1LENR |= RCC_APB1LENR_USART3EN;
|
||||
|
||||
hal_gpio_init(tx, HAL_GPIO_MODE_AF, HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_SPEED_HIGH, 0, af);
|
||||
hal_gpio_init(rx, HAL_GPIO_MODE_AF, HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_SPEED_HIGH, 0, af);
|
||||
uart->CR1 = 0; // Disable this UART
|
||||
uart->BRR = freq / baud; // Set baud rate
|
||||
uart->CR1 = BIT(0) | BIT(2) | BIT(3); // Set UE, RE, TE
|
||||
}
|
||||
static inline void hal_uart_write_byte(USART_TypeDef *uart, uint8_t byte) {
|
||||
uart->TDR = byte;
|
||||
while ((uart->ISR & USART_ISR_TXE_TXFNF) == 0) (void) 0;
|
||||
}
|
||||
static inline void hal_uart_write_buf(USART_TypeDef *uart, char *buf, size_t len) {
|
||||
while (len-- > 0) hal_uart_write_byte(uart, *(uint8_t *) buf++);
|
||||
}
|
||||
static inline int hal_uart_read_ready(USART_TypeDef *uart) {
|
||||
return uart->ISR & BIT(5); // If RXNE bit is set, data is ready
|
||||
}
|
||||
static inline uint8_t hal_uart_read_byte(USART_TypeDef *uart) {
|
||||
return (uint8_t) (uart->RDR & 255);
|
||||
}
|
||||
|
||||
// RNG clock (rng_clk) is CK48, which is disabled after reset. Use HSIDIV3,
|
||||
// 48 MHz. It stays enabled after the system clock switches to HSIS
|
||||
static inline void hal_rng_init(void) {
|
||||
CLRSET(RCC->CCIPR2, RCC_CCIPR2_CK48SEL_Msk, RCC_CCIPR2_CK48SEL_1);
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN; // Enable RNG AHB clock
|
||||
RNG->CR |= RNG_CR_RNGEN; // Enable RNG
|
||||
}
|
||||
|
||||
static inline uint32_t hal_rng_read(void) {
|
||||
while ((RNG->SR & RNG_SR_DRDY) == 0) (void) 0;
|
||||
return RNG->DR;
|
||||
}
|
||||
|
||||
static inline void hal_ethernet_init(void) {
|
||||
// Initialise Ethernet. Enable MAC GPIO pins, see UM3616 Table 9
|
||||
uint16_t pins[][2] = {HAL_ETH_PINS};
|
||||
for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
|
||||
hal_gpio_init(pins[i][0], HAL_GPIO_MODE_AF, HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_SPEED_INSANE,
|
||||
HAL_GPIO_PULL_NONE, (uint8_t) pins[i][1]);
|
||||
}
|
||||
NVIC_EnableIRQ(ETH1_IRQn); // Setup Ethernet IRQ handler
|
||||
RCC->APB3ENR |= RCC_APB3ENR_SBSEN; // Enable SBS clock
|
||||
CLRSET(SBS->PMCR, SBS_PMCR_ETH1_SEL_PHY_Msk, SBS_PMCR_ETH1_SEL_PHY_2); // RMII
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_ETH1CKEN | RCC_AHB1ENR_ETH1EN |
|
||||
RCC_AHB1ENR_ETH1TXEN | RCC_AHB1ENR_ETH1RXEN;
|
||||
}
|
||||
|
||||
static inline void hal_clock_init(void) {
|
||||
CLRSET(FLASH->ACR, FLASH_ACR_LATENCY_Msk | FLASH_ACR_WRHIGHFREQ_Msk,
|
||||
HAL_FLASH_LATENCY);
|
||||
while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (HAL_FLASH_LATENCY & 15)) (void) 0;
|
||||
RCC->CR1 |= RCC_CR1_HSISON; // Enable HSIS, 144 MHz
|
||||
while ((RCC->CR1 & RCC_CR1_HSISRDY) == 0) (void) 0; // Wait until ready
|
||||
CLRSET(RCC->CFGR1, RCC_CFGR1_SW_Msk, RCC_CFGR1_SW_0); // SYSCLK = HSIS
|
||||
while ((RCC->CFGR1 & RCC_CFGR1_SWS_Msk) != RCC_CFGR1_SWS_0) (void) 0;
|
||||
SystemCoreClock = SYS_FREQUENCY; // Update SystemCoreClock global var
|
||||
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
|
||||
}
|
||||
|
||||
static inline void hal_system_init(void) {
|
||||
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
ENTRY(Reset_Handler);
|
||||
MEMORY {
|
||||
flash(rx) : ORIGIN = 0x08000000, LENGTH = 1024k
|
||||
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 256k - 1k
|
||||
health(rw) : ORIGIN = 0x2003fc00, LENGTH = 1k /* Retained health record */
|
||||
}
|
||||
__StackTop = ORIGIN(sram) + LENGTH(sram); /* End of RAM. stack points here */
|
||||
_estack = __StackTop; /* Used by the health fault handler */
|
||||
__StackLimit = __StackTop - 16384; /* Stack limit, MSPLIM. TLS needs > 4 KB */
|
||||
|
||||
SECTIONS {
|
||||
.vectors : { KEEP(*(.vectors)) } > flash
|
||||
.text : { *(.text* .text.*) } > flash
|
||||
.rodata : { *(.rodata*) } > flash
|
||||
|
||||
/* Copy and zero tables for the CMSIS startup code, see __cmsis_start() */
|
||||
.copy.table : {
|
||||
__copy_table_start__ = .;
|
||||
LONG(LOADADDR(.data)) LONG(ADDR(.data)) LONG(SIZEOF(.data) / 4)
|
||||
__copy_table_end__ = .;
|
||||
} > flash
|
||||
.zero.table : {
|
||||
__zero_table_start__ = .;
|
||||
LONG(ADDR(.bss)) LONG(SIZEOF(.bss) / 4)
|
||||
__zero_table_end__ = .;
|
||||
} > flash
|
||||
|
||||
/* Note the .iram section, for functions copied to RAM. Required for MG_IRAM OTA support */
|
||||
.data : { _sdata = .; *(.first_data) *(.iram .iram* .iram.*) *(.data SORT(.data.*)) . = ALIGN(4); _edata = .; } > sram AT > flash
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
.bss : { _sbss = .; *(.bss SORT(.bss.*) COMMON) . = ALIGN(4); _ebss = .; } > sram
|
||||
_end = ALIGN(_ebss, 8); /* Heap starts after .bss */
|
||||
|
||||
/* Retained health record. Startup code must neither copy nor clear it. */
|
||||
.mg_health (NOLOAD) : { KEEP(*(.mg_health .mg_health*)) } > health
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright (c) 2026 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#include "hal.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
#define UART_DEBUG USART2 // ST-LINK virtual COM port, UM3616 7.12
|
||||
#define UART_DEBUG_TX_PIN PIN('A', 2)
|
||||
#define UART_DEBUG_RX_PIN PIN('A', 3)
|
||||
|
||||
#define LED1 PIN('A', 5) // Green, on when high. UM3616 7.8
|
||||
#define LED2 PIN('G', 1) // Red, on when low
|
||||
#define LED3 PIN('G', 2) // Blue, on when low
|
||||
|
||||
static void log_fn(char ch, void *param) {
|
||||
hal_uart_write_buf(param, &ch, 1);
|
||||
}
|
||||
|
||||
static void blink_task(void) {
|
||||
static uint64_t blink_timer = 0;
|
||||
if (hal_timer_expired(&blink_timer, 500, hal_get_tick())) {
|
||||
hal_gpio_toggle(LED2);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t mg_millis(void) {
|
||||
return hal_get_tick();
|
||||
}
|
||||
|
||||
bool mg_random(void *buf, size_t len) {
|
||||
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
|
||||
uint32_t r = hal_rng_read();
|
||||
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Self-signed P-256 certificate and key for the HTTPS listener. Created by:
|
||||
// openssl ecparam -genkey -name prime256v1 -noout -out key.pem
|
||||
// openssl req -x509 -key key.pem -out cert.pem -days 3650 -subj /CN=mg
|
||||
#define TLS_CERT \
|
||||
"-----BEGIN CERTIFICATE-----\n" \
|
||||
"MIIBgjCCASegAwIBAgIUIJOq77Qn7lHbH6WseMemeqorR50wCgYIKoZIzj0EAwIw\n" \
|
||||
"FjEUMBIGA1UEAwwLbnVjbGVvLWg3MjMwHhcNMjYxMDEyMTUwMjE5WhcNMzYxMDA5\n" \
|
||||
"MTUwMjE5WjAWMRQwEgYDVQQDDAtudWNsZW8taDcyMzBZMBMGByqGSM49AgEGCCqG\n" \
|
||||
"SM49AwEHA0IABB6IQJNmzrsdQL+2BnZYS7GYOaj7sz8f6cjBmz3n8D9Em19XodlU\n" \
|
||||
"uy4ybIvyhr766lL0ERoTmMUivb/lGmzx9C+jUzBRMB0GA1UdDgQWBBQqxMuc4gj7\n" \
|
||||
"MTMzreWlRMNI3QMqTzAfBgNVHSMEGDAWgBQqxMuc4gj7MTMzreWlRMNI3QMqTzAP\n" \
|
||||
"BgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQDY4xaJpuxq6b3rHK3b\n" \
|
||||
"lOIQyfkQX+orCRqQUkseplqpqwIhAKswZFNn+2zUNRRNY8+cHmdIwmdpsmxtoWYP\n" \
|
||||
"BCjX++LI\n" \
|
||||
"-----END CERTIFICATE-----\n"
|
||||
|
||||
#define TLS_KEY \
|
||||
"-----BEGIN EC PRIVATE KEY-----\n" \
|
||||
"MHcCAQEEIJ/GBl0TlD52q9PMg1KWaNIdXqp8b/HyIsABmBpqC+O1oAoGCCqGSM49\n" \
|
||||
"AwEHoUQDQgAEHohAk2bOux1Av7YGdlhLsZg5qPuzPx/pyMGbPefwP0SbX1eh2VS7\n" \
|
||||
"LjJsi/KGvvrqUvQRGhOYxSK9v+UabPH0Lw==\n" \
|
||||
"-----END EC PRIVATE KEY-----\n"
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_ACCEPT && c->is_tls) { // Accepted on the https:// listener
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
mg_http_reply(c, 200, "", "{%m:%llu}\n", MG_ESC("tick"), hal_get_tick());
|
||||
} else if (mg_match(hm->uri, mg_str("/api/crash"), NULL)) {
|
||||
__asm volatile("udf #0"); // Trigger HardFault
|
||||
} else {
|
||||
mg_http_reply(c, 200, "",
|
||||
"Hi from Mongoose!\n"
|
||||
"tick: %llu\n"
|
||||
"ram used: %zu\n"
|
||||
"ram free: %zu\n",
|
||||
hal_get_tick(), hal_ram_used(), hal_ram_free());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
MG_HEALTH_INIT();
|
||||
|
||||
hal_clock_init();
|
||||
hal_uart_init(UART_DEBUG, UART_DEBUG_TX_PIN, UART_DEBUG_RX_PIN, 115200);
|
||||
mg_log_set_fn(log_fn, UART_DEBUG);
|
||||
hal_rng_init();
|
||||
hal_ethernet_init();
|
||||
hal_gpio_output(LED1);
|
||||
hal_gpio_output(LED2);
|
||||
hal_gpio_output(LED3);
|
||||
|
||||
struct mg_mgr mgr;
|
||||
mg_mgr_init(&mgr);
|
||||
mg_http_listen(&mgr, "http://0.0.0.0", http_ev_handler, NULL);
|
||||
mg_http_listen(&mgr, "https://0.0.0.0", http_ev_handler, NULL);
|
||||
|
||||
MG_INFO(("Initialised. CPU clock: %lu MHz", SystemCoreClock / 1000000));
|
||||
MG_INFO(("RAM used: %zu, free: %zu", hal_ram_used(), hal_ram_free()));
|
||||
MG_INFO(("Crash record: %M", mg_print_crash_record));
|
||||
|
||||
for (;;) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
blink_task();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "hal.h"
|
||||
|
||||
// See https://mongoose.ws/docs/getting-started/build-environment/
|
||||
#define MG_ARCH MG_ARCH_ARMGCC
|
||||
#define MG_TLS MG_TLS_BUILTIN
|
||||
#define MG_OTA MG_OTA_STM32C5
|
||||
|
||||
#define MG_ENABLE_TCPIP 1
|
||||
#define MG_ENABLE_CUSTOM_MILLIS 1
|
||||
#define MG_ENABLE_CUSTOM_RANDOM 1
|
||||
#define MG_ENABLE_DRIVER_STM32C 1
|
||||
|
||||
// Construct MAC address from the MCU unique ID
|
||||
#define MGUID ((uint32_t *) UID_BASE)
|
||||
#define MG_SET_MAC_ADDRESS(mac) \
|
||||
do { \
|
||||
mac[0] = 2; \
|
||||
mac[1] = MGUID[0] & 255; \
|
||||
mac[2] = (MGUID[0] >> 10) & 255; \
|
||||
mac[3] = (MGUID[0] >> 19) & 255; \
|
||||
mac[4] = MGUID[1] & 255; \
|
||||
mac[5] = MGUID[2] & 255; \
|
||||
} while (0)
|
||||
|
||||
// Crash report support. Health record lives in the .mg_health region, see link.ld
|
||||
#define MG_ENABLE_HEALTH 1
|
||||
|
||||
// mdash.net device management service support
|
||||
#define MG_ENABLE_MDASH 0
|
||||
#define MG_MDASH_KEY "..." // Set this - mDash device token
|
||||
#define MG_FIRMWARE_VERSION "c5a3.1.0.0"
|
||||
@@ -66,7 +66,12 @@ static bool usb_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
}
|
||||
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/debug"), NULL)) {
|
||||
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
|
||||
|
||||
@@ -68,6 +68,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -28,7 +28,12 @@ bool mg_random(void *buf, size_t len) { // Use on-board RNG
|
||||
|
||||
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
(void) hm;
|
||||
mg_http_reply(c, 200, "", "hi\n");
|
||||
|
||||
@@ -66,7 +66,12 @@ static bool usb_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
}
|
||||
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/debug"), NULL)) {
|
||||
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
|
||||
|
||||
@@ -68,6 +68,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -68,6 +68,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -47,7 +47,12 @@ static void timer_fn(void *arg) {
|
||||
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->fn_data;
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/hello"),
|
||||
NULL)) { // Request to /api/hello
|
||||
|
||||
@@ -68,6 +68,11 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_tls_opts opts = {.cert = mg_str(TLS_CERT),
|
||||
.key = mg_str(TLS_KEY)};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/ota"), NULL)) {
|
||||
mg_http_stream_body(c, hm, mg_http_ota_cb, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
[PreviousGenFiles]
|
||||
AdvancedFolderStructure=true
|
||||
HeaderFileListSize=4
|
||||
HeaderFiles#0=..\Core\Inc\FreeRTOSConfig.h
|
||||
HeaderFiles#1=..\Core\Inc\stm32h7xx_it.h
|
||||
HeaderFiles#2=..\Core\Inc\stm32h7xx_hal_conf.h
|
||||
HeaderFiles#3=..\Core\Inc\main.h
|
||||
HeaderFolderListSize=1
|
||||
HeaderPath#0=..\Core\Inc
|
||||
HeaderFiles=;
|
||||
SourceFileListSize=5
|
||||
SourceFiles#0=..\Core\Src\freertos.c
|
||||
SourceFiles#1=..\Core\Src\stm32h7xx_it.c
|
||||
SourceFiles#2=..\Core\Src\stm32h7xx_hal_msp.c
|
||||
SourceFiles#3=..\Core\Src\stm32h7xx_hal_timebase_tim.c
|
||||
SourceFiles#4=..\Core\Src\main.c
|
||||
SourceFolderListSize=1
|
||||
SourcePath#0=..\Core\Src
|
||||
SourceFiles=;
|
||||
|
||||
[PreviousLibFiles]
|
||||
LibFiles=Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_tim.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_tim_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_eth.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_eth_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_bus.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_crs.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_system.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_utils.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_flash.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_flash_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_gpio.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_gpio_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_gpio.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_hsem.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_hsem.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_dma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_dma_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_dma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_dmamux.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_mdma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_pwr.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_pwr_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_pwr.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_def.h;Drivers\STM32H7xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_i2c.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_i2c_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_exti.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_exti.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rng.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rng_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_rng.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_uart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_usart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_lpuart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_uart_ex.h;Middlewares\Third_Party\FreeRTOS\Source\include\croutine.h;Middlewares\Third_Party\FreeRTOS\Source\include\deprecated_definitions.h;Middlewares\Third_Party\FreeRTOS\Source\include\event_groups.h;Middlewares\Third_Party\FreeRTOS\Source\include\FreeRTOS.h;Middlewares\Third_Party\FreeRTOS\Source\include\list.h;Middlewares\Third_Party\FreeRTOS\Source\include\message_buffer.h;Middlewares\Third_Party\FreeRTOS\Source\include\mpu_prototypes.h;Middlewares\Third_Party\FreeRTOS\Source\include\mpu_wrappers.h;Middlewares\Third_Party\FreeRTOS\Source\include\mpu_syscall_numbers.h;Middlewares\Third_Party\FreeRTOS\Source\include\portable.h;Middlewares\Third_Party\FreeRTOS\Source\include\projdefs.h;Middlewares\Third_Party\FreeRTOS\Source\include\queue.h;Middlewares\Third_Party\FreeRTOS\Source\include\semphr.h;Middlewares\Third_Party\FreeRTOS\Source\include\stack_macros.h;Middlewares\Third_Party\FreeRTOS\Source\include\StackMacros.h;Middlewares\Third_Party\FreeRTOS\Source\include\stream_buffer.h;Middlewares\Third_Party\FreeRTOS\Source\include\task.h;Middlewares\Third_Party\FreeRTOS\Source\include\timers.h;Middlewares\Third_Party\FreeRTOS\Source\include\newlib-freertos.h;Middlewares\Third_Party\FreeRTOS\Source\include\picolibc-freertos.h;Middlewares\Third_Party\FreeRTOS\Source\include\atomic.h;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2\cmsis_os2.h;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2\cmsis_os.h;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2\freertos_mpool.h;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2\freertos_os2.h;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM4F\portmacro.h;Drivers\CMSIS\RTOS2\Include\cmsis_os2.h;Drivers\CMSIS\RTOS2\Include\os_tick.h;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_eth.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_eth_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;Drivers\STM32H7xx_Line truncated
|
||||
|
||||
[PreviousUsedCMakes]
|
||||
SourceFiles=Core\Src\main.c;Core\Src\freertos.c;Core\Src\stm32h7xx_it.c;Core\Src\stm32h7xx_hal_msp.c;Core\Src\stm32h7xx_hal_timebase_tim.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_eth.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_eth_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rng.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rng_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;Middlewares\Third_Party\FreeRTOS\Source\portable\Common\mpu_wrappers_v2.c;Middlewares\Third_Party\FreeRTOS\Source\croutine.c;Middlewares\Third_Party\FreeRTOS\Source\event_groups.c;Middlewares\Third_Party\FreeRTOS\Source\list.c;Middlewares\Third_Party\FreeRTOS\Source\queue.c;Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.c;Middlewares\Third_Party\FreeRTOS\Source\tasks.c;Middlewares\Third_Party\FreeRTOS\Source\timers.c;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2\cmsis_os2.c;Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang\heap_4.c;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM4F\port.c;Drivers\CMSIS\Device\ST\STM32H7xx\Source\Templates\system_stm32h7xx.c;Core\Src\system_stm32h7xx.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_eth.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_eth_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rng.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rng_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;Middlewares\Third_Party\FreeRTOS\Source\portable\Common\mpu_wrappers_v2.c;Middlewares\Third_Party\FreeRTOS\Source\croutine.c;Middlewares\Third_Party\FreeRTOS\Source\event_groups.c;Middlewares\Third_Party\FreeRTOS\Source\list.c;Middlewares\Third_Party\FreeRTOS\Source\queue.c;Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.c;Middlewares\Third_Party\FreeRTOS\Source\tasks.c;Middlewares\Third_Party\FreeRTOS\Source\timers.c;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2\cmsis_os2.c;Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang\heap_4.c;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM4F\port.c;Drivers\CMSIS\Device\ST\STM32H7xx\Source\Templates\system_stm32h7xx.c;Core\Src\system_stm32h7xx.c;;;Middlewares\Third_Party\FreeRTOS\Source\portable\Common\mpu_wrappers_v2.c;Middlewares\Third_Party\FreeRTOS\Source\croutine.c;Middlewares\Third_Party\FreeRTOS\Source\event_groups.c;Middlewares\Third_Party\FreeRTOS\Source\list.c;Middlewares\Third_Party\FreeRTOS\Source\queue.c;Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.c;Middlewares\Third_Party\FreeRTOS\Source\tasks.c;Middlewares\Third_Party\FreeRTOS\Source\timers.c;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2\cmsis_os2.c;Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang\heap_4.c;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM4F\port.c;
|
||||
HeaderPath=Drivers\STM32H7xx_HAL_Driver\Inc;Drivers\STM32H7xx_HAL_Driver\Inc\Legacy;Middlewares\Third_Party\FreeRTOS\Source\include;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS_V2;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM4F;Drivers\CMSIS\RTOS2\Include;Drivers\CMSIS\Device\ST\STM32H7xx\Include;Drivers\CMSIS\Include;Core\Inc;
|
||||
CDefines=USE_PWR_LDO_SUPPLY;USE_HAL_DRIVER;STM32H723xx;USE_HAL_DRIVER;USE_HAL_DRIVER;
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
#
|
||||
# This file is generated only once,
|
||||
# and is not re-generated if converter is called multiple times.
|
||||
#
|
||||
# User is free to modify the file as much as necessary
|
||||
#
|
||||
|
||||
# Setup compiler settings
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
|
||||
|
||||
# Define the build type
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
|
||||
# Set the project name
|
||||
set(CMAKE_PROJECT_NAME nucleo-h723zg)
|
||||
|
||||
# Enable compile command to ease indexing with e.g. clangd
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
||||
|
||||
# Core project settings
|
||||
project(${CMAKE_PROJECT_NAME})
|
||||
message("Build type: " ${CMAKE_BUILD_TYPE})
|
||||
|
||||
# Enable CMake support for ASM and C languages
|
||||
enable_language(C ASM)
|
||||
|
||||
# Create an executable object type
|
||||
add_executable(${CMAKE_PROJECT_NAME})
|
||||
|
||||
# Add STM32CubeMX generated sources
|
||||
add_subdirectory(cmake/stm32cubemx)
|
||||
|
||||
# Link directories setup
|
||||
target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
# Add user defined library search paths
|
||||
)
|
||||
|
||||
# Add sources to executable
|
||||
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
# Add user sources here
|
||||
#${CMAKE_SOURCE_DIR}/../../../../mongoose.c
|
||||
${CMAKE_SOURCE_DIR}/mongoose/mongoose.c
|
||||
)
|
||||
|
||||
# Add include paths
|
||||
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
# Add user defined include paths
|
||||
${CMAKE_SOURCE_DIR}/mongoose/
|
||||
#${CMAKE_SOURCE_DIR}/../../../../
|
||||
)
|
||||
|
||||
# Add project symbols (macros)
|
||||
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
# Add user defined symbols
|
||||
)
|
||||
|
||||
# Remove wrong libob.a library dependency when using cpp files
|
||||
list(REMOVE_ITEM CMAKE_C_IMPLICIT_LINK_LIBRARIES ob)
|
||||
|
||||
# Add linked libraries
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
stm32cubemx
|
||||
|
||||
# Add user defined libraries
|
||||
)
|
||||
|
||||
# Generate .bin from .elf
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
|
||||
COMMAND arm-none-eabi-objcopy -O binary $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${CMAKE_PROJECT_NAME}.bin
|
||||
VERBATIM
|
||||
)
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake",
|
||||
"cacheVariables": {
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Debug",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Release",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "Debug",
|
||||
"configurePreset": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "Release",
|
||||
"configurePreset": "Release"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/*
|
||||
* FreeRTOS Kernel V10.6.2
|
||||
* Portion Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Portion Copyright (C) 2019 StMicroelectronics, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* These parameters and more are described within the 'configuration' section of the
|
||||
* FreeRTOS API documentation available on the FreeRTOS.org web site.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* USER CODE BEGIN Includes */
|
||||
/* Section where include file can be added */
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Ensure definitions are only used by the compiler, and not by the assembler. */
|
||||
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
|
||||
#include <stdint.h>
|
||||
extern uint32_t SystemCoreClock;
|
||||
#endif
|
||||
#ifndef CMSIS_device_header
|
||||
#define CMSIS_device_header "stm32h7xx.h"
|
||||
#endif /* CMSIS_device_header */
|
||||
|
||||
#define configENABLE_FPU 0
|
||||
#define configENABLE_MPU 0
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configSUPPORT_STATIC_ALLOCATION 1
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
#define configUSE_IDLE_HOOK 0
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCPU_CLOCK_HZ ( SystemCoreClock )
|
||||
#define configTICK_RATE_HZ ((TickType_t)1000)
|
||||
#define configMAX_PRIORITIES ( 56 )
|
||||
#define configUSE_SB_COMPLETED_CALLBACK ( 0 )
|
||||
#define configUSE_MINI_LIST_ITEM ( 1 )
|
||||
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
|
||||
#define configTOTAL_HEAP_SIZE ((size_t)65536)
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configHEAP_CLEAR_MEMORY_ON_FREE 0
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 8
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||
/* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */
|
||||
/* Defaults to size_t for backward compatibility, but can be changed
|
||||
if lengths will always be less than the number of bytes in a size_t. */
|
||||
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
|
||||
/* USER CODE END MESSAGE_BUFFER_LENGTH_TYPE */
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
|
||||
/* Software timer definitions. */
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY ( 2 )
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH 256
|
||||
|
||||
/* CMSIS-RTOS V2 flags */
|
||||
#define configUSE_OS2_THREAD_SUSPEND_RESUME 1
|
||||
#define configUSE_OS2_THREAD_ENUMERATE 1
|
||||
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 1
|
||||
#define configUSE_OS2_THREAD_FLAGS 1
|
||||
#define configUSE_OS2_TIMER 1
|
||||
#define configUSE_OS2_MUTEX 1
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskCleanUpResources 0
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_xTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
#define INCLUDE_xQueueGetMutexHolder 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
|
||||
/*
|
||||
* The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
|
||||
* by the application thus the correct define need to be enabled below
|
||||
*/
|
||||
#define USE_FreeRTOS_HEAP_4
|
||||
|
||||
/* Cortex-M specific definitions. */
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
#else
|
||||
#define configPRIO_BITS 4
|
||||
#endif
|
||||
|
||||
/* The lowest interrupt priority that can be used in a call to a "set priority"
|
||||
function. */
|
||||
|
||||
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
|
||||
|
||||
/* The highest interrupt priority that can be used by any interrupt service
|
||||
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
|
||||
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
|
||||
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
|
||||
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
|
||||
|
||||
/* Interrupt priorities used by the kernel port layer itself. These are generic
|
||||
to all Cortex-M ports, and do not rely on any particular library functions. */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h
|
||||
header file. */
|
||||
/* USER CODE BEGIN 1 */
|
||||
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
|
||||
/* USER CODE END 1 */
|
||||
|
||||
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
|
||||
standard names. */
|
||||
#define vPortSVCHandler SVC_Handler
|
||||
#define xPortPendSVHandler PendSV_Handler
|
||||
/* IMPORTANT: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */
|
||||
|
||||
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0
|
||||
|
||||
/* USER CODE BEGIN Defines */
|
||||
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
|
||||
/* USER CODE END Defines */
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
@@ -1,69 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.h
|
||||
* @brief : Header for main.c file.
|
||||
* This file contains the common defines of the application.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32h7xx_hal.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
@@ -1,514 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32h7xx_hal_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief HAL configuration file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef STM32H7xx_HAL_CONF_H
|
||||
#define STM32H7xx_HAL_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* ########################## Module Selection ############################## */
|
||||
/**
|
||||
* @brief This is the list of modules to be used in the HAL driver
|
||||
*/
|
||||
#define HAL_MODULE_ENABLED
|
||||
|
||||
/* #define HAL_ADC_MODULE_ENABLED */
|
||||
/* #define HAL_FDCAN_MODULE_ENABLED */
|
||||
/* #define HAL_FMAC_MODULE_ENABLED */
|
||||
/* #define HAL_CEC_MODULE_ENABLED */
|
||||
/* #define HAL_COMP_MODULE_ENABLED */
|
||||
/* #define HAL_CORDIC_MODULE_ENABLED */
|
||||
/* #define HAL_CRC_MODULE_ENABLED */
|
||||
/* #define HAL_CRYP_MODULE_ENABLED */
|
||||
/* #define HAL_DAC_MODULE_ENABLED */
|
||||
/* #define HAL_DCMI_MODULE_ENABLED */
|
||||
/* #define HAL_DMA2D_MODULE_ENABLED */
|
||||
#define HAL_ETH_MODULE_ENABLED
|
||||
/* #define HAL_ETH_LEGACY_MODULE_ENABLED */
|
||||
/* #define HAL_NAND_MODULE_ENABLED */
|
||||
/* #define HAL_NOR_MODULE_ENABLED */
|
||||
/* #define HAL_OTFDEC_MODULE_ENABLED */
|
||||
/* #define HAL_SRAM_MODULE_ENABLED */
|
||||
/* #define HAL_SDRAM_MODULE_ENABLED */
|
||||
/* #define HAL_HASH_MODULE_ENABLED */
|
||||
/* #define HAL_HRTIM_MODULE_ENABLED */
|
||||
/* #define HAL_HSEM_MODULE_ENABLED */
|
||||
/* #define HAL_GFXMMU_MODULE_ENABLED */
|
||||
/* #define HAL_JPEG_MODULE_ENABLED */
|
||||
/* #define HAL_OPAMP_MODULE_ENABLED */
|
||||
/* #define HAL_OSPI_MODULE_ENABLED */
|
||||
/* #define HAL_I2S_MODULE_ENABLED */
|
||||
/* #define HAL_SMBUS_MODULE_ENABLED */
|
||||
/* #define HAL_IWDG_MODULE_ENABLED */
|
||||
/* #define HAL_LPTIM_MODULE_ENABLED */
|
||||
/* #define HAL_LTDC_MODULE_ENABLED */
|
||||
/* #define HAL_QSPI_MODULE_ENABLED */
|
||||
/* #define HAL_RAMECC_MODULE_ENABLED */
|
||||
#define HAL_RNG_MODULE_ENABLED
|
||||
/* #define HAL_RTC_MODULE_ENABLED */
|
||||
/* #define HAL_SAI_MODULE_ENABLED */
|
||||
/* #define HAL_SD_MODULE_ENABLED */
|
||||
/* #define HAL_MMC_MODULE_ENABLED */
|
||||
/* #define HAL_SPDIFRX_MODULE_ENABLED */
|
||||
/* #define HAL_SPI_MODULE_ENABLED */
|
||||
/* #define HAL_SWPMI_MODULE_ENABLED */
|
||||
#define HAL_TIM_MODULE_ENABLED
|
||||
#define HAL_UART_MODULE_ENABLED
|
||||
/* #define HAL_USART_MODULE_ENABLED */
|
||||
/* #define HAL_IRDA_MODULE_ENABLED */
|
||||
/* #define HAL_SMARTCARD_MODULE_ENABLED */
|
||||
/* #define HAL_WWDG_MODULE_ENABLED */
|
||||
/* #define HAL_PCD_MODULE_ENABLED */
|
||||
/* #define HAL_HCD_MODULE_ENABLED */
|
||||
/* #define HAL_DFSDM_MODULE_ENABLED */
|
||||
/* #define HAL_DSI_MODULE_ENABLED */
|
||||
/* #define HAL_JPEG_MODULE_ENABLED */
|
||||
/* #define HAL_MDIOS_MODULE_ENABLED */
|
||||
/* #define HAL_PSSI_MODULE_ENABLED */
|
||||
/* #define HAL_DTS_MODULE_ENABLED */
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_DMA_MODULE_ENABLED
|
||||
#define HAL_MDMA_MODULE_ENABLED
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
#define HAL_FLASH_MODULE_ENABLED
|
||||
#define HAL_EXTI_MODULE_ENABLED
|
||||
#define HAL_PWR_MODULE_ENABLED
|
||||
#define HAL_I2C_MODULE_ENABLED
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
#define HAL_HSEM_MODULE_ENABLED
|
||||
|
||||
/* ########################## Oscillator Values adaptation ####################*/
|
||||
/**
|
||||
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
* (when HSE is used as system clock source, directly or through the PLL).
|
||||
*/
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE (25000000UL) /*!< Value of the External oscillator in Hz : FPGA case fixed to 60MHZ */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSE_STARTUP_TIMEOUT)
|
||||
#define HSE_STARTUP_TIMEOUT (100UL) /*!< Time out for HSE start up, in ms */
|
||||
#endif /* HSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal oscillator (CSI) default value.
|
||||
* This value is the default CSI value after Reset.
|
||||
*/
|
||||
#if !defined (CSI_VALUE)
|
||||
#define CSI_VALUE (4000000UL) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* CSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Internal High Speed oscillator (HSI) value.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
* (when HSI is used as system clock source, directly or through the PLL).
|
||||
*/
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE (64000000UL) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief External Low Speed oscillator (LSE) value.
|
||||
* This value is used by the UART, RTC HAL module to compute the system frequency
|
||||
*/
|
||||
#if !defined (LSE_VALUE)
|
||||
#define LSE_VALUE (32768UL) /*!< Value of the External oscillator in Hz*/
|
||||
#endif /* LSE_VALUE */
|
||||
|
||||
#if !defined (LSE_STARTUP_TIMEOUT)
|
||||
#define LSE_STARTUP_TIMEOUT (5000UL) /*!< Time out for LSE start up, in ms */
|
||||
#endif /* LSE_STARTUP_TIMEOUT */
|
||||
|
||||
#if !defined (LSI_VALUE)
|
||||
#define LSI_VALUE (32000UL) /*!< LSI Typical Value in Hz*/
|
||||
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
|
||||
The real value may vary depending on the variations
|
||||
in voltage and temperature.*/
|
||||
|
||||
/**
|
||||
* @brief External clock source for I2S peripheral
|
||||
* This value is used by the I2S HAL module to compute the I2S clock source
|
||||
* frequency, this source is inserted directly through I2S_CKIN pad.
|
||||
*/
|
||||
#if !defined (EXTERNAL_CLOCK_VALUE)
|
||||
#define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/
|
||||
#endif /* EXTERNAL_CLOCK_VALUE */
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to use different HSE,
|
||||
=== you can define the HSE value in your toolchain compiler preprocessor. */
|
||||
|
||||
/* ########################### System Configuration ######################### */
|
||||
/**
|
||||
* @brief This is the HAL system configuration section
|
||||
*/
|
||||
#define VDD_VALUE (3300UL) /*!< Value of VDD in mv */
|
||||
#define TICK_INT_PRIORITY (15UL) /*!< tick interrupt priority */
|
||||
#define USE_RTOS 0
|
||||
#define USE_SD_TRANSCEIVER 0U /*!< use uSD Transceiver */
|
||||
#define USE_SPI_CRC 0U /*!< use CRC in SPI */
|
||||
|
||||
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
|
||||
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
|
||||
#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */
|
||||
#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */
|
||||
#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */
|
||||
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
|
||||
#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */
|
||||
#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */
|
||||
#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */
|
||||
#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */
|
||||
#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */
|
||||
#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
|
||||
#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */
|
||||
#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */
|
||||
#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */
|
||||
#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */
|
||||
#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */
|
||||
#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */
|
||||
#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */
|
||||
#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */
|
||||
#define USE_HAL_GFXMMU_REGISTER_CALLBACKS 0U /* GFXMMU register callback disabled */
|
||||
#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */
|
||||
#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */
|
||||
#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */
|
||||
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */
|
||||
#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */
|
||||
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */
|
||||
#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */
|
||||
#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */
|
||||
#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */
|
||||
#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */
|
||||
#define USE_HAL_OSPI_REGISTER_CALLBACKS 0U /* OSPI register callback disabled */
|
||||
#define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */
|
||||
#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */
|
||||
#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */
|
||||
#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */
|
||||
#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */
|
||||
#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */
|
||||
#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */
|
||||
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */
|
||||
#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */
|
||||
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */
|
||||
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */
|
||||
#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */
|
||||
#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */
|
||||
#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */
|
||||
#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */
|
||||
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */
|
||||
|
||||
/* ########################### Ethernet Configuration ######################### */
|
||||
#define ETH_TX_DESC_CNT 4U /* number of Ethernet Tx DMA descriptors */
|
||||
#define ETH_RX_DESC_CNT 4U /* number of Ethernet Rx DMA descriptors */
|
||||
|
||||
#define ETH_MAC_ADDR0 (0x02UL)
|
||||
#define ETH_MAC_ADDR1 (0x00UL)
|
||||
#define ETH_MAC_ADDR2 (0x00UL)
|
||||
#define ETH_MAC_ADDR3 (0x00UL)
|
||||
#define ETH_MAC_ADDR4 (0x00UL)
|
||||
#define ETH_MAC_ADDR5 (0x00UL)
|
||||
|
||||
/* ########################## Assert Selection ############################## */
|
||||
/**
|
||||
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||
* HAL drivers code
|
||||
*/
|
||||
/* #define USE_FULL_ASSERT 1U */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Include module's header file
|
||||
*/
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_dma.h"
|
||||
#endif /* HAL_DMA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_MDMA_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_mdma.h"
|
||||
#endif /* HAL_MDMA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HASH_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_hash.h"
|
||||
#endif /* HAL_HASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DCMI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_dcmi.h"
|
||||
#endif /* HAL_DCMI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA2D_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_dma2d.h"
|
||||
#endif /* HAL_DMA2D_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DSI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_dsi.h"
|
||||
#endif /* HAL_DSI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DFSDM_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_dfsdm.h"
|
||||
#endif /* HAL_DFSDM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DTS_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_dts.h"
|
||||
#endif /* HAL_DTS_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ETH_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_eth.h"
|
||||
#endif /* HAL_ETH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ETH_LEGACY_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_eth_legacy.h"
|
||||
#endif /* HAL_ETH_LEGACY_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_cortex.h"
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_adc.h"
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FDCAN_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_fdcan.h"
|
||||
#endif /* HAL_FDCAN_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CEC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_cec.h"
|
||||
#endif /* HAL_CEC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_COMP_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_comp.h"
|
||||
#endif /* HAL_COMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORDIC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_cordic.h"
|
||||
#endif /* HAL_CORDIC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_crc.h"
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRYP_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_cryp.h"
|
||||
#endif /* HAL_CRYP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_dac.h"
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_flash.h"
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GFXMMU_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_gfxmmu.h"
|
||||
#endif /* HAL_GFXMMU_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FMAC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_fmac.h"
|
||||
#endif /* HAL_FMAC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HRTIM_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_hrtim.h"
|
||||
#endif /* HAL_HRTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HSEM_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_hsem.h"
|
||||
#endif /* HAL_HSEM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SRAM_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_sram.h"
|
||||
#endif /* HAL_SRAM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NOR_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_nor.h"
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NAND_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_nand.h"
|
||||
#endif /* HAL_NAND_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_i2c.h"
|
||||
#endif /* HAL_I2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2S_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_i2s.h"
|
||||
#endif /* HAL_I2S_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_iwdg.h"
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_JPEG_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_jpeg.h"
|
||||
#endif /* HAL_JPEG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_MDIOS_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_mdios.h"
|
||||
#endif /* HAL_MDIOS_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_MMC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_mmc.h"
|
||||
#endif /* HAL_MMC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LPTIM_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_lptim.h"
|
||||
#endif /* HAL_LPTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LTDC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_ltdc.h"
|
||||
#endif /* HAL_LTDC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_OPAMP_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_opamp.h"
|
||||
#endif /* HAL_OPAMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_OSPI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_ospi.h"
|
||||
#endif /* HAL_OSPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_OTFDEC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_otfdec.h"
|
||||
#endif /* HAL_OTFDEC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PSSI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_pssi.h"
|
||||
#endif /* HAL_PSSI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_pwr.h"
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_QSPI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_qspi.h"
|
||||
#endif /* HAL_QSPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RAMECC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_ramecc.h"
|
||||
#endif /* HAL_RAMECC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RNG_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_rng.h"
|
||||
#endif /* HAL_RNG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_rtc.h"
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SAI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_sai.h"
|
||||
#endif /* HAL_SAI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SD_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_sd.h"
|
||||
#endif /* HAL_SD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SDRAM_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_sdram.h"
|
||||
#endif /* HAL_SDRAM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_spi.h"
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPDIFRX_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_spdifrx.h"
|
||||
#endif /* HAL_SPDIFRX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SWPMI_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_swpmi.h"
|
||||
#endif /* HAL_SWPMI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_tim.h"
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_uart.h"
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_usart.h"
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IRDA_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_irda.h"
|
||||
#endif /* HAL_IRDA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMARTCARD_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_smartcard.h"
|
||||
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMBUS_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_smbus.h"
|
||||
#endif /* HAL_SMBUS_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_wwdg.h"
|
||||
#endif /* HAL_WWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_pcd.h"
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HCD_MODULE_ENABLED
|
||||
#include "stm32h7xx_hal_hcd.h"
|
||||
#endif /* HAL_HCD_MODULE_ENABLED */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief The assert_param macro is used for function's parameters check.
|
||||
* @param expr: If expr is false, it calls assert_failed function
|
||||
* which reports the name of the source file and the source
|
||||
* line number of the call that failed.
|
||||
* If expr is true, it returns no value.
|
||||
* @retval None
|
||||
*/
|
||||
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void assert_failed(uint8_t *file, uint32_t line);
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STM32H7xx_HAL_CONF_H */
|
||||
@@ -1,60 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32h7xx_it.h
|
||||
* @brief This file contains the headers of the interrupt handlers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32H7xx_IT_H
|
||||
#define __STM32H7xx_IT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void NMI_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void TIM6_DAC_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32H7xx_IT_H */
|
||||
@@ -1,59 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : freertos.c
|
||||
* Description : Code for freertos applications
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "main.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Variables */
|
||||
|
||||
/* USER CODE END Variables */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN FunctionPrototypes */
|
||||
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
/* Private application code --------------------------------------------------*/
|
||||
/* USER CODE BEGIN Application */
|
||||
|
||||
/* USER CODE END Application */
|
||||
|
||||
@@ -1,541 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.c
|
||||
* @brief : Main program body
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
#include "string.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "cmsis_os2.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "mongoose.h"
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma location=0x30000000
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
#pragma location=0x30000080
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
|
||||
#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
|
||||
|
||||
__attribute__((at(0x30000000))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
__attribute__((at(0x30000080))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
|
||||
#elif defined ( __GNUC__ ) /* GNU Compiler */
|
||||
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDescripSection"))); /* Ethernet Rx DMA Descriptors */
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDescripSection"))); /* Ethernet Tx DMA Descriptors */
|
||||
#endif
|
||||
|
||||
ETH_TxPacketConfig TxConfig;
|
||||
|
||||
ETH_HandleTypeDef heth;
|
||||
|
||||
RNG_HandleTypeDef hrng;
|
||||
|
||||
UART_HandleTypeDef huart3;
|
||||
|
||||
/* Definitions for defaultTask */
|
||||
osThreadId_t defaultTaskHandle;
|
||||
const osThreadAttr_t defaultTask_attributes = {
|
||||
.name = "defaultTask",
|
||||
.stack_size = MG_HEALTH_STACK_TOTAL,
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
};
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void SystemClock_Config(void);
|
||||
static void MPU_Config(void);
|
||||
static void MX_GPIO_Init(void);
|
||||
static void MX_ETH_Init(void);
|
||||
static void MX_RNG_Init(void);
|
||||
static void MX_USART3_UART_Init(void);
|
||||
void StartDefaultTask(void *argument);
|
||||
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
static void log_fn(char ch, void *param) {
|
||||
HAL_UART_Transmit(param, (unsigned char *) &ch, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
mg_http_reply(c, 200, "", "{%m:%lu}\n", MG_ESC("tick"), HAL_GetTick());
|
||||
} else if (mg_match(hm->uri, mg_str("/api/kill"), NULL)) {
|
||||
SCB->SHCSR &= ~SCB_SHCSR_USGFAULTENA_Msk;
|
||||
__asm volatile("udf #0");
|
||||
} else {
|
||||
mg_http_reply(c, 200, "Content-Type: text/plain\r\n",
|
||||
"Hi from Mongoose, tick %lu\n"
|
||||
"stack %zu/%zu bytes, heap %zu/%zu bytes\n",
|
||||
(unsigned long) HAL_GetTick(),
|
||||
(size_t) MG_HEALTH_STACK_USED, (size_t) MG_HEALTH_STACK_TOTAL,
|
||||
(size_t) MG_HEALTH_HEAP_USED, (size_t) MG_HEALTH_HEAP_TOTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/**
|
||||
* @brief The application entry point.
|
||||
* @retval int
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
MG_HEALTH_INIT();
|
||||
/* USER CODE END 1 */
|
||||
|
||||
/* MPU Configuration--------------------------------------------------------*/
|
||||
MPU_Config();
|
||||
|
||||
/* MCU Configuration--------------------------------------------------------*/
|
||||
|
||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
||||
HAL_Init();
|
||||
|
||||
/* USER CODE BEGIN Init */
|
||||
|
||||
/* USER CODE END Init */
|
||||
|
||||
/* Configure the system clock */
|
||||
SystemClock_Config();
|
||||
|
||||
/* USER CODE BEGIN SysInit */
|
||||
|
||||
/* USER CODE END SysInit */
|
||||
|
||||
/* Initialize all configured peripherals */
|
||||
MX_GPIO_Init();
|
||||
MX_ETH_Init();
|
||||
MX_RNG_Init();
|
||||
MX_USART3_UART_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Init scheduler */
|
||||
osKernelInitialize();
|
||||
|
||||
/* USER CODE BEGIN RTOS_MUTEX */
|
||||
/* add mutexes, ... */
|
||||
/* USER CODE END RTOS_MUTEX */
|
||||
|
||||
/* USER CODE BEGIN RTOS_SEMAPHORES */
|
||||
/* add semaphores, ... */
|
||||
/* USER CODE END RTOS_SEMAPHORES */
|
||||
|
||||
/* USER CODE BEGIN RTOS_TIMERS */
|
||||
/* start timers, add new ones, ... */
|
||||
/* USER CODE END RTOS_TIMERS */
|
||||
|
||||
/* USER CODE BEGIN RTOS_QUEUES */
|
||||
/* add queues, ... */
|
||||
/* USER CODE END RTOS_QUEUES */
|
||||
|
||||
/* Create the thread(s) */
|
||||
/* creation of defaultTask */
|
||||
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
|
||||
|
||||
/* USER CODE BEGIN RTOS_THREADS */
|
||||
/* add threads, ... */
|
||||
/* USER CODE END RTOS_THREADS */
|
||||
|
||||
/* USER CODE BEGIN RTOS_EVENTS */
|
||||
/* add events, ... */
|
||||
/* USER CODE END RTOS_EVENTS */
|
||||
|
||||
/* Start scheduler */
|
||||
osKernelStart();
|
||||
|
||||
/* We should never get here as control is now taken by the scheduler */
|
||||
|
||||
/* Infinite loop */
|
||||
/* USER CODE BEGIN WHILE */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE END WHILE */
|
||||
|
||||
/* USER CODE BEGIN 3 */
|
||||
}
|
||||
/* USER CODE END 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System Clock Configuration
|
||||
* @retval None
|
||||
*/
|
||||
void SystemClock_Config(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
|
||||
/** Supply configuration update enable
|
||||
*/
|
||||
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
|
||||
|
||||
/** Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
|
||||
|
||||
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
|
||||
|
||||
/** Initializes the RCC Oscillators according to the specified parameters
|
||||
* in the RCC_OscInitTypeDef structure.
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
|
||||
RCC_OscInitStruct.HSICalibrationValue = 64;
|
||||
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 34;
|
||||
RCC_OscInitStruct.PLL.PLLP = 1;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 2;
|
||||
RCC_OscInitStruct.PLL.PLLR = 2;
|
||||
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
|
||||
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
|
||||
RCC_OscInitStruct.PLL.PLLFRACN = 3072;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Initializes the CPU, AHB and APB buses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|
||||
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
|
||||
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
|
||||
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ETH Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_ETH_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN ETH_Init 0 */
|
||||
|
||||
/* USER CODE END ETH_Init 0 */
|
||||
|
||||
static uint8_t MACAddr[6];
|
||||
|
||||
/* USER CODE BEGIN ETH_Init 1 */
|
||||
|
||||
/* USER CODE END ETH_Init 1 */
|
||||
heth.Instance = ETH;
|
||||
MACAddr[0] = 0x00;
|
||||
MACAddr[1] = 0x80;
|
||||
MACAddr[2] = 0xE1;
|
||||
MACAddr[3] = 0x00;
|
||||
MACAddr[4] = 0x00;
|
||||
MACAddr[5] = 0x00;
|
||||
heth.Init.MACAddr = &MACAddr[0];
|
||||
heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
|
||||
heth.Init.TxDesc = DMATxDscrTab;
|
||||
heth.Init.RxDesc = DMARxDscrTab;
|
||||
heth.Init.RxBuffLen = 1536;
|
||||
|
||||
/* USER CODE BEGIN MACADDRESS */
|
||||
|
||||
/* USER CODE END MACADDRESS */
|
||||
|
||||
if (HAL_ETH_Init(&heth) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN ETH_Init 2 */
|
||||
|
||||
/* USER CODE END ETH_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RNG Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_RNG_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN RNG_Init 0 */
|
||||
|
||||
/* USER CODE END RNG_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN RNG_Init 1 */
|
||||
|
||||
/* USER CODE END RNG_Init 1 */
|
||||
hrng.Instance = RNG;
|
||||
hrng.Init.ClockErrorDetection = RNG_CED_ENABLE;
|
||||
if (HAL_RNG_Init(&hrng) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN RNG_Init 2 */
|
||||
|
||||
/* USER CODE END RNG_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART3 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_USART3_UART_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN USART3_Init 0 */
|
||||
|
||||
/* USER CODE END USART3_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN USART3_Init 1 */
|
||||
|
||||
/* USER CODE END USART3_Init 1 */
|
||||
huart3.Instance = USART3;
|
||||
huart3.Init.BaudRate = 115200;
|
||||
huart3.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
huart3.Init.StopBits = UART_STOPBITS_1;
|
||||
huart3.Init.Parity = UART_PARITY_NONE;
|
||||
huart3.Init.Mode = UART_MODE_TX_RX;
|
||||
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||
huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
|
||||
huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
|
||||
huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
|
||||
if (HAL_UART_Init(&huart3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN USART3_Init 2 */
|
||||
|
||||
/* USER CODE END USART3_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_GPIO_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
||||
|
||||
/* USER CODE END MX_GPIO_Init_1 */
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_14, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pins : PB0 PB14 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_14;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : PE1 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN MX_GPIO_Init_2 */
|
||||
|
||||
/* USER CODE END MX_GPIO_Init_2 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 4 */
|
||||
|
||||
/* USER CODE END 4 */
|
||||
|
||||
/* USER CODE BEGIN Header_StartDefaultTask */
|
||||
/**
|
||||
* @brief Function implementing the defaultTask thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_StartDefaultTask */
|
||||
void StartDefaultTask(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN 5 */
|
||||
struct mg_mgr mgr;
|
||||
(void) argument;
|
||||
mg_log_set_fn(log_fn, &huart3);
|
||||
mg_mgr_init(&mgr);
|
||||
mg_http_listen(&mgr, "http://0.0.0.0", http_ev_handler, NULL);
|
||||
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
osDelay(1);
|
||||
}
|
||||
/* USER CODE END 5 */
|
||||
}
|
||||
|
||||
/* MPU Configuration */
|
||||
|
||||
void MPU_Config(void)
|
||||
{
|
||||
MPU_Region_InitTypeDef MPU_InitStruct = {0};
|
||||
|
||||
/* Disables the MPU */
|
||||
HAL_MPU_Disable();
|
||||
|
||||
/** Initializes and configures the Region and the memory to be protected
|
||||
*/
|
||||
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||||
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
|
||||
MPU_InitStruct.BaseAddress = 0x0;
|
||||
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
|
||||
MPU_InitStruct.SubRegionDisable = 0x87;
|
||||
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||||
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
|
||||
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||||
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
|
||||
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
|
||||
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||||
|
||||
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||||
/* Enables the MPU */
|
||||
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Period elapsed callback in non blocking mode
|
||||
* @note This function is called when TIM6 interrupt took place, inside
|
||||
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
|
||||
* a global variable "uwTick" used as application time base.
|
||||
* @param htim : TIM handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* USER CODE BEGIN Callback 0 */
|
||||
|
||||
/* USER CODE END Callback 0 */
|
||||
if (htim->Instance == TIM6)
|
||||
{
|
||||
HAL_IncTick();
|
||||
}
|
||||
/* USER CODE BEGIN Callback 1 */
|
||||
|
||||
/* USER CODE END Callback 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is executed in case of error occurrence.
|
||||
* @retval None
|
||||
*/
|
||||
void Error_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN Error_Handler_Debug */
|
||||
/* User can add his own implementation to report the HAL error return state */
|
||||
__disable_irq();
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
/* USER CODE END Error_Handler_Debug */
|
||||
}
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief Reports the name of the source file and the source line number
|
||||
* where the assert_param error has occurred.
|
||||
* @param file: pointer to the source file name
|
||||
* @param line: assert_param error line source number
|
||||
* @retval None
|
||||
*/
|
||||
void assert_failed(uint8_t *file, uint32_t line)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
/* User can add his own implementation to report the file name and line number,
|
||||
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* USER CODE END 6 */
|
||||
}
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
@@ -1,329 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32h7xx_hal_msp.c
|
||||
* @brief This file provides code for the MSP Initialization
|
||||
* and de-Initialization codes.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
|
||||
/* USER CODE END TD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Define */
|
||||
|
||||
/* USER CODE END Define */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Macro */
|
||||
|
||||
/* USER CODE END Macro */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* External functions --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ExternalFunctions */
|
||||
|
||||
/* USER CODE END ExternalFunctions */
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
/**
|
||||
* Initializes the Global MSP.
|
||||
*/
|
||||
void HAL_MspInit(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN MspInit 0 */
|
||||
|
||||
/* USER CODE END MspInit 0 */
|
||||
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
|
||||
/* System interrupt init*/
|
||||
/* PendSV_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);
|
||||
|
||||
/* USER CODE BEGIN MspInit 1 */
|
||||
|
||||
/* USER CODE END MspInit 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ETH MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param heth: ETH handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(heth->Instance==ETH)
|
||||
{
|
||||
/* USER CODE BEGIN ETH_MspInit 0 */
|
||||
|
||||
/* USER CODE END ETH_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_ETH1MAC_CLK_ENABLE();
|
||||
__HAL_RCC_ETH1TX_CLK_ENABLE();
|
||||
__HAL_RCC_ETH1RX_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
/**ETH GPIO Configuration
|
||||
PC1 ------> ETH_MDC
|
||||
PA1 ------> ETH_REF_CLK
|
||||
PA2 ------> ETH_MDIO
|
||||
PA7 ------> ETH_CRS_DV
|
||||
PC4 ------> ETH_RXD0
|
||||
PC5 ------> ETH_RXD1
|
||||
PB13 ------> ETH_TXD1
|
||||
PG11 ------> ETH_TX_EN
|
||||
PG13 ------> ETH_TXD0
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_13;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN ETH_MspInit 1 */
|
||||
|
||||
/* USER CODE END ETH_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ETH MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param heth: ETH handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
|
||||
{
|
||||
if(heth->Instance==ETH)
|
||||
{
|
||||
/* USER CODE BEGIN ETH_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END ETH_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_ETH1MAC_CLK_DISABLE();
|
||||
__HAL_RCC_ETH1TX_CLK_DISABLE();
|
||||
__HAL_RCC_ETH1RX_CLK_DISABLE();
|
||||
|
||||
/**ETH GPIO Configuration
|
||||
PC1 ------> ETH_MDC
|
||||
PA1 ------> ETH_REF_CLK
|
||||
PA2 ------> ETH_MDIO
|
||||
PA7 ------> ETH_CRS_DV
|
||||
PC4 ------> ETH_RXD0
|
||||
PC5 ------> ETH_RXD1
|
||||
PB13 ------> ETH_TXD1
|
||||
PG11 ------> ETH_TX_EN
|
||||
PG13 ------> ETH_TXD0
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOG, GPIO_PIN_11|GPIO_PIN_13);
|
||||
|
||||
/* USER CODE BEGIN ETH_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END ETH_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RNG MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hrng: RNG handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RNG_MspInit(RNG_HandleTypeDef* hrng)
|
||||
{
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
if(hrng->Instance==RNG)
|
||||
{
|
||||
/* USER CODE BEGIN RNG_MspInit 0 */
|
||||
|
||||
/* USER CODE END RNG_MspInit 0 */
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RNG;
|
||||
PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_HSI48;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_RNG_CLK_ENABLE();
|
||||
/* USER CODE BEGIN RNG_MspInit 1 */
|
||||
|
||||
/* USER CODE END RNG_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RNG MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hrng: RNG handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RNG_MspDeInit(RNG_HandleTypeDef* hrng)
|
||||
{
|
||||
if(hrng->Instance==RNG)
|
||||
{
|
||||
/* USER CODE BEGIN RNG_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END RNG_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_RNG_CLK_DISABLE();
|
||||
/* USER CODE BEGIN RNG_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END RNG_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param huart: UART handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
if(huart->Instance==USART3)
|
||||
{
|
||||
/* USER CODE BEGIN USART3_MspInit 0 */
|
||||
|
||||
/* USER CODE END USART3_MspInit 0 */
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;
|
||||
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_USART3_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
/**USART3 GPIO Configuration
|
||||
PD8 ------> USART3_TX
|
||||
PD9 ------> USART3_RX
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN USART3_MspInit 1 */
|
||||
|
||||
/* USER CODE END USART3_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param huart: UART handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
|
||||
{
|
||||
if(huart->Instance==USART3)
|
||||
{
|
||||
/* USER CODE BEGIN USART3_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END USART3_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_USART3_CLK_DISABLE();
|
||||
|
||||
/**USART3 GPIO Configuration
|
||||
PD8 ------> USART3_TX
|
||||
PD9 ------> USART3_RX
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9);
|
||||
|
||||
/* USER CODE BEGIN USART3_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END USART3_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
@@ -1,131 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32h7xx_hal_timebase_tim.c
|
||||
* @brief HAL time base based on the hardware TIM.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32h7xx_hal.h"
|
||||
#include "stm32h7xx_hal_tim.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
TIM_HandleTypeDef htim6;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the TIM6 as a time base source.
|
||||
* The time source is configured to have 1ms time base with a dedicated
|
||||
* Tick interrupt priority.
|
||||
* @note This function is called automatically at the beginning of program after
|
||||
* reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
|
||||
* @param TickPriority: Tick interrupt priority.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
{
|
||||
RCC_ClkInitTypeDef clkconfig;
|
||||
uint32_t uwTimclock, uwAPB1Prescaler;
|
||||
uint32_t uwPrescalerValue;
|
||||
uint32_t pFLatency;
|
||||
|
||||
/*Configure the TIM6 IRQ priority */
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0);
|
||||
|
||||
/* Enable the TIM6 global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
|
||||
uwTickPrio = TickPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable TIM6 clock */
|
||||
__HAL_RCC_TIM6_CLK_ENABLE();
|
||||
|
||||
/* Get clock configuration */
|
||||
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
|
||||
|
||||
/* Get APB1 prescaler */
|
||||
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
|
||||
/* Compute TIM6 clock */
|
||||
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
|
||||
{
|
||||
uwTimclock = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
else
|
||||
{
|
||||
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
|
||||
/* Compute the prescaler value to have TIM6 counter clock equal to 1MHz */
|
||||
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
|
||||
|
||||
/* Initialize TIM6 */
|
||||
htim6.Instance = TIM6;
|
||||
|
||||
/* Initialize TIMx peripheral as follow:
|
||||
* Period = [(TIM6CLK/1000) - 1]. to have a (1/1000) s time base.
|
||||
* Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
|
||||
* ClockDivision = 0
|
||||
* Counter direction = Up
|
||||
*/
|
||||
htim6.Init.Period = (1000000U / 1000U) - 1U;
|
||||
htim6.Init.Prescaler = uwPrescalerValue;
|
||||
htim6.Init.ClockDivision = 0;
|
||||
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
|
||||
if(HAL_TIM_Base_Init(&htim6) == HAL_OK)
|
||||
{
|
||||
|
||||
/* Start the TIM time Base generation in interrupt mode */
|
||||
return HAL_TIM_Base_Start_IT(&htim6);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend Tick increment.
|
||||
* @note Disable the tick increment by disabling TIM6 update interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable TIM6 update Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(&htim6, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume Tick increment.
|
||||
* @note Enable the tick increment by Enabling TIM6 update interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ResumeTick(void)
|
||||
{
|
||||
/* Enable TIM6 Update interrupt */
|
||||
__HAL_TIM_ENABLE_IT(&htim6, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32h7xx_it.c
|
||||
* @brief Interrupt Service Routines.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
#include "stm32h7xx_it.h"
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
|
||||
/* USER CODE END TD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern TIM_HandleTypeDef htim6;
|
||||
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex Processor Interruption and Exception Handlers */
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @brief This function handles Non maskable interrupt.
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
|
||||
|
||||
/* USER CODE END NonMaskableInt_IRQn 0 */
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
/* USER CODE END NonMaskableInt_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Debug monitor.
|
||||
*/
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 0 */
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 1 */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* STM32H7xx Peripheral Interrupt Handlers */
|
||||
/* Add here the Interrupt Handlers for the used peripherals. */
|
||||
/* For the available peripheral interrupt handler names, */
|
||||
/* please refer to the startup file (startup_stm32h7xx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM6 global interrupt, DAC1_CH1 and DAC1_CH2 underrun error interrupts.
|
||||
*/
|
||||
void TIM6_DAC_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */
|
||||
|
||||
/* USER CODE END TIM6_DAC_IRQn 0 */
|
||||
HAL_TIM_IRQHandler(&htim6);
|
||||
/* USER CODE BEGIN TIM6_DAC_IRQn 1 */
|
||||
|
||||
/* USER CODE END TIM6_DAC_IRQn 1 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
@@ -1,244 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file syscalls.c
|
||||
* @author Auto-generated by STM32CubeMX
|
||||
* @brief Minimal System calls file
|
||||
*
|
||||
* For more information about which c-functions
|
||||
* need which of these lowlevel functions
|
||||
* please consult the Newlib or Picolibc libc-manual
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2020-2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
|
||||
/* Variables */
|
||||
extern int __io_putchar(int ch) __attribute__((weak));
|
||||
extern int __io_getchar(void) __attribute__((weak));
|
||||
|
||||
|
||||
char *__env[1] = { 0 };
|
||||
char **environ = __env;
|
||||
|
||||
|
||||
/* Functions */
|
||||
void initialise_monitor_handles()
|
||||
{
|
||||
}
|
||||
|
||||
int _getpid(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig)
|
||||
{
|
||||
(void)pid;
|
||||
(void)sig;
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _exit (int status)
|
||||
{
|
||||
_kill(status, -1);
|
||||
while (1) {} /* Make sure we hang here */
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _read(int file, char *ptr, int len)
|
||||
{
|
||||
(void)file;
|
||||
int DataIdx;
|
||||
|
||||
for (DataIdx = 0; DataIdx < len; DataIdx++)
|
||||
{
|
||||
*ptr++ = __io_getchar();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int file, char *ptr, int len)
|
||||
{
|
||||
(void)file;
|
||||
int DataIdx;
|
||||
|
||||
for (DataIdx = 0; DataIdx < len; DataIdx++)
|
||||
{
|
||||
__io_putchar(*ptr++);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int _close(int file)
|
||||
{
|
||||
(void)file;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int _fstat(int file, struct stat *st)
|
||||
{
|
||||
(void)file;
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty(int file)
|
||||
{
|
||||
(void)file;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
(void)dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _open(char *path, int flags, ...)
|
||||
{
|
||||
(void)path;
|
||||
(void)flags;
|
||||
/* Pretend like we always fail */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _wait(int *status)
|
||||
{
|
||||
(void)status;
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _unlink(char *name)
|
||||
{
|
||||
(void)name;
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
clock_t _times(struct tms *buf)
|
||||
{
|
||||
(void)buf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat(const char *file, struct stat *st)
|
||||
{
|
||||
(void)file;
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _link(char *old, char *new)
|
||||
{
|
||||
(void)old;
|
||||
(void)new;
|
||||
errno = EMLINK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fork(void)
|
||||
{
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _execve(char *name, char **argv, char **env)
|
||||
{
|
||||
(void)name;
|
||||
(void)argv;
|
||||
(void)env;
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// --- Picolibc Specific Section ---
|
||||
#if defined(__PICOLIBC__)
|
||||
|
||||
/**
|
||||
* @brief Picolibc helper function to output a character to a FILE stream.
|
||||
* This redirects the output to the low-level __io_putchar function.
|
||||
* @param c Character to write.
|
||||
* @param file FILE stream pointer (ignored).
|
||||
* @retval int The character written.
|
||||
*/
|
||||
static int starm_putc(char c, FILE *file)
|
||||
{
|
||||
(void) file;
|
||||
__io_putchar(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Picolibc helper function to input a character from a FILE stream.
|
||||
* This redirects the input from the low-level __io_getchar function.
|
||||
* @param file FILE stream pointer (ignored).
|
||||
* @retval int The character read, cast to an unsigned char then int.
|
||||
*/
|
||||
static int starm_getc(FILE *file)
|
||||
{
|
||||
unsigned char c;
|
||||
(void) file;
|
||||
c = __io_getchar();
|
||||
return c;
|
||||
}
|
||||
|
||||
// Define and initialize the standard I/O streams for Picolibc.
|
||||
// FDEV_SETUP_STREAM connects the starm_putc and starm_getc helper functions to a FILE structure.
|
||||
// _FDEV_SETUP_RW indicates the stream is for reading and writing.
|
||||
static FILE __stdio = FDEV_SETUP_STREAM(starm_putc,
|
||||
starm_getc,
|
||||
NULL,
|
||||
_FDEV_SETUP_RW);
|
||||
|
||||
// Assign the standard stream pointers (stdin, stdout, stderr) to the initialized stream.
|
||||
// Picolibc uses these pointers for standard I/O operations (printf, scanf, etc.).
|
||||
FILE *const stdin = &__stdio;
|
||||
__strong_reference(stdin, stdout);
|
||||
__strong_reference(stdin, stderr);
|
||||
|
||||
// Create strong aliases mapping standard C library function names (without underscore)
|
||||
// to the implemented system call stubs (with underscore). Picolibc uses these
|
||||
// standard names internally, so this linking is required.
|
||||
__strong_reference(_read, read);
|
||||
__strong_reference(_write, write);
|
||||
__strong_reference(_times, times);
|
||||
__strong_reference(_execve, execve);
|
||||
__strong_reference(_fork, fork);
|
||||
__strong_reference(_link, link);
|
||||
__strong_reference(_unlink, unlink);
|
||||
__strong_reference(_stat, stat);
|
||||
__strong_reference(_wait, wait);
|
||||
__strong_reference(_open, open);
|
||||
__strong_reference(_close, close);
|
||||
__strong_reference(_lseek, lseek);
|
||||
__strong_reference(_isatty, isatty);
|
||||
__strong_reference(_fstat, fstat);
|
||||
__strong_reference(_exit, exit);
|
||||
__strong_reference(_kill, kill);
|
||||
__strong_reference(_getpid, getpid);
|
||||
|
||||
#endif //__PICOLIBC__
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file sysmem.c
|
||||
* @author Generated by STM32CubeMX
|
||||
* @brief System Memory calls file
|
||||
*
|
||||
* For more information about which C functions
|
||||
* need which of these lowlevel functions
|
||||
* please consult the Newlib or Picolibc libc manual
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Pointer to the current high watermark of the heap usage
|
||||
*/
|
||||
static uint8_t *__sbrk_heap_end = NULL;
|
||||
|
||||
/**
|
||||
* @brief _sbrk() allocates memory to the newlib heap and is used by malloc
|
||||
* and others from the C library
|
||||
*
|
||||
* @verbatim
|
||||
* ############################################################################
|
||||
* # .data # .bss # newlib heap # MSP stack #
|
||||
* # # # # Reserved by _Min_Stack_Size #
|
||||
* ############################################################################
|
||||
* ^-- RAM start ^-- _end _estack, RAM end --^
|
||||
* @endverbatim
|
||||
*
|
||||
* This implementation starts allocating at the '_end' linker symbol
|
||||
* The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
|
||||
* The implementation considers '_estack' linker symbol to be RAM end
|
||||
* NOTE: If the MSP stack, at any point during execution, grows larger than the
|
||||
* reserved size, please increase the '_Min_Stack_Size'.
|
||||
*
|
||||
* @param incr Memory size
|
||||
* @return Pointer to allocated memory
|
||||
*/
|
||||
void *_sbrk(ptrdiff_t incr)
|
||||
{
|
||||
extern uint8_t _end; /* Symbol defined in the linker script */
|
||||
extern uint8_t _estack; /* Symbol defined in the linker script */
|
||||
extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
|
||||
const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
|
||||
const uint8_t *max_heap = (uint8_t *)stack_limit;
|
||||
uint8_t *prev_heap_end;
|
||||
|
||||
/* Initialize heap end at first call */
|
||||
if (NULL == __sbrk_heap_end)
|
||||
{
|
||||
__sbrk_heap_end = &_end;
|
||||
}
|
||||
|
||||
/* Protect heap from growing into the reserved MSP stack */
|
||||
if (__sbrk_heap_end + incr > max_heap)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return (void *)-1;
|
||||
}
|
||||
|
||||
prev_heap_end = __sbrk_heap_end;
|
||||
__sbrk_heap_end += incr;
|
||||
|
||||
return (void *)prev_heap_end;
|
||||
}
|
||||
|
||||
#if defined(__PICOLIBC__)
|
||||
// Picolibc expects syscalls without the leading underscore.
|
||||
// This creates a strong alias so that
|
||||
// calls to `sbrk()` are resolved to our `_sbrk()` implementation.
|
||||
__strong_reference(_sbrk, sbrk);
|
||||
#endif
|
||||
@@ -1,554 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32h7xx.c
|
||||
* @author MCD Application Team
|
||||
* @brief CMSIS Cortex-Mx Device Peripheral Access Layer System Source File.
|
||||
*
|
||||
* This file provides two functions and one global variable to be called from
|
||||
* user application:
|
||||
* - ExitRun0Mode(): Specifies the Power Supply source. This function is
|
||||
* called at startup just after reset and before the call
|
||||
* of SystemInit(). This call is made inside
|
||||
* the "startup_stm32h7xx.s" file.
|
||||
*
|
||||
* - SystemInit(): This function is called at startup just after reset and
|
||||
* before branch to main program. This call is made inside
|
||||
* the "startup_stm32h7xx.s" file.
|
||||
*
|
||||
* - SystemCoreClock variable: Contains the core clock, it can be used
|
||||
* by the user application to setup the SysTick
|
||||
* timer or configure other parameters.
|
||||
*
|
||||
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
|
||||
* be called whenever the core clock is changed
|
||||
* during program execution.
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32h7xx_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32H7xx_System_Private_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "stm32h7xx.h"
|
||||
#include <math.h>
|
||||
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (CSI_VALUE)
|
||||
#define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* CSI_VALUE */
|
||||
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32H7xx_System_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32H7xx_System_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/************************* Miscellaneous Configuration ************************/
|
||||
/*!< Uncomment the following line if you need to use initialized data in D2 domain SRAM (AHB SRAM) */
|
||||
/* #define DATA_IN_D2_SRAM */
|
||||
|
||||
/* Note: Following vector table addresses must be defined in line with linker
|
||||
configuration. */
|
||||
/*!< Uncomment the following line if you need to relocate the vector table
|
||||
anywhere in FLASH BANK1 or AXI SRAM, else the vector table is kept at the automatic
|
||||
remap of boot address selected */
|
||||
/* #define USER_VECT_TAB_ADDRESS */
|
||||
|
||||
#if defined(USER_VECT_TAB_ADDRESS)
|
||||
#if defined(DUAL_CORE) && defined(CORE_CM4)
|
||||
/*!< Uncomment the following line if you need to relocate your vector Table
|
||||
in D2 AXI SRAM else user remap will be done in FLASH BANK2. */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#if defined(VECT_TAB_SRAM)
|
||||
#define VECT_TAB_BASE_ADDRESS D2_AXISRAM_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x400. */
|
||||
#else
|
||||
#define VECT_TAB_BASE_ADDRESS FLASH_BANK2_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x400. */
|
||||
#endif /* VECT_TAB_SRAM */
|
||||
#else
|
||||
/*!< Uncomment the following line if you need to relocate your vector Table
|
||||
in D1 AXI SRAM else user remap will be done in FLASH BANK1. */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#if defined(VECT_TAB_SRAM)
|
||||
#define VECT_TAB_BASE_ADDRESS D1_AXISRAM_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x400. */
|
||||
#else
|
||||
#define VECT_TAB_BASE_ADDRESS FLASH_BANK1_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x400. */
|
||||
#endif /* VECT_TAB_SRAM */
|
||||
#endif /* DUAL_CORE && CORE_CM4 */
|
||||
|
||||
#if !defined(VECT_TAB_OFFSET)
|
||||
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
|
||||
This value must be a multiple of 0x400. */
|
||||
#endif /* VECT_TAB_OFFSET */
|
||||
|
||||
#endif /* USER_VECT_TAB_ADDRESS */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32H7xx_System_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32H7xx_System_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
/* This variable is updated in three ways:
|
||||
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
|
||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
||||
Note: If you use this function to configure the system clock; then there
|
||||
is no need to call the 2 first functions listed above, since SystemCoreClock
|
||||
variable is updated automatically.
|
||||
*/
|
||||
uint32_t SystemCoreClock = 64000000;
|
||||
uint32_t SystemD2Clock = 64000000;
|
||||
const uint8_t D1CorePrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32H7xx_System_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32H7xx_System_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system
|
||||
* Initialize the FPU setting and vector table location
|
||||
* configuration.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
#if defined (DATA_IN_D2_SRAM)
|
||||
__IO uint32_t tmpreg;
|
||||
#endif /* DATA_IN_D2_SRAM */
|
||||
|
||||
/* FPU settings ------------------------------------------------------------*/
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2))); /* set CP10 and CP11 Full Access */
|
||||
#endif
|
||||
/* Reset the RCC clock configuration to the default reset state ------------*/
|
||||
|
||||
/* Increasing the CPU frequency */
|
||||
if(FLASH_LATENCY_DEFAULT > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
|
||||
{
|
||||
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
|
||||
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
|
||||
}
|
||||
|
||||
/* Set HSION bit */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
|
||||
/* Reset CFGR register */
|
||||
RCC->CFGR = 0x00000000;
|
||||
|
||||
/* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
|
||||
RCC->CR &= 0xEAF6ED7FU;
|
||||
|
||||
/* Decreasing the number of wait states because of lower CPU frequency */
|
||||
if(FLASH_LATENCY_DEFAULT < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
|
||||
{
|
||||
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
|
||||
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
|
||||
}
|
||||
|
||||
#if defined(D3_SRAM_BASE)
|
||||
/* Reset D1CFGR register */
|
||||
RCC->D1CFGR = 0x00000000;
|
||||
|
||||
/* Reset D2CFGR register */
|
||||
RCC->D2CFGR = 0x00000000;
|
||||
|
||||
/* Reset D3CFGR register */
|
||||
RCC->D3CFGR = 0x00000000;
|
||||
#else
|
||||
/* Reset CDCFGR1 register */
|
||||
RCC->CDCFGR1 = 0x00000000;
|
||||
|
||||
/* Reset CDCFGR2 register */
|
||||
RCC->CDCFGR2 = 0x00000000;
|
||||
|
||||
/* Reset SRDCFGR register */
|
||||
RCC->SRDCFGR = 0x00000000;
|
||||
#endif
|
||||
/* Reset PLLCKSELR register */
|
||||
RCC->PLLCKSELR = 0x02020200;
|
||||
|
||||
/* Reset PLLCFGR register */
|
||||
RCC->PLLCFGR = 0x01FF0000;
|
||||
/* Reset PLL1DIVR register */
|
||||
RCC->PLL1DIVR = 0x01010280;
|
||||
/* Reset PLL1FRACR register */
|
||||
RCC->PLL1FRACR = 0x00000000;
|
||||
|
||||
/* Reset PLL2DIVR register */
|
||||
RCC->PLL2DIVR = 0x01010280;
|
||||
|
||||
/* Reset PLL2FRACR register */
|
||||
|
||||
RCC->PLL2FRACR = 0x00000000;
|
||||
/* Reset PLL3DIVR register */
|
||||
RCC->PLL3DIVR = 0x01010280;
|
||||
|
||||
/* Reset PLL3FRACR register */
|
||||
RCC->PLL3FRACR = 0x00000000;
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
RCC->CR &= 0xFFFBFFFFU;
|
||||
|
||||
/* Disable all interrupts */
|
||||
RCC->CIER = 0x00000000;
|
||||
|
||||
#if (STM32H7_DEV_ID == 0x450UL)
|
||||
/* dual core CM7 or single core line */
|
||||
if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
|
||||
{
|
||||
/* if stm32h7 revY*/
|
||||
/* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
|
||||
*((__IO uint32_t*)0x51008108) = 0x000000001U;
|
||||
}
|
||||
#endif /* STM32H7_DEV_ID */
|
||||
|
||||
#if defined(DATA_IN_D2_SRAM)
|
||||
/* in case of initialized data in D2 SRAM (AHB SRAM), enable the D2 SRAM clock (AHB SRAM clock) */
|
||||
#if defined(RCC_AHB2ENR_D2SRAM3EN)
|
||||
RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
|
||||
#elif defined(RCC_AHB2ENR_D2SRAM2EN)
|
||||
RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN);
|
||||
#else
|
||||
RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
|
||||
#endif /* RCC_AHB2ENR_D2SRAM3EN */
|
||||
|
||||
tmpreg = RCC->AHB2ENR;
|
||||
(void) tmpreg;
|
||||
#endif /* DATA_IN_D2_SRAM */
|
||||
|
||||
#if defined(DUAL_CORE) && defined(CORE_CM4)
|
||||
/* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
|
||||
#if defined(USER_VECT_TAB_ADDRESS)
|
||||
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D2 AXI-RAM or in Internal FLASH */
|
||||
#endif /* USER_VECT_TAB_ADDRESS */
|
||||
|
||||
#else
|
||||
if(READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) == 0U)
|
||||
{
|
||||
/* Enable the FMC interface clock */
|
||||
SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
|
||||
|
||||
/*
|
||||
* Disable the FMC bank1 (enabled after reset).
|
||||
* This, prevents CPU speculation access on this bank which blocks the use of FMC during
|
||||
* 24us. During this time the others FMC master (such as LTDC) cannot use it!
|
||||
*/
|
||||
FMC_Bank1_R->BTCR[0] = 0x000030D2;
|
||||
|
||||
/* Disable the FMC interface clock */
|
||||
CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
|
||||
}
|
||||
|
||||
/* Configure the Vector Table location -------------------------------------*/
|
||||
#if defined(USER_VECT_TAB_ADDRESS)
|
||||
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */
|
||||
#endif /* USER_VECT_TAB_ADDRESS */
|
||||
|
||||
#endif /*DUAL_CORE && CORE_CM4*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update SystemCoreClock variable according to Clock Register Values.
|
||||
* The SystemCoreClock variable contains the core clock , it can
|
||||
* be used by the user application to setup the SysTick timer or configure
|
||||
* other parameters.
|
||||
*
|
||||
* @note Each time the core clock changes, this function must be called
|
||||
* to update SystemCoreClock variable value. Otherwise, any configuration
|
||||
* based on this variable will be incorrect.
|
||||
*
|
||||
* @note - The system frequency computed by this function is not the real
|
||||
* frequency in the chip. It is calculated based on the predefined
|
||||
* constant and the selected clock source:
|
||||
*
|
||||
* - If SYSCLK source is CSI, SystemCoreClock will contain the CSI_VALUE(*)
|
||||
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
|
||||
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
|
||||
* - If SYSCLK source is PLL, SystemCoreClock will contain the CSI_VALUE(*),
|
||||
* HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
|
||||
*
|
||||
* (*) CSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
|
||||
* 4 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
* (**) HSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
|
||||
* 64 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
*
|
||||
* (***)HSE_VALUE is a constant defined in stm32h7xx_hal.h file (default value
|
||||
* 25 MHz), user has to ensure that HSE_VALUE is same as the real
|
||||
* frequency of the crystal used. Otherwise, this function may
|
||||
* have wrong result.
|
||||
*
|
||||
* - The result of this function could be not correct when using fractional
|
||||
* value for HSE crystal.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
uint32_t pllp, pllsource, pllm, pllfracen, hsivalue, tmp;
|
||||
uint32_t common_system_clock;
|
||||
float_t fracn1, pllvco;
|
||||
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
|
||||
switch (RCC->CFGR & RCC_CFGR_SWS)
|
||||
{
|
||||
case RCC_CFGR_SWS_HSI: /* HSI used as system clock source */
|
||||
common_system_clock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3));
|
||||
break;
|
||||
|
||||
case RCC_CFGR_SWS_CSI: /* CSI used as system clock source */
|
||||
common_system_clock = CSI_VALUE;
|
||||
break;
|
||||
|
||||
case RCC_CFGR_SWS_HSE: /* HSE used as system clock source */
|
||||
common_system_clock = HSE_VALUE;
|
||||
break;
|
||||
|
||||
case RCC_CFGR_SWS_PLL1: /* PLL1 used as system clock source */
|
||||
|
||||
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
|
||||
SYSCLK = PLL_VCO / PLLR
|
||||
*/
|
||||
pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
|
||||
pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1)>> 4) ;
|
||||
pllfracen = ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN)>>RCC_PLLCFGR_PLL1FRACEN_Pos);
|
||||
fracn1 = (float_t)(uint32_t)(pllfracen* ((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1)>> 3));
|
||||
|
||||
if (pllm != 0U)
|
||||
{
|
||||
switch (pllsource)
|
||||
{
|
||||
case RCC_PLLCKSELR_PLLSRC_HSI: /* HSI used as PLL clock source */
|
||||
|
||||
hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ;
|
||||
pllvco = ( (float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
|
||||
|
||||
break;
|
||||
|
||||
case RCC_PLLCKSELR_PLLSRC_CSI: /* CSI used as PLL clock source */
|
||||
pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
|
||||
break;
|
||||
|
||||
case RCC_PLLCKSELR_PLLSRC_HSE: /* HSE used as PLL clock source */
|
||||
pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
|
||||
break;
|
||||
|
||||
default:
|
||||
hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ;
|
||||
pllvco = ((float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
|
||||
break;
|
||||
}
|
||||
pllp = (((RCC->PLL1DIVR & RCC_PLL1DIVR_P1) >>9) + 1U ) ;
|
||||
common_system_clock = (uint32_t)(float_t)(pllvco/(float_t)pllp);
|
||||
}
|
||||
else
|
||||
{
|
||||
common_system_clock = 0U;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
common_system_clock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Compute SystemClock frequency --------------------------------------------------*/
|
||||
#if defined (RCC_D1CFGR_D1CPRE)
|
||||
tmp = D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE)>> RCC_D1CFGR_D1CPRE_Pos];
|
||||
|
||||
/* common_system_clock frequency : CM7 CPU frequency */
|
||||
common_system_clock >>= tmp;
|
||||
|
||||
/* SystemD2Clock frequency : CM4 CPU, AXI and AHBs Clock frequency */
|
||||
SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
|
||||
|
||||
#else
|
||||
tmp = D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE)>> RCC_CDCFGR1_CDCPRE_Pos];
|
||||
|
||||
/* common_system_clock frequency : CM7 CPU frequency */
|
||||
common_system_clock >>= tmp;
|
||||
|
||||
/* SystemD2Clock frequency : AXI and AHBs Clock frequency */
|
||||
SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE)>> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(DUAL_CORE) && defined(CORE_CM4)
|
||||
SystemCoreClock = SystemD2Clock;
|
||||
#else
|
||||
SystemCoreClock = common_system_clock;
|
||||
#endif /* DUAL_CORE && CORE_CM4 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit Run* mode and Configure the system Power Supply
|
||||
*
|
||||
* @note This function exits the Run* mode and configures the system power supply
|
||||
* according to the definition to be used at compilation preprocessing level.
|
||||
* The application shall set one of the following configuration option:
|
||||
* - PWR_LDO_SUPPLY
|
||||
* - PWR_DIRECT_SMPS_SUPPLY
|
||||
* - PWR_EXTERNAL_SOURCE_SUPPLY
|
||||
* - PWR_SMPS_1V8_SUPPLIES_LDO
|
||||
* - PWR_SMPS_2V5_SUPPLIES_LDO
|
||||
* - PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO
|
||||
* - PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO
|
||||
* - PWR_SMPS_1V8_SUPPLIES_EXT
|
||||
* - PWR_SMPS_2V5_SUPPLIES_EXT
|
||||
*
|
||||
* @note The function modifies the PWR->CR3 register to enable or disable specific
|
||||
* power supply modes and waits until the voltage level flag is set, indicating
|
||||
* that the power supply configuration is stable.
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void ExitRun0Mode(void)
|
||||
{
|
||||
#if defined(USE_PWR_LDO_SUPPLY)
|
||||
#if defined(SMPS)
|
||||
/* Exit Run* mode by disabling SMPS and enabling LDO */
|
||||
PWR->CR3 = (PWR->CR3 & ~PWR_CR3_SMPSEN) | PWR_CR3_LDOEN;
|
||||
#else
|
||||
/* Enable LDO mode */
|
||||
PWR->CR3 |= PWR_CR3_LDOEN;
|
||||
#endif /* SMPS */
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_EXTERNAL_SOURCE_SUPPLY)
|
||||
#if defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_SMPSEN | PWR_CR3_LDOEN)) | PWR_CR3_BYPASS;
|
||||
#else
|
||||
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_LDOEN)) | PWR_CR3_BYPASS;
|
||||
#endif /* SMPS */
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_DIRECT_SMPS_SUPPLY) && defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 &= ~(PWR_CR3_LDOEN);
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_SMPS_1V8_SUPPLIES_LDO) && defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 |= PWR_CR3_SMPSLEVEL_0 | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_SMPS_2V5_SUPPLIES_LDO) && defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 |= PWR_CR3_SMPSLEVEL_1 | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO) && defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 |= PWR_CR3_SMPSLEVEL_0 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO) && defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 |= PWR_CR3_SMPSLEVEL_1 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_SMPS_1V8_SUPPLIES_EXT) && defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_LDOEN)) | PWR_CR3_SMPSLEVEL_0 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_BYPASS;
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#elif defined(USE_PWR_SMPS_2V5_SUPPLIES_EXT) && defined(SMPS)
|
||||
/* Exit Run* mode */
|
||||
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_LDOEN)) | PWR_CR3_SMPSLEVEL_1 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_BYPASS;
|
||||
/* Wait till voltage level flag is set */
|
||||
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
|
||||
{}
|
||||
#else
|
||||
/* No system power supply configuration is selected at exit Run* mode */
|
||||
#endif /* USE_PWR_LDO_SUPPLY */
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
-24445
File diff suppressed because it is too large.
Load diff
-302
@@ -1,302 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32h7xx.h
|
||||
* @author MCD Application Team
|
||||
* @brief CMSIS STM32H7xx Device Peripheral Access Layer Header File.
|
||||
*
|
||||
* The file is the unique include file that the application programmer
|
||||
* is using in the C source code, usually in main.c. This file contains:
|
||||
* - Configuration section that allows to select:
|
||||
* - The STM32H7xx device used in the target application
|
||||
* - To use or not the peripheral's drivers in application code(i.e.
|
||||
* code will be based on direct access to peripheral's registers
|
||||
* rather than drivers API), this option is controlled by
|
||||
* "#define USE_HAL_DRIVER"
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32h7xx
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef STM32H7xx_H
|
||||
#define STM32H7xx_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** @addtogroup Library_configuration_section
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief STM32 Family
|
||||
*/
|
||||
#if !defined (STM32H7)
|
||||
#define STM32H7
|
||||
#endif /* STM32H7 */
|
||||
|
||||
|
||||
/* Uncomment the line below according to the target STM32H7 device used in your
|
||||
application
|
||||
*/
|
||||
|
||||
#if !defined (STM32H743xx) && !defined (STM32H753xx) && !defined (STM32H750xx) && !defined (STM32H742xx) && \
|
||||
!defined (STM32H745xx) && !defined (STM32H745xG) && !defined (STM32H755xx) && !defined (STM32H747xx) && !defined (STM32H747xG)&& !defined (STM32H757xx) && \
|
||||
!defined (STM32H7A3xx) && !defined (STM32H7A3xxQ) && !defined (STM32H7B3xx) && !defined (STM32H7B3xxQ) && !defined (STM32H7B0xx) && !defined (STM32H7B0xxQ) && \
|
||||
!defined (STM32H735xx) && !defined (STM32H733xx) && !defined (STM32H730xx) && !defined (STM32H730xxQ) && !defined (STM32H725xx) && !defined (STM32H723xx)
|
||||
/* #define STM32H742xx */ /*!< STM32H742VI, STM32H742ZI, STM32H742AI, STM32H742II, STM32H742BI, STM32H742XI Devices */
|
||||
/* #define STM32H743xx */ /*!< STM32H743VI, STM32H743ZI, STM32H743AI, STM32H743II, STM32H743BI, STM32H743XI Devices */
|
||||
/* #define STM32H753xx */ /*!< STM32H753VI, STM32H753ZI, STM32H753AI, STM32H753II, STM32H753BI, STM32H753XI Devices */
|
||||
/* #define STM32H750xx */ /*!< STM32H750V, STM32H750I, STM32H750X Devices */
|
||||
/* #define STM32H747xx */ /*!< STM32H747ZI, STM32H747AI, STM32H747II, STM32H747BI, STM32H747XI Devices */
|
||||
/* #define STM32H747xG */ /*!< STM32H747AG, STM32H747IG, STM32H747BG, STM32H747XG */
|
||||
/* #define STM32H757xx */ /*!< STM32H757ZI, STM32H757AI, STM32H757II, STM32H757BI, STM32H757XI Devices */
|
||||
/* #define STM32H745xx */ /*!< STM32H745ZI, STM32H745II, STM32H745BI, STM32H745XI Devices */
|
||||
/* #define STM32H745xG */ /*!< STM32H745ZG, STM32H745IG, STM32H745BG, STM32H745XG Devices */
|
||||
/* #define STM32H755xx */ /*!< STM32H755ZI, STM32H755II, STM32H755BI, STM32H755XI Devices */
|
||||
/* #define STM32H7B0xx */ /*!< STM32H7B0IBTx, STM32H7B0RBTx, STM32H7B0VBTx, STM32H7B0ZBTx Devices */
|
||||
/* #define STM32H7B0xxQ */ /*!< STM32H7B0ABIxQ, STM32H7B0IBKxQ Devices */
|
||||
/* #define STM32H7A3xx */ /*!< STM32H7A3IIK6, STM32H7A3IIT6, STM32H7A3NIH6, STM32H7A3RIT6, STM32H7A3VIH6, STM32H7A3VIT6, STM32H7A3ZIT6 */
|
||||
/* #define STM32H7A3xxQ */ /*!< STM32H7A3QIY6Q, STM32H7A3IIK6Q, STM32H7A3IIT6Q, STM32H7A3LIH6Q, STM32H7A3VIH6Q, STM32H7A3VIT6Q, STM32H7A3AII6Q, STM32H7A3ZIT6Q */
|
||||
/* #define STM32H7B3xx */ /*!< STM32H7B3IIK6, STM32H7B3IIT6, STM32H7B3NIH6, STM32H7B3RIT6, STM32H7B3VIH6, STM32H7B3VIT6, STM32H7B3ZIT6 */
|
||||
/* #define STM32H7B3xxQ */ /*!< STM32H7B3QIY6Q, STM32H7B3IIK6Q, STM32H7B3IIT6Q, STM32H7B3LIH6Q, STM32H7B3VIH6Q, STM32H7B3VIT6Q, STM32H7B3AII6Q, STM32H7B3ZIT6Q */
|
||||
/* #define STM32H735xx */ /*!< STM32H735AGI6, STM32H735IGK6, STM32H735RGV6, STM32H735VGT6, STM32H735VGY6, STM32H735ZGT6 Devices */
|
||||
/* #define STM32H733xx */ /*!< STM32H733VGH6, STM32H733VGT6, STM32H733ZGI6, STM32H733ZGT6, Devices */
|
||||
/* #define STM32H730xx */ /*!< STM32H730VBH6, STM32H730VBT6, STM32H730ZBT6, STM32H730ZBI6 Devices */
|
||||
/* #define STM32H730xxQ */ /*!< STM32H730IBT6Q, STM32H730ABI6Q, STM32H730IBK6Q Devices */
|
||||
/* #define STM32H725xx */ /*!< STM32H725AGI6, STM32H725IGK6, STM32H725IGT6, STM32H725RGV6, STM32H725VGT6, STM32H725VGY6, STM32H725ZGT6, STM32H725REV6, SM32H725VET6, STM32H725ZET6, STM32H725AEI6, STM32H725IET6, STM32H725IEK6 Devices */
|
||||
/* #define STM32H723xx */ /*!< STM32H723VGH6, STM32H723VGT6, STM32H723ZGI6, STM32H723ZGT6, STM32H723VET6, STM32H723VEH6, STM32H723ZET6, STM32H723ZEI6 Devices */
|
||||
#endif
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to switch between these
|
||||
devices, you can define the device in your toolchain compiler preprocessor.
|
||||
*/
|
||||
|
||||
#if !defined (USE_HAL_DRIVER)
|
||||
/**
|
||||
* @brief Comment the line below if you will not use the peripherals drivers.
|
||||
In this case, these drivers will not be included and the application code will
|
||||
be based on direct access to peripherals registers
|
||||
*/
|
||||
/*#define USE_HAL_DRIVER */
|
||||
#endif /* USE_HAL_DRIVER */
|
||||
|
||||
/**
|
||||
* @brief CMSIS Device version number V1.10.7
|
||||
*/
|
||||
#define __STM32H7xx_CMSIS_DEVICE_VERSION_MAIN (0x01) /*!< [31:24] main version */
|
||||
#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB1 (0x0A) /*!< [23:16] sub1 version */
|
||||
#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB2 (0x07) /*!< [15:8] sub2 version */
|
||||
#define __STM32H7xx_CMSIS_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */
|
||||
#define __STM32H7xx_CMSIS_DEVICE_VERSION ((__STM32H7xx_CMSIS_DEVICE_VERSION_MAIN << 24)\
|
||||
|(__STM32H7xx_CMSIS_DEVICE_VERSION_SUB1 << 16)\
|
||||
|(__STM32H7xx_CMSIS_DEVICE_VERSION_SUB2 << 8 )\
|
||||
|(__STM32H7xx_CMSIS_DEVICE_VERSION_RC))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Device_Included
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(STM32H743xx)
|
||||
#include "stm32h743xx.h"
|
||||
#elif defined(STM32H753xx)
|
||||
#include "stm32h753xx.h"
|
||||
#elif defined(STM32H750xx)
|
||||
#include "stm32h750xx.h"
|
||||
#elif defined(STM32H742xx)
|
||||
#include "stm32h742xx.h"
|
||||
#elif defined(STM32H745xx)
|
||||
#include "stm32h745xx.h"
|
||||
#elif defined(STM32H745xG)
|
||||
#include "stm32h745xg.h"
|
||||
#elif defined(STM32H755xx)
|
||||
#include "stm32h755xx.h"
|
||||
#elif defined(STM32H747xx)
|
||||
#include "stm32h747xx.h"
|
||||
#elif defined(STM32H747xG)
|
||||
#include "stm32h747xg.h"
|
||||
#elif defined(STM32H757xx)
|
||||
#include "stm32h757xx.h"
|
||||
#elif defined(STM32H7B0xx)
|
||||
#include "stm32h7b0xx.h"
|
||||
#elif defined(STM32H7B0xxQ)
|
||||
#include "stm32h7b0xxq.h"
|
||||
#elif defined(STM32H7A3xx)
|
||||
#include "stm32h7a3xx.h"
|
||||
#elif defined(STM32H7B3xx)
|
||||
#include "stm32h7b3xx.h"
|
||||
#elif defined(STM32H7A3xxQ)
|
||||
#include "stm32h7a3xxq.h"
|
||||
#elif defined(STM32H7B3xxQ)
|
||||
#include "stm32h7b3xxq.h"
|
||||
#elif defined(STM32H735xx)
|
||||
#include "stm32h735xx.h"
|
||||
#elif defined(STM32H733xx)
|
||||
#include "stm32h733xx.h"
|
||||
#elif defined(STM32H730xx)
|
||||
#include "stm32h730xx.h"
|
||||
#elif defined(STM32H730xxQ)
|
||||
#include "stm32h730xxq.h"
|
||||
#elif defined(STM32H725xx)
|
||||
#include "stm32h725xx.h"
|
||||
#elif defined(STM32H723xx)
|
||||
#include "stm32h723xx.h"
|
||||
#else
|
||||
#error "Please select first the target STM32H7xx device used in your application (in stm32h7xx.h file)"
|
||||
#endif
|
||||
|
||||
#if defined(DUAL_CORE) && !defined(CORE_CM4) && !defined(CORE_CM7)
|
||||
#error "Dual core device, please select CORE_CM4 or CORE_CM7"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Exported_types
|
||||
* @{
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
RESET = 0,
|
||||
SET = !RESET
|
||||
} FlagStatus, ITStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DISABLE = 0,
|
||||
ENABLE = !DISABLE
|
||||
} FunctionalState;
|
||||
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SUCCESS = 0,
|
||||
ERROR = !SUCCESS
|
||||
} ErrorStatus;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Exported_macros
|
||||
* @{
|
||||
*/
|
||||
#define SET_BIT(REG, BIT) ((REG) |= (BIT))
|
||||
|
||||
#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
|
||||
|
||||
#define READ_BIT(REG, BIT) ((REG) & (BIT))
|
||||
|
||||
#define CLEAR_REG(REG) ((REG) = (0x0))
|
||||
|
||||
#define WRITE_REG(REG, VAL) ((REG) = (VAL))
|
||||
|
||||
#define READ_REG(REG) ((REG))
|
||||
|
||||
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
|
||||
|
||||
#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
|
||||
|
||||
/* Use of CMSIS compiler intrinsics for register exclusive access */
|
||||
/* Atomic 32-bit register access macro to set one or several bits */
|
||||
#define ATOMIC_SET_BIT(REG, BIT) \
|
||||
do { \
|
||||
uint32_t val; \
|
||||
do { \
|
||||
val = __LDREXW((__IO uint32_t *)&(REG)) | (BIT); \
|
||||
} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \
|
||||
} while(0)
|
||||
|
||||
/* Atomic 32-bit register access macro to clear one or several bits */
|
||||
#define ATOMIC_CLEAR_BIT(REG, BIT) \
|
||||
do { \
|
||||
uint32_t val; \
|
||||
do { \
|
||||
val = __LDREXW((__IO uint32_t *)&(REG)) & ~(BIT); \
|
||||
} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \
|
||||
} while(0)
|
||||
|
||||
/* Atomic 32-bit register access macro to clear and set one or several bits */
|
||||
#define ATOMIC_MODIFY_REG(REG, CLEARMSK, SETMASK) \
|
||||
do { \
|
||||
uint32_t val; \
|
||||
do { \
|
||||
val = (__LDREXW((__IO uint32_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \
|
||||
} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \
|
||||
} while(0)
|
||||
|
||||
/* Atomic 16-bit register access macro to set one or several bits */
|
||||
#define ATOMIC_SETH_BIT(REG, BIT) \
|
||||
do { \
|
||||
uint16_t val; \
|
||||
do { \
|
||||
val = __LDREXH((__IO uint16_t *)&(REG)) | (BIT); \
|
||||
} while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \
|
||||
} while(0)
|
||||
|
||||
/* Atomic 16-bit register access macro to clear one or several bits */
|
||||
#define ATOMIC_CLEARH_BIT(REG, BIT) \
|
||||
do { \
|
||||
uint16_t val; \
|
||||
do { \
|
||||
val = __LDREXH((__IO uint16_t *)&(REG)) & ~(BIT); \
|
||||
} while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \
|
||||
} while(0)
|
||||
|
||||
/* Atomic 16-bit register access macro to clear and set one or several bits */
|
||||
#define ATOMIC_MODIFYH_REG(REG, CLEARMSK, SETMASK) \
|
||||
do { \
|
||||
uint16_t val; \
|
||||
do { \
|
||||
val = (__LDREXH((__IO uint16_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \
|
||||
} while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined (USE_HAL_DRIVER)
|
||||
#include "stm32h7xx_hal.h"
|
||||
#endif /* USE_HAL_DRIVER */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* STM32H7xx_H */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
Loaded 100 of 267 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user