mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-29 12:41:03 +00:00
Add frdm-mcxw71 support
This commit is contained in:
1 parent
a6b6a0d779
commit
1ca4fd1fef
27 files changed
+4018
-19
No files matched your search
@@ -2,7 +2,7 @@
|
||||
|
||||
MGDIR = ../../../..
|
||||
|
||||
CFLAGS = -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion
|
||||
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
|
||||
@@ -10,9 +10,11 @@ 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 -lgcc -Wl,--gc-sections
|
||||
|
||||
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
|
||||
|
||||
@@ -2,6 +2,61 @@
|
||||
// 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) {
|
||||
|
||||
@@ -13,13 +13,18 @@
|
||||
#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
|
||||
|
||||
extern uint32_t SystemCoreClock; // CPU clock, Hz. Set by hal_clock_init()
|
||||
|
||||
// MRCC peripheral clock source, MRCC_xx[MUX], see fsl_clock.h
|
||||
enum { MRCC_SRC_FRO6M = 2, MRCC_SRC_FRO192M = 3 };
|
||||
|
||||
@@ -30,10 +35,43 @@ static inline uint32_t hal_firc_freq(void) {
|
||||
return freqs[SCG0->FIRCCFG & SCG_FIRCCFG_RANGE_MASK];
|
||||
}
|
||||
|
||||
// Work out the CPU clock from the SCG clock source and core divider. The
|
||||
// clock is left as configured at reset
|
||||
// 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 = SCG0->CSR, freq = 0;
|
||||
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
|
||||
@@ -108,7 +146,273 @@ static inline void hal_sys_init(void) {
|
||||
hal_wdog_disable();
|
||||
}
|
||||
|
||||
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);
|
||||
// 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},
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
/* MCXW716C memory map, see MCUXpresso SDK gcc/mcxw716_flash.ld */
|
||||
ENTRY(Reset_Handler);
|
||||
MEMORY {
|
||||
flash(rx) : ORIGIN = 0x00000000, LENGTH = 1024k
|
||||
flash(rx) : ORIGIN = 0x00000000, LENGTH = 512k /* Upper half: OTA staging */
|
||||
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 112k
|
||||
}
|
||||
__StackTop = ORIGIN(sram) + LENGTH(sram); /* Stack points here */
|
||||
@@ -16,6 +16,7 @@ SECTIONS {
|
||||
__data_start__ = .;
|
||||
_sdata = .;
|
||||
*(.first_data)
|
||||
*(.iram .iram.*) /* OTA flash operations, copied to RAM by startup */
|
||||
*(.data SORT(.data.*))
|
||||
. = ALIGN(4);
|
||||
__data_end__ = .;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
// 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"
|
||||
@@ -14,19 +19,71 @@ 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_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 (;;) {
|
||||
static uint64_t timer;
|
||||
if (hal_timer_expired(&timer, 1000, hal_get_tick())) {
|
||||
MG_INFO(("Hi from Mongoose, tick %llu", hal_get_tick()));
|
||||
}
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
mg_mqtt_poll(&mgr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
#pragma once
|
||||
#include "MCXW716C.h"
|
||||
|
||||
// See https://mongoose.ws/documentation/#build-options
|
||||
// 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 // Built-in TCP/IP stack. No network driver yet
|
||||
#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)
|
||||
Reference in new issue
Block a user