mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-09 16:21:45 +00:00
Reorganized NXP examples
This commit is contained in:
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,
|
||||
},
|
||||
};
|
||||
@@ -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) {
|
||||
}
|
||||
@@ -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, ®ion);
|
||||
}
|
||||
|
||||
// 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)
|
||||
//
|
||||
Reference in new issue
Block a user