mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-18 10:59:45 +00:00
663 lines
23 KiB
C
663 lines
23 KiB
C
// 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;
|
|
}
|