Reorganized NXP examples

This commit is contained in:
robert committed 2026-09-18 10:07:08 +03:00
1 parent aae31aba9c
commit 201a81a315
1955 files changed
+5705 -1344015

No files matched your search

@@ -0,0 +1 @@
See the example at https://github.com/mongoose-examples/frdm-imxrt1186
@@ -0,0 +1,48 @@
# Environment setup: https://mongoose.ws/documentation/tutorials/tools/
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 -Wno-unused-function
CFLAGS += -I. -Imongoose -Icmsis_core/CMSIS/Core/Include/
CFLAGS += -Icmsis_rt1186/devices/MIMXRT1186/ -Icmsis_rt1186/devices/MIMXRT1186/periph/ -Icmsis_rt1186/devices/MIMXRT1186/drivers/
CFLAGS += -DCPU_MIMXRT1186CVJ8C_cm33 -DCPU_MIMXRT1186CVJ8C -DMIMXRT1186_cm33_SERIES
CFLAGS += -DXIP_EXTERNAL_FLASH=1 -DXIP_BOOT_HEADER_ENABLE=1
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 -Wl,-Map=$@.map
SOURCES = main.c hal.c flash_image.c mongoose/mongoose.c
SOURCES += cmsis_rt1186/devices/MIMXRT1186/gcc/startup_MIMXRT1186_cm33.S
SOURCES += cmsis_rt1186/devices/MIMXRT1186/drivers/fsl_clock.c
SOURCES += cmsis_rt1186/devices/MIMXRT1186/drivers/fsl_pmu.c
SOURCES += cmsis_rt1186/devices/MIMXRT1186/drivers/fsl_common_arm.c
SOURCES += cmsis_rt1186/devices/MIMXRT1186/drivers/fsl_ele_base_api.c
SOURCES += cmsis_rt1186/devices/MIMXRT1186/drivers/fsl_s3mu.c
SOURCES += cmsis_rt1186/devices/MIMXRT1186/drivers/fsl_trdc.c
CFLAGS += -D__ATOLLIC__ -D__STARTUP_CLEAR_BSS -DMG_HAL_DISABLE_RANDOM
all build: firmware.bin
mongoose/mongoose.c mongoose/mongoose.h:
mkdir -p mongoose
cp ../../../../mongoose.[ch] mongoose/
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
arm-none-eabi-size --format=berkeley $<
firmware.elf: cmsis_core cmsis_rt1186 $(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 $@
cmsis_rt1186:
curl -sL https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.MIMXRT1186_DFP.26.06.00.pack -o NXP.MIMXRT1186_DFP.26.06.00.pack
unzip -q NXP.MIMXRT1186_DFP.26.06.00.pack -d $@
rm NXP.MIMXRT1186_DFP.26.06.00.pack
clean:
rm -rf firmware.* cmsis_* mongoose/mongoose.*
@@ -0,0 +1,157 @@
#include <stdint.h>
#define LUT_OPERAND0(x) ((uint32_t) (x) << 0)
#define LUT_NUM_PADS0(x) ((uint32_t) (x) << 8)
#define LUT_OPCODE0(x) ((uint32_t) (x) << 10)
#define LUT_OPERAND1(x) ((uint32_t) (x) << 16)
#define LUT_NUM_PADS1(x) ((uint32_t) (x) << 24)
#define LUT_OPCODE1(x) ((uint32_t) (x) << 26)
#define LUT_SEQ(cmd0, pads0, operand0, cmd1, pads1, operand1) \
(LUT_OPERAND0(operand0) | LUT_NUM_PADS0(pads0) | LUT_OPCODE0(cmd0) | \
LUT_OPERAND1(operand1) | LUT_NUM_PADS1(pads1) | LUT_OPCODE1(cmd1))
enum {
LUT_STOP = 0x00,
LUT_CMD_SDR = 0x01,
LUT_RADDR_SDR = 0x02,
LUT_WRITE_SDR = 0x08,
LUT_READ_SDR = 0x09,
LUT_DUMMY_SDR = 0x0c,
LUT_1_PAD = 0,
LUT_4_PADS = 2,
};
// FlexSPI2 NOR configuration block for the FRDM-IMXRT1186 QSPI flash
// The ROM expects this 512-byte structure at flash offset 0x400
__attribute__((section(".boot_hdr.conf"), used))
const uint32_t qspi_flash_nor_config[128] = {
[0] = 0x42464346, // Tag: "FCFB"
[1] = 0x56010400, // Version 1.4.0
[3] = 0x00030301, // DQS loopback, CS hold/setup = 3
[16] = 0x00000010, // Safe configuration
[17] = 0x00050401, // Serial NOR, 4 pads, 100 MHz
[20] = 16U * 1024U * 1024U,
// Read
[32] =
LUT_SEQ(LUT_CMD_SDR, LUT_1_PAD, 0xeb, LUT_RADDR_SDR, LUT_4_PADS, 0x18),
[33] =
LUT_SEQ(LUT_DUMMY_SDR, LUT_4_PADS, 0x06, LUT_READ_SDR, LUT_4_PADS, 0x04),
// Read status
[36] =
LUT_SEQ(LUT_CMD_SDR, LUT_1_PAD, 0x05, LUT_READ_SDR, LUT_1_PAD, 0x04),
// Write enable
[44] =
LUT_SEQ(LUT_CMD_SDR, LUT_1_PAD, 0x06, LUT_STOP, LUT_1_PAD, 0x00),
// Erase 4-KiB sector
[52] =
LUT_SEQ(LUT_CMD_SDR, LUT_1_PAD, 0x20, LUT_RADDR_SDR, LUT_1_PAD, 0x18),
// Erase 64-KiB block
[64] =
LUT_SEQ(LUT_CMD_SDR, LUT_1_PAD, 0xd8, LUT_RADDR_SDR, LUT_1_PAD, 0x18),
// Program page
[68] =
LUT_SEQ(LUT_CMD_SDR, LUT_1_PAD, 0x02, LUT_RADDR_SDR, LUT_1_PAD, 0x18),
[69] =
LUT_SEQ(LUT_WRITE_SDR, LUT_1_PAD, 0x04, LUT_STOP, LUT_1_PAD, 0x00),
// Erase chip
[76] =
LUT_SEQ(LUT_CMD_SDR, LUT_1_PAD, 0x60, LUT_STOP, LUT_1_PAD, 0x00),
[112] = 256, // Page size
[113] = 4U * 1024U, // Sector size
[114] = 1, // IP-command serial clock
[116] = 64U * 1024U, // Block size
};
typedef struct __attribute__((packed)) {
uint8_t version;
uint16_t length;
uint8_t tag;
uint32_t flags;
uint16_t software_version;
uint8_t fuse_version;
uint8_t image_count;
uint16_t signature_block_offset;
uint16_t reserved;
} container_header_t;
typedef struct __attribute__((packed)) {
uint32_t offset;
uint32_t size;
uint32_t load_address;
uint32_t reserved1;
uint32_t entry_address;
uint32_t reserved2;
uint32_t flags;
uint32_t metadata;
uint8_t hash[64];
uint8_t iv[32];
} container_image_t;
typedef struct __attribute__((packed)) {
uint8_t version;
uint16_t length;
uint8_t tag;
uint16_t certificate_offset;
uint16_t srk_table_offset;
uint16_t signature_offset;
uint16_t blob_offset;
uint32_t reserved;
} signature_block_t;
typedef struct __attribute__((packed)) {
container_header_t header;
container_image_t image[1];
signature_block_t signature;
} boot_container_t;
extern const uint32_t _image_offset[];
extern const uint32_t _image_size[];
extern const uint32_t _image_loadaddr[];
extern const uint32_t Reset_Handler[];
// RT1180 Program Image Container. The ROM expects it at flash offset 0x1000
__attribute__((section(".boot_hdr.container"), used))
const boot_container_t container_data = {
.header = {
.version = 0,
.length = sizeof(boot_container_t),
.tag = 0x87,
.flags = 0,
.software_version = 0,
.fuse_version = 0,
.image_count = 1,
.signature_block_offset =
sizeof(container_header_t) + sizeof(container_image_t),
.reserved = 0,
},
.image = {{
.offset = (uint32_t) _image_offset,
.size = (uint32_t) _image_size,
.load_address = (uint32_t) _image_loadaddr,
.reserved1 = 0,
.entry_address = (uint32_t) Reset_Handler,
.reserved2 = 0,
.flags = 0x00000213, // Plain SHA-512 CM33 executable image
.metadata = 0,
.hash = {0},
.iv = {0},
}},
.signature = {
.version = 0,
.length = sizeof(signature_block_t),
.tag = 0x90,
.certificate_offset = 0,
.srk_table_offset = 0,
.signature_offset = 0,
.blob_offset = 0,
.reserved = 0,
},
};
+125
View File
@@ -0,0 +1,125 @@
// Copyright (c) 2026 Cesanta Software Limited
// All rights reserved
#include "hal.h"
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;
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) {
}
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) {
}
+662
View File
@@ -0,0 +1,662 @@
// https://www.nxp.com/docs/en/reference-manual/IMXRT1180RM.pdf
// https://www.nxp.com/docs/en/data-sheet/IMXRT1180EC.pdf
// https://www.mouser.com/catalog/specsheets/NXP_0-28-2026_FRDM-IMXRT1186.pdf
#pragma once
#include "MIMXRT1186_cm33.h"
#include "fsl_clock.h"
#include "fsl_ele_base_api.h"
#include "fsl_trdc.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define PIN(bank, num) ((((bank) - '0') << 8) | (num))
#define PINNO(pin) ((pin) & 255)
#define PINBANK(pin) ((pin) >> 8)
#define HAL_DEBUG_UART_CLK_ROOT kCLOCK_Root_Lpuart0102
#define HAL_DEBUG_UART_CLK 24000000UL
#define HAL_DEBUG_UART_TX_PIN PIN('1', 8) // GPIO_AON_08, ball A7
#define HAL_DEBUG_UART_RX_PIN PIN('1', 9) // GPIO_AON_09, ball B12
#define SYS_FREQUENCY 240000000UL
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;
}
enum { HAL_GPIO_MODE_INPUT, HAL_GPIO_MODE_OUTPUT };
enum { HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_OTYPE_OPEN_DRAIN };
enum { HAL_GPIO_SPEED_LOW, HAL_GPIO_SPEED_HIGH };
enum { HAL_GPIO_PULL_NONE, HAL_GPIO_PULL_UP, HAL_GPIO_PULL_DOWN };
static void hal_flexspi2_clock_config(uint8_t src, uint32_t divider)
__attribute__((section(".iram")));
static void hal_flexspi2_clock_config(uint8_t src, uint32_t divider) {
const clock_root_t root = kCLOCK_Root_Flexspi2;
const clock_lpcg_t lpcg = kCLOCK_Flexspi2;
FLEXSPI_Type *base = FLEXSPI2;
uint32_t status, last_status, retry;
if ((CCM->CLOCK_ROOT[root].CONTROL & CCM_CLOCK_ROOT_CONTROL_MUX_MASK) ==
CCM_CLOCK_ROOT_CONTROL_MUX(src) &&
(CCM->CLOCK_ROOT[root].CONTROL & CCM_CLOCK_ROOT_CONTROL_DIV_MASK) ==
CCM_CLOCK_ROOT_CONTROL_DIV(divider - 1U)) {
return;
}
// BOARD_DeinitFlash(): flush/disable the CM33 cache, then stop FlexSPI2.
if ((XCACHE_PC->CCR & XCACHE_CCR_ENCACHE_MASK) != 0U) {
XCACHE_PC->CCR |=
XCACHE_CCR_PUSHW0_MASK | XCACHE_CCR_PUSHW1_MASK | XCACHE_CCR_GO_MASK;
while ((XCACHE_PC->CCR & XCACHE_CCR_GO_MASK) != 0U) (void) 0;
XCACHE_PC->CCR &=
~(XCACHE_CCR_PUSHW0_MASK | XCACHE_CCR_PUSHW1_MASK |
XCACHE_CCR_ENCACHE_MASK);
__ISB();
__DSB();
}
base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
while ((base->STS0 & (FLEXSPI_STS0_ARBIDLE_MASK |
FLEXSPI_STS0_SEQIDLE_MASK)) !=
(FLEXSPI_STS0_ARBIDLE_MASK | FLEXSPI_STS0_SEQIDLE_MASK)) {
(void) 0;
}
base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
CCM->LPCG[lpcg].DIRECT &= ~CCM_LPCG_DIRECT_ON_MASK;
__DSB();
__ISB();
while ((CCM->LPCG[lpcg].STATUS0 & CCM_LPCG_STATUS0_ON_MASK) != 0U)
(void) 0;
CCM->CLOCK_ROOT[root].CONTROL =
CCM_CLOCK_ROOT_CONTROL_MUX(src) |
CCM_CLOCK_ROOT_CONTROL_DIV(divider - 1U);
__DSB();
__ISB();
(void) CCM->CLOCK_ROOT[root].CONTROL;
CCM->LPCG[lpcg].DIRECT |= CCM_LPCG_DIRECT_ON_MASK;
__DSB();
__ISB();
while ((CCM->LPCG[lpcg].STATUS0 & CCM_LPCG_STATUS0_ON_MASK) == 0U)
(void) 0;
// BOARD_InitFlash(): restore the reference project's AHB buffers and DLL.
if ((base->AHBCR & FLEXSPI_AHBCR_PREFETCHEN_MASK) != 0U) {
base->AHBRXBUFCR0[0] =
FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK |
FLEXSPI_AHBRXBUFCR0_PRIORITY(4U) |
FLEXSPI_AHBRXBUFCR0_MSTRID(0U) |
FLEXSPI_AHBRXBUFCR0_BUFSZ(512U / 8U); // NETC
base->AHBRXBUFCR0[1] =
FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK |
FLEXSPI_AHBRXBUFCR0_PRIORITY(7U) |
FLEXSPI_AHBRXBUFCR0_MSTRID(8U) |
FLEXSPI_AHBRXBUFCR0_BUFSZ(512U / 8U); // CM33
base->AHBRXBUFCR0[2] =
FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK |
FLEXSPI_AHBRXBUFCR0_PRIORITY(7U) |
FLEXSPI_AHBRXBUFCR0_MSTRID(9U) |
FLEXSPI_AHBRXBUFCR0_BUFSZ(512U / 8U); // CM7
for (uint32_t i = 3U; i < FLEXSPI_AHBRXBUFCR0_COUNT; i++) {
base->AHBRXBUFCR0[i] =
FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK |
FLEXSPI_AHBRXBUFCR0_BUFSZ(0U);
}
}
base->DLLCR[0] = 1U;
base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
while ((base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) != 0U) (void) 0;
if ((base->DLLCR[0] & FLEXSPI_DLLCR_DLLEN_MASK) != 0U) {
last_status = base->STS2;
retry = 10U;
do {
status = base->STS2;
if ((status &
(FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK)) ==
(FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK)) {
retry = 100U;
break;
} else if (status == last_status) {
retry--;
} else {
retry = 10U;
last_status = status;
}
} while (retry > 0U);
while (retry-- > 0U) __NOP(); // ERR011377
}
if ((XCACHE_PC->CCR & XCACHE_CCR_ENCACHE_MASK) == 0U) {
XCACHE_PC->CCR = XCACHE_CCR_INVW1_MASK | XCACHE_CCR_INVW0_MASK;
XCACHE_PC->CCR |= XCACHE_CCR_GO_MASK;
while ((XCACHE_PC->CCR & XCACHE_CCR_GO_MASK) != 0U) (void) 0;
XCACHE_PC->CCR = XCACHE_CCR_ENCACHE_MASK;
__ISB();
__DSB();
}
}
static inline void hal_clock_root(clock_root_t root, uint8_t mux, uint8_t div) {
const clock_root_config_t config = {
.clockOff = false,
.mux = mux,
.div = div,
};
CLOCK_SetRootClock(root, &config);
}
static inline void hal_edgelock_clock_config(uint8_t mux, uint8_t div) {
if (CLOCK_GetRootClockDiv(kCLOCK_Root_Edgelock) != div ||
CLOCK_GetRootClockMux(kCLOCK_Root_Edgelock) != mux) {
status_t status;
do {
status = ELE_BaseAPI_ClockChangeStart(MU_RT_S3MUA);
} while (status != kStatus_Success);
hal_clock_root(kCLOCK_Root_Edgelock, mux, div);
uint8_t mhz =
(uint8_t) (CLOCK_GetRootClockFreq(kCLOCK_Root_Edgelock) / 1000000UL);
do {
status = ELE_BaseAPI_ClockChangeFinish(MU_RT_S3MUA, mhz, 0U);
} while (status != kStatus_Success);
}
}
static inline void hal_clock_init(void) {
const clock_sys_pll1_config_t sys_pll1 = {
.pllDiv2En = true,
.pllDiv5En = true,
.ss = NULL,
.ssEnable = false,
};
const clock_sys_pll2_config_t sys_pll2 = {
.mfd = 268435455U,
.ss = NULL,
.ssEnable = false,
};
CLOCK_OSC_EnableOscRc400M();
hal_clock_root(kCLOCK_Root_M33, kCLOCK_M33_ClockRoot_MuxOscRc400M, 2U);
CLOCK_OSC_Set1MHzOutputBehavior(kCLOCK_1MHzOutEnableFreeRunning1Mhz);
CLOCK_OSC_EnableOscRc24M(true);
ANADIG_OSC->OSC_24M_CTRL |=
ANADIG_OSC_OSC_24M_CTRL_OSC_EN_MASK |
ANADIG_OSC_OSC_24M_CTRL_LP_EN_MASK;
ANADIG_OSC->OSC_24M_CTRL &=
~(ANADIG_OSC_OSC_24M_CTRL_BYPASS_EN_MASK |
ANADIG_OSC_OSC_24M_CTRL_OSC_24M_GATE_MASK);
while ((ANADIG_OSC->OSC_24M_CTRL &
ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK) == 0U) {
(void) 0;
}
// The image is linked at 0x04000000 and executes through FlexSPI2.
hal_flexspi2_clock_config(0U, 1U); // OSC_RC_24M while PLLs change
CLOCK_InitSysPll1(&sys_pll1);
CLOCK_InitSysPll2(&sys_pll2);
CLOCK_InitSysPll3();
CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd2, 22U);
CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd3, 18U);
hal_clock_root(kCLOCK_Root_M33, kCLOCK_M33_ClockRoot_MuxSysPll3Out, 2U);
hal_edgelock_clock_config(kCLOCK_EDGELOCK_ClockRoot_MuxOscRc400M, 2U);
hal_clock_root(kCLOCK_Root_Bus_Aon,
kCLOCK_BUS_AON_ClockRoot_MuxSysPll2Out, 4U);
hal_clock_root(kCLOCK_Root_Bus_Wakeup,
kCLOCK_BUS_WAKEUP_ClockRoot_MuxSysPll2Out, 4U);
hal_clock_root(kCLOCK_Root_Wakeup_Axi,
kCLOCK_WAKEUP_AXI_ClockRoot_MuxSysPll3Out, 2U);
hal_clock_root(kCLOCK_Root_M33_Systick,
kCLOCK_M33_SYSTICK_ClockRoot_MuxOsc24MOut, 240U);
hal_flexspi2_clock_config(
kCLOCK_FLEXSPI2_ClockRoot_MuxSysPll3Pfd2, 4U);
hal_clock_root(kCLOCK_Root_Lpuart0102,
kCLOCK_LPUART0102_ClockRoot_MuxSysPll3Div2, 10U);
hal_clock_root(kCLOCK_Root_Enet,
kCLOCK_ENET_ClockRoot_MuxSysPll1Div2, 4U);
hal_clock_root(kCLOCK_Root_Tmr_1588,
kCLOCK_TMR_1588_ClockRoot_MuxSysPll3Out, 2U);
hal_clock_root(kCLOCK_Root_Netc,
kCLOCK_NETC_ClockRoot_MuxSysPll3Pfd3, 2U);
hal_clock_root(kCLOCK_Root_Mac0,
kCLOCK_MAC0_ClockRoot_MuxSysPll1Div2, 4U);
hal_clock_root(kCLOCK_Root_Mac1,
kCLOCK_MAC1_ClockRoot_MuxSysPll1Div2, 4U);
hal_clock_root(kCLOCK_Root_Mac2,
kCLOCK_MAC2_ClockRoot_MuxSysPll1Div2, 4U);
hal_clock_root(kCLOCK_Root_Mac3,
kCLOCK_MAC3_ClockRoot_MuxSysPll1Div2, 4U);
hal_clock_root(kCLOCK_Root_Mac4,
kCLOCK_MAC4_ClockRoot_MuxSysPll1Div2, 10U);
BLK_CTRL_WAKEUPMIX->NETC_PORT_MISC_CFG &=
~(BLK_CTRL_WAKEUPMIX_NETC_PORT_MISC_CFG_PORT0_RMII_REF_CLK_DIR_MASK |
BLK_CTRL_WAKEUPMIX_NETC_PORT_MISC_CFG_PORT1_RMII_REF_CLK_DIR_MASK |
BLK_CTRL_WAKEUPMIX_NETC_PORT_MISC_CFG_PORT2_RMII_REF_CLK_DIR_MASK |
BLK_CTRL_WAKEUPMIX_NETC_PORT_MISC_CFG_PORT3_RMII_REF_CLK_DIR_MASK |
BLK_CTRL_WAKEUPMIX_NETC_PORT_MISC_CFG_PORT4_RMII_REF_CLK_DIR_MASK);
BLK_CTRL_WAKEUPMIX->NETC_PORT_MISC_CFG |=
BLK_CTRL_WAKEUPMIX_NETC_PORT_MISC_CFG_TMR_EXT_CLK_SEL_MASK;
SystemCoreClock = CLOCK_GetRootClockFreq(kCLOCK_Root_M33);
}
static inline void hal_rtwdog_disable(RTWDOG_Type *wdog) {
if ((wdog->CS & RTWDOG_CS_CMD32EN_MASK) != 0U) {
wdog->CNT = 0xD928C520U;
} else {
wdog->CNT = 0xC520U;
wdog->CNT = 0xD928U;
}
wdog->TOVAL = 0xFFFFU;
wdog->CS = (wdog->CS & ~RTWDOG_CS_EN_MASK) | RTWDOG_CS_UPDATE_MASK;
}
static inline void hal_system_init(void) {
extern uint32_t _siram, _eiram, _siiram;
volatile uint32_t *dst = &_siram;
const uint32_t *src = &_siiram;
while (dst < &_eiram) *dst++ = *src++;
SCB->CPACR |= (3UL << 10U * 2U) | (3UL << 11U * 2U);
hal_rtwdog_disable(RTWDOG1);
hal_rtwdog_disable(RTWDOG2);
hal_rtwdog_disable(RTWDOG3);
hal_rtwdog_disable(RTWDOG4);
hal_rtwdog_disable(RTWDOG5);
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
if ((XCACHE_PC->CCR & XCACHE_CCR_ENCACHE_MASK) == 0U) {
XCACHE_PC->CCR = XCACHE_CCR_INVW1_MASK | XCACHE_CCR_INVW0_MASK;
XCACHE_PC->CCR |= XCACHE_CCR_GO_MASK;
while ((XCACHE_PC->CCR & XCACHE_CCR_GO_MASK) != 0U) (void) 0;
XCACHE_PC->CCR = XCACHE_CCR_ENCACHE_MASK;
}
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
__DSB();
__ISB();
}
static inline RGPIO_Type *hal_gpio_bank(uint16_t pin) {
static RGPIO_Type *const g[] = RGPIO_BASE_PTRS;
return g[PINBANK(pin)];
}
static inline void hal_gpio_mux_config(uint16_t index, uint8_t af) {
IOMUXC->SW_MUX_CTL_PAD[index] =
IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(af);
}
static inline void hal_periph_mux_config(uint16_t index, uint8_t input) {
IOMUXC->SELECT_INPUT[index] = input;
}
static inline void hal_gpio_aon_mux_config(uint16_t index, uint8_t af) {
IOMUXC_AON->SW_MUX_CTL_PAD[index] =
IOMUXC_AON_SW_MUX_CTL_PAD_MUX_MODE(af);
}
static inline void hal_gpio_pad_config(uint16_t index, uint8_t type,
uint8_t speed, uint8_t pull) {
if (index < kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_00 ||
index >= kIOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B1_00) {
uint8_t pad_pull = 3U; // No pull
if (pull == HAL_GPIO_PULL_UP) pad_pull = 1U;
if (pull == HAL_GPIO_PULL_DOWN) pad_pull = 2U;
IOMUXC->SW_PAD_CTL_PAD[index] =
IOMUXC_SW_PAD_CTL_PAD_PDRV(speed == HAL_GPIO_SPEED_LOW) |
IOMUXC_SW_PAD_CTL_PAD_ODE(type == HAL_GPIO_OTYPE_OPEN_DRAIN) |
IOMUXC_SW_PAD_CTL_PAD_PULL(pad_pull);
} else {
bool dopull = pull != HAL_GPIO_PULL_NONE;
IOMUXC->SW_PAD_CTL_PAD[index] =
IOMUXC_SW_PAD_CTL_PAD_SRE(speed == HAL_GPIO_SPEED_LOW) |
IOMUXC_SW_PAD_CTL_PAD_DSE(speed == HAL_GPIO_SPEED_HIGH) |
IOMUXC_SW_PAD_CTL_PAD_ODE(type == HAL_GPIO_OTYPE_OPEN_DRAIN) |
IOMUXC_SW_PAD_CTL_PAD_PUE(dopull) |
IOMUXC_SW_PAD_CTL_PAD_PUS(pull == HAL_GPIO_PULL_UP);
}
}
static inline void hal_gpio_aon_pad_config(uint16_t index, uint8_t type,
uint8_t speed, uint8_t pull) {
bool dopull = pull != HAL_GPIO_PULL_NONE;
IOMUXC_AON->SW_PAD_CTL_PAD[index] =
IOMUXC_AON_SW_PAD_CTL_PAD_SRE(speed == HAL_GPIO_SPEED_LOW) |
IOMUXC_AON_SW_PAD_CTL_PAD_DSE(speed == HAL_GPIO_SPEED_HIGH) |
IOMUXC_AON_SW_PAD_CTL_PAD_ODE(type == HAL_GPIO_OTYPE_OPEN_DRAIN) |
IOMUXC_AON_SW_PAD_CTL_PAD_PUE(dopull) |
IOMUXC_AON_SW_PAD_CTL_PAD_PUS(pull == HAL_GPIO_PULL_UP);
}
static inline void hal_gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
uint8_t speed, uint8_t pull) {
static const clock_ip_name_t clocks[] = GPIO_CLOCKS;
uint8_t bank = (uint8_t) PINBANK(pin);
uint8_t bit = (uint8_t) PINNO(pin);
uint32_t mask = 1UL << bit;
uint16_t index;
switch (bank) {
case 1:
index = kIOMUXC_AON_SW_MUX_CTL_PAD_GPIO_AON_00 + bit;
break;
case 2:
index = kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B1_00 + bit;
break;
case 3:
index = kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B1_32 + bit;
break;
case 4:
index = kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_00 + bit;
break;
case 5:
index = kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_32 + bit;
break;
case 6:
index = kIOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 + bit;
break;
default:
return;
}
RGPIO_Type *gpio = hal_gpio_bank(pin);
CLOCK_EnableClock(clocks[bank]);
CLOCK_EnableClock(bank == 1U ? kCLOCK_Iomuxc2 : kCLOCK_Iomuxc1);
gpio->ICR[bit] = RGPIO_ICR_ISF_MASK; // Disable and clear interrupts
gpio->PIDR &= ~mask; // Keep the digital input path enabled
if (mode == HAL_GPIO_MODE_INPUT) {
gpio->PDDR &= ~mask;
} else {
gpio->PCOR = mask; // Initial output level is low
gpio->PDDR |= mask;
}
if (bank == 1U) {
hal_gpio_aon_pad_config(index, type, speed, pull);
hal_gpio_aon_mux_config(index, 5U);
} else {
hal_gpio_pad_config(index, type, speed, pull);
hal_gpio_mux_config(index, 5U);
}
}
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_LOW, HAL_GPIO_PULL_NONE);
}
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_LOW, HAL_GPIO_PULL_NONE);
}
static inline bool hal_gpio_read(uint16_t pin) {
RGPIO_Type *gpio = hal_gpio_bank(pin);
return (gpio->PDIR & (1UL << PINNO(pin))) != 0U;
}
static inline void hal_gpio_write(uint16_t pin, bool value) {
RGPIO_Type *gpio = hal_gpio_bank(pin);
uint32_t mask = 1UL << PINNO(pin);
if (value) {
gpio->PSOR = mask;
} else {
gpio->PCOR = mask;
}
}
static inline void hal_gpio_toggle(uint16_t pin) {
RGPIO_Type *gpio = hal_gpio_bank(pin);
gpio->PTOR = 1UL << PINNO(pin);
}
static inline void hal_uart_init(LPUART_Type *uart, unsigned long baud) {
if (uart != LPUART1 || baud == 0UL) return;
uint16_t tx = kIOMUXC_AON_SW_MUX_CTL_PAD_GPIO_AON_00 +
PINNO(HAL_DEBUG_UART_TX_PIN);
uint16_t rx = kIOMUXC_AON_SW_MUX_CTL_PAD_GPIO_AON_00 +
PINNO(HAL_DEBUG_UART_RX_PIN);
uint32_t sbr = HAL_DEBUG_UART_CLK / (16UL * baud);
if (sbr == 0U) sbr = 1U;
hal_clock_root(HAL_DEBUG_UART_CLK_ROOT,
kCLOCK_LPUART0102_ClockRoot_MuxSysPll3Div2, 10U);
CLOCK_EnableClock(kCLOCK_Iomuxc2);
CLOCK_EnableClock(kCLOCK_Lpuart1);
hal_gpio_aon_pad_config(tx, HAL_GPIO_OTYPE_PUSH_PULL,
HAL_GPIO_SPEED_HIGH, HAL_GPIO_PULL_NONE);
hal_gpio_aon_mux_config(tx, 0U);
hal_gpio_aon_pad_config(rx, HAL_GPIO_OTYPE_PUSH_PULL,
HAL_GPIO_SPEED_HIGH, HAL_GPIO_PULL_NONE);
hal_gpio_aon_mux_config(rx, 0U);
uart->GLOBAL |= LPUART_GLOBAL_RST_MASK;
uart->GLOBAL &= ~LPUART_GLOBAL_RST_MASK;
uart->FIFO = 0U; // Disable TX/RX FIFOs and FIFO interrupts
uart->WATER = 0U;
uart->BAUD = LPUART_BAUD_OSR(16U - 1U) | LPUART_BAUD_SBR(sbr);
uart->CTRL = LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK;
}
static inline void hal_uart_write_byte(LPUART_Type *uart, uint8_t byte) {
uart->DATA = byte;
while ((uart->STAT & LPUART_STAT_TDRE_MASK) == 0U) spin(1);
}
static inline void hal_uart_write_buf(LPUART_Type *uart, const char *buf,
size_t len) {
while (len-- > 0U) hal_uart_write_byte(uart, (uint8_t) *buf++);
}
static inline int hal_uart_read_ready(LPUART_Type *uart) {
return (int) (uart->STAT & LPUART_STAT_RDRF_MASK);
}
static inline uint8_t hal_uart_read_byte(LPUART_Type *uart) {
return (uint8_t) (uart->DATA & 0xFFU);
}
#define HAL_NETC_PHY0_ADDR 5U
#define HAL_NETC_PHY0_RESET PIN('1', 15)
static inline void hal_netc_trdc_region(uint8_t mrc, uint8_t domain,
uint32_t start, uint32_t end) {
const trdc_mrc_region_descriptor_config_t region = {
.memoryAccessControlSelect = 7U,
.startAddr = start,
.valid = true,
.nseEnable = false,
.endAddr = end,
.mrcIdx = mrc,
.domainIdx = domain,
.regionIdx = 0U,
};
TRDC_MrcSetRegionDescriptorConfig(TRDC2, &region);
}
// Open the security gates needed by the CPU and NETC
static inline void hal_netc_trdc_init(void) {
const trdc_processor_domain_assignment_t cm33 = {
.domainId = 2U,
.domainIdSelect = kTRDC_DidInput,
.pidDomainHitConfig = kTRDC_pidDomainHitNone0,
.pidMask = 0U,
.secureAttr = kTRDC_ForceSecure,
.pid = 0U,
.lock = false,
};
const trdc_processor_domain_assignment_t netc = {
.domainId = 10U,
.domainIdSelect = kTRDC_DidInput,
.pidDomainHitConfig = kTRDC_pidDomainHitNone0,
.pidMask = 0U,
.secureAttr = kTRDC_ForceSecure,
.pid = 0U,
.lock = false,
};
const trdc_memory_access_control_config_t netc_access = {
.secureUsrW = 1U,
.secureUsrR = 1U,
.securePrivW = 1U,
.securePrivR = 1U,
};
const trdc_memory_access_control_config_t cpu_access = {
.securePrivW = 1U,
.securePrivR = 1U,
};
ELE_BaseAPI_ReleaseRDC(MU_RT_S3MUA, 0x74U, 1U); // TRDC AON
ELE_BaseAPI_ReleaseRDC(MU_RT_S3MUA, 0x82U, 1U); // TRDC MEGA
ELE_BaseAPI_ReleaseRDC(MU_RT_S3MUA, 0x78U, 1U); // TRDC WAKEUP
TRDC_SetProcessorDomainAssignment(
TRDC1, (uint8_t) kTRDC1_MasterCM33, 0U, &cm33);
TRDC_SetProcessorDomainAssignment(
TRDC2, (uint8_t) kTRDC2_MasterNETC, 0U, &netc);
TRDC_MrcSetMemoryAccessConfig(TRDC2, &netc_access, 3U, 7U);
TRDC_MrcSetMemoryAccessConfig(TRDC2, &netc_access, 4U, 7U);
TRDC_MrcSetMemoryAccessConfig(TRDC2, &cpu_access, 6U, 7U);
hal_netc_trdc_region(3U, 10U, 0x20480000UL, 0x204FFFFFUL);
hal_netc_trdc_region(4U, 10U, 0x20500000UL, 0x2053FFFFUL);
hal_netc_trdc_region(6U, 2U, 0x60000000UL, 0x60FFFFFFUL);
}
static inline void hal_netc_pins_init(void) {
static const struct {
uint16_t index;
uint8_t af;
} muxes[] = {
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_00, 4U}, // RX_CLK
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_01, 4U}, // RX_DATA_2
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_02, 4U}, // RX_DATA_3
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_03, 4U}, // TX_DATA_2
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_04, 4U}, // TX_DATA_3
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_05, 3U}, // TX_DATA_0
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_06, 3U}, // TX_DATA_1
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_07, 3U}, // TX_EN
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_08, 3U}, // TX_CLK
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_09, 3U}, // RX_DATA_0
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_10, 3U}, // RX_DATA_1
{kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_B2_11, 3U}, // RX_EN
};
static const struct {
uint16_t index;
uint8_t input;
} inputs[] = {
{kIOMUXC_NETC_PINMUX_IPP_IND_ETH0_RX_CLK_SELECT_INPUT, 0U},
{kIOMUXC_NETC_PINMUX_IPP_IND_ETH0_RX_DV_SELECT_INPUT, 1U},
{kIOMUXC_NETC_PINMUX_IPP_IND_ETH0_RXD_SELECT_INPUT_0, 1U},
{kIOMUXC_NETC_PINMUX_IPP_IND_ETH0_RXD_SELECT_INPUT_1, 1U},
{kIOMUXC_NETC_PINMUX_IPP_IND_ETH0_RXD_SELECT_INPUT_2, 0U},
{kIOMUXC_NETC_PINMUX_IPP_IND_ETH0_RXD_SELECT_INPUT_3, 0U},
{kIOMUXC_NETC_PINMUX_IPP_IND_ETH0_TX_CLK_SELECT_INPUT, 1U},
};
CLOCK_EnableClock(kCLOCK_Iomuxc1);
CLOCK_EnableClock(kCLOCK_Iomuxc2);
hal_gpio_output(HAL_NETC_PHY0_RESET);
hal_gpio_write(HAL_NETC_PHY0_RESET, true);
hal_gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_30, 7U); // EMDC
hal_gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_30,
HAL_GPIO_OTYPE_PUSH_PULL, HAL_GPIO_SPEED_HIGH,
HAL_GPIO_PULL_DOWN);
hal_gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_31, 7U); // EMDIO
hal_gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_31,
HAL_GPIO_OTYPE_OPEN_DRAIN, HAL_GPIO_SPEED_HIGH,
HAL_GPIO_PULL_DOWN);
hal_periph_mux_config(kIOMUXC_NETC_EMDIO_IN_SELECT_INPUT, 4U);
for (size_t i = 0; i < sizeof(muxes) / sizeof(muxes[0]); i++) {
hal_gpio_mux_config(muxes[i].index, muxes[i].af);
}
for (size_t i = 0; i < sizeof(inputs) / sizeof(inputs[0]); i++) {
hal_periph_mux_config(inputs[i].index, inputs[i].input);
}
}
static inline bool hal_netc_ierb_init(void) {
uint32_t timeout = 1000000UL;
BLK_CTRL_WAKEUPMIX->NETC_LINK_CFG[0] =
(BLK_CTRL_WAKEUPMIX->NETC_LINK_CFG[0] &
~BLK_CTRL_WAKEUPMIX_NETC_LINK_CFG_MII_PROT_MASK) |
BLK_CTRL_WAKEUPMIX_NETC_LINK_CFG_MII_PROT(2U);
if ((NETC_PRIV->NETCRR & NETC_PRIV_NETCRR_LOCK_MASK) != 0U) {
NETC_PRIV->NETCRR &= ~NETC_PRIV_NETCRR_LOCK_MASK;
while ((NETC_PRIV->NETCRR & NETC_PRIV_NETCRR_LOCK_MASK) != 0U &&
timeout > 0U) {
timeout--;
}
if ((NETC_PRIV->NETCRR & NETC_PRIV_NETCRR_LOCK_MASK) != 0U) return false;
}
// Attribute 1 permits MSI-X writes through the root-complex window.
NETC_IERB->ARRAY_NUM_RC[0].RCMSIAMQR =
(NETC_IERB->ARRAY_NUM_RC[0].RCMSIAMQR & ~(7UL << 27)) | (1UL << 27);
// RT1180's SoC-specific topology fixes link 0 to switch port 0, link 4 to
// ENETC0, and link 5 between switch port 4 and ENETC1.
NETC_IERB->L0BCR =
NETC_IERB_L0BCR_MDIO_PHYAD_PRTAD(HAL_NETC_PHY0_ADDR);
__DSB();
if ((NETC_PRIV->NETCSR & NETC_PRIV_NETCSR_ERROR_MASK) != 0U) return false;
NETC_PRIV->NETCRR |= NETC_PRIV_NETCRR_LOCK_MASK;
timeout = 1000000UL;
while ((NETC_PRIV->NETCSR & NETC_PRIV_NETCSR_STATE_MASK) != 0U &&
timeout > 0U) {
timeout--;
}
return (NETC_PRIV->NETCSR &
(NETC_PRIV_NETCSR_STATE_MASK | NETC_PRIV_NETCSR_ERROR_MASK)) == 0U;
}
static inline void hal_ethernet_init(void) {
hal_netc_trdc_init();
CLOCK_EnableClock(kCLOCK_Netc);
hal_netc_pins_init();
if (!hal_netc_ierb_init()) return;
hal_gpio_write(HAL_NETC_PHY0_RESET, false);
SDK_DelayAtLeastUs(10000U, SYS_FREQUENCY);
hal_gpio_write(HAL_NETC_PHY0_RESET, true);
SDK_DelayAtLeastUs(150000U, SYS_FREQUENCY);
NVIC_EnableIRQ(MSGINTR1_IRQn);
}
static inline void hal_rng_init(void) {
}
static inline uint32_t hal_rng_read(void) {
return 42;
}
@@ -0,0 +1,64 @@
ENTRY(Reset_Handler)
MEMORY {
boot_hdr (rx) : ORIGIN = 0x04000000, LENGTH = 0x0000b000
flash_irq (rx) : ORIGIN = 0x0400b000, LENGTH = 0x00000400
flash (rx) : ORIGIN = 0x0400b400, LENGTH = 0x00ff4c00
itcm (rwx) : ORIGIN = 0x0ffe0000, LENGTH = 128k
dtcm (rwx) : ORIGIN = 0x20000000, LENGTH = 128k
ocram1 (rw) : ORIGIN = 0x204c0000, LENGTH = 256k
}
__StackSize = 4k;
__StackTop = ORIGIN(dtcm) + LENGTH(dtcm);
__StackLimit = __StackTop - __StackSize;
SECTIONS {
.boot_hdr : {
FILL(0x00)
. = 0x0400; KEEP(*(.boot_hdr.conf))
. = 0x0800; KEEP(*(.boot_hdr.xmcd_data))
. = 0x1000; __boot_hdr_container__ = ABSOLUTE(.); KEEP(*(.boot_hdr.container))
. = 0xb000;
} > boot_hdr
.isr_vector ALIGN(1024) : { KEEP(*(.isr_vector)) } > flash_irq
.text : { *(.text .text.*) *(.rodata .rodata.*) *(.constdata .constdata.*) } > flash
.iram : { _siram = .; *(.iram .iram.*) . = ALIGN(4); _eiram = .; } > itcm AT > flash
_siiram = LOADADDR(.iram);
.data : {
__data_start__ = .;
*(.data SORT(.data.*)) *(.sdata SORT(.sdata.*))
. = ALIGN(4);
__data_end__ = .;
} > dtcm AT > flash
__data_flash_start = LOADADDR(.data);
.bss (NOLOAD) : {
__bss_start__ = .;
*(.bss SORT(.bss.*)) *(.sbss SORT(.sbss.*)) *(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > dtcm
_end = ALIGN(8);
/* Required by startup only; hal.c manages the dynamic heap from _end. */
__HeapBase = _end;
__HeapLimit = _end;
.eth_ram (NOLOAD) : {
. = ALIGN(64);
__eth_ram_start__ = .;
*(.eth_ram .eth_ram.*)
. = ALIGN(64);
__eth_ram_end__ = .;
} > ocram1
_image_size = LOADADDR(.data) + SIZEOF(.data) - ADDR(.isr_vector);
_image_loadaddr = ADDR(.isr_vector);
_image_offset = ADDR(.isr_vector) - __boot_hdr_container__;
}
@@ -0,0 +1,74 @@
// Copyright (c) 2026 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
#include "hal.h"
#ifndef UART_DEBUG
#define UART_DEBUG LPUART1
#endif
#define LED1 PIN('2', 11) // User LED: GPIO_EMC_B1_11, RGPIO2.11
#define LED2 LED1
#define LED3 LED1
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(LED1);
}
}
uint64_t mg_millis(void) {
return hal_get_tick();
}
#if MG_ENABLE_CUSTOM_RANDOM
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;
}
#endif
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
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)) {
mg_http_reply(c, 200, "", "{%m:%llu}\n", MG_ESC("tick"), hal_get_tick());
} else {
mg_http_reply(c, 200, "", "Hi from Mongoose, tick %llu\n",
hal_get_tick());
}
}
}
int main(void) {
hal_clock_init();
hal_rng_init();
hal_gpio_output(LED1);
hal_gpio_output(LED2);
hal_gpio_output(LED3);
hal_uart_init(UART_DEBUG, 115200);
mg_log_set_fn(log_fn, UART_DEBUG);
hal_ethernet_init();
// Start a minimal web server
struct mg_mgr mgr;
mg_mgr_init(&mgr);
mg_http_listen(&mgr, "http://0.0.0.0", http_ev_handler, NULL);
for (;;) {
mg_mgr_poll(&mgr, 0);
blink_task();
}
return 0;
}
@@ -0,0 +1,21 @@
#define MG_ARCH MG_ARCH_ARMGCC
#define MG_ENABLE_TCPIP 1
#define MG_ENABLE_DRIVER_NETC 1
#define MG_OTA MG_OTA_RT1180
#define MG_IO_SIZE 256
#define MG_ENABLE_CUSTOM_MILLIS 1
#define MG_ETH_RAM __attribute__((section(".eth_ram")))
// For static IP configuration, define MG_TCPIP_{IP,MASK,GW}
// By default, those are set to zero, meaning that DHCP is used
//
// #define MG_TCPIP_IP MG_IPV4(192, 168, 0, 10)
// #define MG_TCPIP_GW MG_IPV4(192, 168, 0, 1)
// #define MG_TCPIP_MASK MG_IPV4(255, 255, 255, 0)
// Set custom MAC address. By default, it is randomly generated
// Using a build-time constant:
// #define MG_SET_MAC_ADDRESS(mac) do { mac[0] = 2; mac[1] = 3; mac[2] = 4; mac[3] = 5; mac[4] = 6; mac[5] = 7; } while (0)
//