summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOnlyoutzZ <[email protected]>2026-09-11 18:38:30 +0800
committerRbb666 <[email protected]>2026-09-16 09:06:34 +0800
commit97634bffe8cf66ba3be103e61aff266ec806fc63 (patch)
tree70093b659953cebf04ba860e3c4e15b73d26e21b
parent1d2152ceeefef23dba61e80d97f0f4e20d46dd05 (diff)
[bsp][n32] n32hxxx: extend H47x_48x/H49x/H7xx driver support
- libraries/N32_Drivers: add ADC/DAC/I2C/SPI config headers for the h47x_48x, h49x and h7xx series, and extend the shared drivers (adc, dac, eth, gpio, hard_i2c, nand, qspi, sdram, spi, usart, wdt). - n32h487zgl7-evb / n32h497zgl7-evb: add board ports (femc_timing, phy_reset, usb_config) and update Kconfig, SConscript, rtconfig and the IAR/Keil project files. - n32h760zil7-stb: update Kconfig and rtconfig. - CI: register the three n32hxxx boards.
-rw-r--r--.github/workflows/manual_trigger_scons_except_STM32_all.yml27
-rw-r--r--bsp/README.md4
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/adc_config.h68
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dac_config.h107
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dma_config.h180
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/i2c_hard_config.h204
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/spi_config.h254
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/adc_config.h62
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dac_config.h55
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dma_config.h2
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/i2c_hard_config.h204
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/spi_config.h254
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h7xx/dma_config.h5
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_adc.c210
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_config.h9
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_dac.c81
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.c56
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.h84
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.c89
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.h1
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.c1317
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.h9
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_nand.c370
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.c484
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.h26
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_sdram.c15
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.c1703
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.h47
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.c68
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.h20
-rw-r--r--bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_wdt.c36
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/.config30
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/Cube_Config.ntfxbin2621 -> 2672 bytes
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/USER/src/n32h47x_48x_cfg.c9
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/Kconfig359
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/SConscript1
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/SConscript6
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.c53
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.h34
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/phy_reset.c29
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/usb_config.h69
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/project.ewp11
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvoptx12
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvprojx12
-rw-r--r--bsp/n32/n32hxxx/n32h487zgl7-evb/rtconfig.h9
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/.config35
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/Cube_Config.ntfxbin3429 -> 3465 bytes
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/USER/src/n32h49x_cfg.c7
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/Kconfig440
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/SConscript5
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/board.h2
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/SConscript6
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.c53
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.h34
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/phy_reset.c29
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/usb_config.h69
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/project.ewp11
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvoptx4
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvprojx8
-rw-r--r--bsp/n32/n32hxxx/n32h497zgl7-evb/rtconfig.h10
-rw-r--r--bsp/n32/n32hxxx/n32h760zil7-stb/.config24
-rw-r--r--bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/Cube.ntfxbin4076 -> 5044 bytes
-rw-r--r--bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/USER/src/n32h7xx_cfg.c16
-rw-r--r--bsp/n32/n32hxxx/n32h760zil7-stb/board/Kconfig258
-rw-r--r--bsp/n32/n32hxxx/n32h760zil7-stb/project.uvoptx980
-rw-r--r--bsp/n32/n32hxxx/n32h760zil7-stb/project.uvprojx1551
-rw-r--r--bsp/n32/n32hxxx/n32h760zil7-stb/rtconfig.h11
-rw-r--r--tools/ci/bsp_detail.yml46
-rw-r--r--tools/ci/toolchain_bsp.yml29
69 files changed, 7560 insertions, 2753 deletions
diff --git a/.github/workflows/manual_trigger_scons_except_STM32_all.yml b/.github/workflows/manual_trigger_scons_except_STM32_all.yml
index 5e173eb76e..6b1debcda3 100644
--- a/.github/workflows/manual_trigger_scons_except_STM32_all.yml
+++ b/.github/workflows/manual_trigger_scons_except_STM32_all.yml
@@ -190,18 +190,21 @@ jobs:
#- {RTT_BSP_NAME: "mm32f327x", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "mm32f327x"} #编译问题
- {RTT_BSP_NAME: "mm32l07x", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "mm32l07x"}
- {RTT_BSP_NAME: "mm32l3xx", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "mm32l3xx"}
- - {RTT_BSP_NAME: "n32_n32g43xcl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32g43xcl-stb"}
- - {RTT_BSP_NAME: "n32_n32g457qel-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32g457qel-stb"}
- - {RTT_BSP_NAME: "n32_n32g45xcl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32g45xcl-stb"}
- - {RTT_BSP_NAME: "n32_n32g45xml-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32g45xml-stb"}
- - {RTT_BSP_NAME: "n32_n32g45xrl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32g45xrl-stb"}
- - {RTT_BSP_NAME: "n32_n32g45xvl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32g45xvl-stb"}
- - {RTT_BSP_NAME: "n32_n32g4frml-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32g4frml-stb"}
- - {RTT_BSP_NAME: "n32_n32l40xcl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32l40xcl-stb"}
- - {RTT_BSP_NAME: "n32_n32l436-evb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32l436-evb"}
- - {RTT_BSP_NAME: "n32_n32l43xml-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32l43xml-stb"}
- - {RTT_BSP_NAME: "n32_n32l43xrl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32l43xrl-stb"}
- - {RTT_BSP_NAME: "n32_n32wb45xl-evb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32wb45xl-evb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32g43xcl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32g43xcl-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32g457qel-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32g457qel-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32g45xcl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32g45xcl-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32g45xml-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32g45xml-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32g45xrl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32g45xrl-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32g45xvl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32g45xvl-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32g4frml-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32g4frml-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32l40xcl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32l40xcl-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32l436-evb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32l436-evb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32l43xml-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32l43xml-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32l43xrl-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32l43xrl-stb"}
+ - {RTT_BSP_NAME: "n32_n32gxx_lxx_n32wb45xl-evb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32gxx_lxx/n32wb45xl-evb"}
+ - {RTT_BSP_NAME: "n32_n32hxxx_n32h487zgl7-evb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32hxxx/n32h487zgl7-evb"}
+ - {RTT_BSP_NAME: "n32_n32hxxx_n32h497zgl7-evb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32hxxx/n32h497zgl7-evb"}
+ - {RTT_BSP_NAME: "n32_n32hxxx_n32h760zil7-stb", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32/n32hxxx/n32h760zil7-stb"}
- {RTT_BSP_NAME: "n32g452xx_n32g452xx-mini-system", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "n32g452xx/n32g452xx-mini-system"}
#- {RTT_BSP_NAME: "nios_ii", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "nios_ii"} #编译问题
- {RTT_BSP_NAME: "nrf5x_nrf51822", RTT_TOOL_CHAIN: "sourcery-arm", RTT_BSP: "nrf5x/nrf51822"}
diff --git a/bsp/README.md b/bsp/README.md
index 848df098e2..e4fed6f96a 100644
--- a/bsp/README.md
+++ b/bsp/README.md
@@ -334,8 +334,8 @@ This document is based on the RT-Thread mainline repository and categorizes the
| [n32l43xrl-stb](n32/n32gxx_lxx/n32l43xrl-stb) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | - | - | - | - | - | - | - | - | - |
| [n32wb45xl-evb](n32/n32gxx_lxx/n32wb45xl-evb) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | - | - | - | - | - | - | - | - | - |
| [n32h760zil7-stb](n32/n32hxxx/n32h760zil7-stb) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| [n32h497zgl7-evb](n32/n32hxxx/n32h497zgl7-evb) | ✅ | ✅ | - | ✅ | - | - | - | ✅ | - | - | - | - | - | - | - | ✅ | - | - | - |
-| [n32h487zgl7-evb](n32/n32hxxx/n32h487zgl7-evb) | ✅ | ✅ | - | ✅ | - | - | - | ✅ | - | - | - | - | - | - | - | ✅ | - | - | - |
+| [n32h497zgl7-evb](n32/n32hxxx/n32h497zgl7-evb) | ✅ | ✅ | ✅ | ✅ | ✅ | - | ✅ | ✅ | ✅ | ✅ | - | - | - | ✅ | ✅ | ✅ | ✅ | - | ✅ |
+| [n32h487zgl7-evb](n32/n32hxxx/n32h487zgl7-evb) | ✅ | ✅ | ✅ | ✅ | ✅ | - | ✅ | ✅ | ✅ | ✅ | - | - | - | ✅ | ✅ | ✅ | - | - | ✅ |
#### 🟡 NRF5x
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/adc_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/adc_config.h
new file mode 100644
index 0000000000..d8a29195ae
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/adc_config.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-28 FUNMSAN first version
+ */
+
+#ifndef __ADC_CONFIG_H__
+#define __ADC_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define N32H47X_48X_ADC_CONFIG(ADC_INSTANCE, ADC_PERIPH) \
+ { \
+ .ADCx = ADC_INSTANCE, \
+ .AHB_periph = ADC_PERIPH, \
+ .EnablePeriphClk = RCC_EnableAHB1PeriphClk, \
+ .ADC_ClkMode = ADC_CTRL3_CKMOD_AHB, \
+ .RCC_ADCPrescaler = RCC_ADCHCLK_DIV16, \
+ .ADC1M_ClkSource = RCC_ADC1MCLK_SRC_HSI, \
+ .ADC1M_ClkPrescaler = RCC_ADC1MCLK_DIV8, \
+ .Rank = 1U, \
+ .ADC_SampleTime = ADC_SAMP_TIME_CYCLES_239_5, \
+ .Init.WorkMode = ADC_WORKMODE_INDEPENDENT, \
+ .Init.MultiChEn = DISABLE, \
+ .Init.ContinueConvEn = DISABLE, \
+ .Init.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE, \
+ .Init.DatAlign = ADC_DAT_ALIGN_R, \
+ .Init.ChsNumber = 1U, \
+ .Init.Resolution = ADC_DATA_RES_12BIT, \
+ }
+
+#ifdef BSP_USING_ADC1
+#ifndef ADC1_CONFIG
+#define ADC1_CONFIG N32H47X_48X_ADC_CONFIG(ADC1, RCC_AHB_PERIPHEN_ADC1)
+#endif /* ADC1_CONFIG */
+#endif /* BSP_USING_ADC1 */
+
+#ifdef BSP_USING_ADC2
+#ifndef ADC2_CONFIG
+#define ADC2_CONFIG N32H47X_48X_ADC_CONFIG(ADC2, RCC_AHB_PERIPHEN_ADC2)
+#endif /* ADC2_CONFIG */
+#endif /* BSP_USING_ADC2 */
+
+#ifdef BSP_USING_ADC3
+#ifndef ADC3_CONFIG
+#define ADC3_CONFIG N32H47X_48X_ADC_CONFIG(ADC3, RCC_AHB_PERIPHEN_ADC3)
+#endif /* ADC3_CONFIG */
+#endif /* BSP_USING_ADC3 */
+
+#ifdef BSP_USING_ADC4
+#ifndef ADC4_CONFIG
+#define ADC4_CONFIG N32H47X_48X_ADC_CONFIG(ADC4, RCC_AHB_PERIPHEN_ADC4)
+#endif /* ADC4_CONFIG */
+#endif /* BSP_USING_ADC4 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ADC_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dac_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dac_config.h
new file mode 100644
index 0000000000..eec6279a70
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dac_config.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-28 FUNMSAN first version
+ */
+
+#ifndef __DAC_CONFIG_H__
+#define __DAC_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(N32H473) || defined(N32H474)
+#define N32H47X_48X_DAC1234_CLK_PRESCALER 100U
+#else
+#define N32H47X_48X_DAC1234_CLK_PRESCALER 120U
+#endif
+
+#define N32H47X_48X_DAC5678_CLK_PRESCALER 16U
+
+#define N32H47X_48X_DAC_CONFIG(DAC_INSTANCE, DAC_MODULE, DAC_PERIPH, CLK_ENABLE, CLK_PRESCALER) \
+ { \
+ .DACx = DAC_INSTANCE, \
+ .DAC_Module = DAC_MODULE, \
+ .periph_clk = DAC_PERIPH, \
+ .EnablePeriphClk = CLK_ENABLE, \
+ .DAC_clk_pres = CLK_PRESCALER, \
+ .Init.DAC_Trigger = DAC_Trigger_Software, \
+ .Init.DAC_Trigger2 = DAC_Trigger2_Software, \
+ .Init.DAC_WaveGeneration = DAC_WaveGeneration_None, \
+ .Init.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0, \
+ .Init.DAC_OutputBuffer = DISABLE, \
+ .Init.DAC_TriggerEnable = ENABLE, \
+ .Init.DAC_ConnectOnChipPeripheral = DISABLE, \
+ .Init.DAC_ConnectExternalPin = ENABLE, \
+ .Init.DAC_DMADoubleDataMode = DISABLE, \
+ .Init.DAC_SignedFormat = DISABLE, \
+ }
+
+#ifdef BSP_USING_DAC1
+#ifndef DAC1_CONFIG
+#define DAC1_CONFIG N32H47X_48X_DAC_CONFIG(DAC1, DAC12, RCC_APB1_PERIPH_DAC12, \
+ RCC_EnableAPB1PeriphClk, N32H47X_48X_DAC1234_CLK_PRESCALER)
+#endif /* DAC1_CONFIG */
+#endif /* BSP_USING_DAC1 */
+
+#ifdef BSP_USING_DAC2
+#ifndef DAC2_CONFIG
+#define DAC2_CONFIG N32H47X_48X_DAC_CONFIG(DAC2, DAC12, RCC_APB1_PERIPH_DAC12, \
+ RCC_EnableAPB1PeriphClk, N32H47X_48X_DAC1234_CLK_PRESCALER)
+#endif /* DAC2_CONFIG */
+#endif /* BSP_USING_DAC2 */
+
+#ifdef BSP_USING_DAC3
+#ifndef DAC3_CONFIG
+#define DAC3_CONFIG N32H47X_48X_DAC_CONFIG(DAC3, DAC34, RCC_APB1_PERIPH_DAC34, \
+ RCC_EnableAPB1PeriphClk, N32H47X_48X_DAC1234_CLK_PRESCALER)
+#endif /* DAC3_CONFIG */
+#endif /* BSP_USING_DAC3 */
+
+#ifdef BSP_USING_DAC4
+#ifndef DAC4_CONFIG
+#define DAC4_CONFIG N32H47X_48X_DAC_CONFIG(DAC4, DAC34, RCC_APB1_PERIPH_DAC34, \
+ RCC_EnableAPB1PeriphClk, N32H47X_48X_DAC1234_CLK_PRESCALER)
+#endif /* DAC4_CONFIG */
+#endif /* BSP_USING_DAC4 */
+
+#ifdef BSP_USING_DAC5
+#ifndef DAC5_CONFIG
+#define DAC5_CONFIG N32H47X_48X_DAC_CONFIG(DAC5, DAC56, RCC_AHB_PERIPHEN_DAC56, \
+ RCC_EnableAHBPeriphClk, N32H47X_48X_DAC5678_CLK_PRESCALER)
+#endif /* DAC5_CONFIG */
+#endif /* BSP_USING_DAC5 */
+
+#ifdef BSP_USING_DAC6
+#ifndef DAC6_CONFIG
+#define DAC6_CONFIG N32H47X_48X_DAC_CONFIG(DAC6, DAC56, RCC_AHB_PERIPHEN_DAC56, \
+ RCC_EnableAHBPeriphClk, N32H47X_48X_DAC5678_CLK_PRESCALER)
+#endif /* DAC6_CONFIG */
+#endif /* BSP_USING_DAC6 */
+
+#ifdef BSP_USING_DAC7
+#ifndef DAC7_CONFIG
+#define DAC7_CONFIG N32H47X_48X_DAC_CONFIG(DAC7, DAC78, RCC_AHB_PERIPHEN_DAC78, \
+ RCC_EnableAHBPeriphClk, N32H47X_48X_DAC5678_CLK_PRESCALER)
+#endif /* DAC7_CONFIG */
+#endif /* BSP_USING_DAC7 */
+
+#ifdef BSP_USING_DAC8
+#ifndef DAC8_CONFIG
+#define DAC8_CONFIG N32H47X_48X_DAC_CONFIG(DAC8, DAC78, RCC_AHB_PERIPHEN_DAC78, \
+ RCC_EnableAHBPeriphClk, N32H47X_48X_DAC5678_CLK_PRESCALER)
+#endif /* DAC8_CONFIG */
+#endif /* BSP_USING_DAC8 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DAC_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dma_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dma_config.h
index f14ac09485..f42203ba24 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dma_config.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/dma_config.h
@@ -37,6 +37,14 @@ extern "C" {
#define UART2_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
#define UART2_RX_DMA_REQUEST DMA_REMAP_USART2_RX
#define UART2_RX_DMA_CHANNEL 2U
+#elif defined(BSP_I2C2_RX_USING_DMA) && !defined(I2C2_RX_DMA)
+#define I2C2_RX_DMA DMA1
+#define I2C2_RX_DMA_IRQHandler DMA1_Channel2_IRQHandler
+#define I2C2_RX_DMA_CHType DMA1_CH2
+#define I2C2_RX_DMA_IRQ DMA1_Channel2_IRQn
+#define I2C2_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define I2C2_RX_DMA_REQUEST DMA_REMAP_I2C2_RX
+#define I2C2_RX_DMA_CHANNEL 2U
#endif
/* DMA1 channel3 */
@@ -48,6 +56,14 @@ extern "C" {
#define UART3_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
#define UART3_RX_DMA_REQUEST DMA_REMAP_USART3_RX
#define UART3_RX_DMA_CHANNEL 3U
+#elif defined(BSP_I2C3_RX_USING_DMA) && !defined(I2C3_RX_DMA)
+#define I2C3_RX_DMA DMA1
+#define I2C3_RX_DMA_IRQHandler DMA1_Channel3_IRQHandler
+#define I2C3_RX_DMA_CHType DMA1_CH3
+#define I2C3_RX_DMA_IRQ DMA1_Channel3_IRQn
+#define I2C3_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define I2C3_RX_DMA_REQUEST DMA_REMAP_I2C3_RX
+#define I2C3_RX_DMA_CHANNEL 3U
#endif
/* DMA1 channel4 */
@@ -59,6 +75,22 @@ extern "C" {
#define UART4_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
#define UART4_RX_DMA_REQUEST DMA_REMAP_USART4_RX
#define UART4_RX_DMA_CHANNEL 4U
+#elif defined(BSP_SPI6_RX_USING_DMA) && !defined(SPI6_RX_DMA)
+#define SPI6_RX_DMA DMA1
+#define SPI6_RX_DMA_IRQHandler DMA1_Channel4_IRQHandler
+#define SPI6_RX_DMA_CHType DMA1_CH4
+#define SPI6_RX_DMA_IRQ DMA1_Channel4_IRQn
+#define SPI6_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define SPI6_RX_DMA_REQUEST DMA_REMAP_SPI6_RX
+#define SPI6_RX_DMA_CHANNEL 4U
+#elif defined(BSP_I2C4_RX_USING_DMA) && !defined(I2C4_RX_DMA)
+#define I2C4_RX_DMA DMA1
+#define I2C4_RX_DMA_IRQHandler DMA1_Channel4_IRQHandler
+#define I2C4_RX_DMA_CHType DMA1_CH4
+#define I2C4_RX_DMA_IRQ DMA1_Channel4_IRQn
+#define I2C4_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define I2C4_RX_DMA_REQUEST DMA_REMAP_I2C4_RX
+#define I2C4_RX_DMA_CHANNEL 4U
#endif
/* DMA1 channel5 */
@@ -70,6 +102,14 @@ extern "C" {
#define UART5_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
#define UART5_RX_DMA_REQUEST DMA_REMAP_UART5_RX
#define UART5_RX_DMA_CHANNEL 5U
+#elif defined(BSP_SPI5_RX_USING_DMA) && !defined(SPI5_RX_DMA)
+#define SPI5_RX_DMA DMA1
+#define SPI5_RX_DMA_IRQHandler DMA1_Channel5_IRQHandler
+#define SPI5_RX_DMA_CHType DMA1_CH5
+#define SPI5_RX_DMA_IRQ DMA1_Channel5_IRQn
+#define SPI5_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define SPI5_RX_DMA_REQUEST DMA_REMAP_SPI5_RX
+#define SPI5_RX_DMA_CHANNEL 5U
#endif
/* DMA1 channel6 */
@@ -81,6 +121,29 @@ extern "C" {
#define UART6_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
#define UART6_RX_DMA_REQUEST DMA_REMAP_UART6_RX
#define UART6_RX_DMA_CHANNEL 6U
+#elif defined(BSP_SPI4_RX_USING_DMA) && !defined(SPI4_RX_DMA)
+#define SPI4_RX_DMA DMA1
+#define SPI4_RX_DMA_IRQHandler DMA1_Channel6_IRQHandler
+#define SPI4_RX_DMA_CHType DMA1_CH6
+#define SPI4_RX_DMA_IRQ DMA1_Channel6_IRQn
+#define SPI4_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define SPI4_RX_DMA_REQUEST DMA_REMAP_SPI4_RX
+#define SPI4_RX_DMA_CHANNEL 6U
+#elif defined(BSP_USING_SDIO)
+#define SDIO_RX_DMA DMA1
+#define SDIO_TX_DMA DMA1
+#define SDIO_RX_TX_DMA_IRQHandler DMA1_Channel6_IRQHandler
+#define SDIO_TX_DMA_CHType DMA1_CH6
+#define SDIO_RX_DMA_CHType DMA1_CH6
+#define SDIO_TX_DMA_IRQ DMA1_Channel6_IRQn
+#define SDIO_RX_DMA_IRQ DMA1_Channel6_IRQn
+#define SDIO_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define SDIO_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define SDIO_TX_DMA_REQUEST DMA_REMAP_SDIO_DMA
+#define SDIO_RX_DMA_REQUEST DMA_REMAP_SDIO_DMA
+
+#define SDIO_TX_DMA_CHANNEL 6U
+#define SDIO_RX_DMA_CHANNEL 6U
#endif
/* DMA1 channel7 */
@@ -92,6 +155,14 @@ extern "C" {
#define UART7_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
#define UART7_RX_DMA_REQUEST DMA_REMAP_UART7_RX
#define UART7_RX_DMA_CHANNEL 7U
+#elif defined(BSP_SPI3_RX_USING_DMA) && !defined(SPI3_RX_DMA)
+#define SPI3_RX_DMA DMA1
+#define SPI3_RX_DMA_IRQHandler DMA1_Channel7_IRQHandler
+#define SPI3_RX_DMA_CHType DMA1_CH7
+#define SPI3_RX_DMA_IRQ DMA1_Channel7_IRQn
+#define SPI3_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define SPI3_RX_DMA_REQUEST DMA_REMAP_SPI3_I2S3_RX
+#define SPI3_RX_DMA_CHANNEL 7U
#endif
/* DMA1 channel8 */
@@ -103,6 +174,15 @@ extern "C" {
#define UART8_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
#define UART8_RX_DMA_REQUEST DMA_REMAP_UART8_RX
#define UART8_RX_DMA_CHANNEL 8U
+#elif defined(BSP_SPI2_RX_USING_DMA) && !defined(SPI2_RX_DMA)
+#define SPI2_RX_DMA DMA1
+#define SPI2_RX_DMA_IRQHandler DMA1_Channel8_IRQHandler
+#define SPI2_RX_DMA_CHType DMA1_CH8
+#define SPI2_RX_DMA_IRQ DMA1_Channel8_IRQn
+#define SPI2_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA1
+#define SPI2_RX_DMA_REQUEST DMA_REMAP_SPI2_I2S2_RX
+#define SPI2_RX_DMA_CHANNEL 8U
+
#endif
/* DMA2 channel1 */
@@ -114,6 +194,22 @@ extern "C" {
#define UART1_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART1_TX_DMA_REQUEST DMA_REMAP_USART1_TX
#define UART1_TX_DMA_CHANNEL 1U
+#elif defined(BSP_SPI1_RX_USING_DMA) && !defined(SPI1_RX_DMA)
+#define SPI1_RX_DMA DMA2
+#define SPI1_RX_DMA_IRQHandler DMA2_Channel1_IRQHandler
+#define SPI1_RX_DMA_CHType DMA2_CH1
+#define SPI1_RX_DMA_IRQ DMA2_Channel1_IRQn
+#define SPI1_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define SPI1_RX_DMA_REQUEST DMA_REMAP_SPI1_RX
+#define SPI1_RX_DMA_CHANNEL 1U
+#elif defined(BSP_I2C1_RX_USING_DMA) && !defined(I2C1_RX_DMA)
+#define I2C1_RX_DMA DMA2
+#define I2C1_RX_DMA_IRQHandler DMA2_Channel1_IRQHandler
+#define I2C1_RX_DMA_CHType DMA2_CH1
+#define I2C1_RX_DMA_IRQ DMA2_Channel1_IRQn
+#define I2C1_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define I2C1_RX_DMA_REQUEST DMA_REMAP_I2C1_RX
+#define I2C1_RX_DMA_CHANNEL 1U
#endif
/* DMA2 channel2 */
@@ -125,17 +221,34 @@ extern "C" {
#define UART2_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART2_TX_DMA_REQUEST DMA_REMAP_USART2_TX
#define UART2_TX_DMA_CHANNEL 2U
+
#endif
/* DMA2 channel3 */
#if defined(BSP_UART3_TX_USING_DMA) && !defined(UART3_TX_DMA)
#define UART3_TX_DMA DMA2
-#define I2C10_RX_DMA_IRQHandler DMA2_Channel3_IRQHandler
+#define UART3_TX_DMA_IRQHandler DMA2_Channel3_IRQHandler
#define UART3_TX_DMA_CHType DMA2_CH3
#define UART3_TX_DMA_IRQ DMA2_Channel3_IRQn
#define UART3_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART3_TX_DMA_REQUEST DMA_REMAP_USART3_TX
#define UART3_TX_DMA_CHANNEL 3U
+#elif defined(BSP_SPI6_TX_USING_DMA) && !defined(SPI6_TX_DMA)
+#define SPI6_TX_DMA DMA2
+#define SPI6_TX_DMA_IRQHandler DMA2_Channel3_IRQHandler
+#define SPI6_TX_DMA_CHType DMA2_CH3
+#define SPI6_TX_DMA_IRQ DMA2_Channel3_IRQn
+#define SPI6_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define SPI6_TX_DMA_REQUEST DMA_REMAP_SPI6_TX
+#define SPI6_TX_DMA_CHANNEL 3U
+#elif defined(BSP_I2C1_TX_USING_DMA) && !defined(I2C1_TX_DMA)
+#define I2C1_TX_DMA DMA2
+#define I2C1_TX_DMA_IRQHandler DMA2_Channel3_IRQHandler
+#define I2C1_TX_DMA_CHType DMA2_CH3
+#define I2C1_TX_DMA_IRQ DMA2_Channel3_IRQn
+#define I2C1_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define I2C1_TX_DMA_REQUEST DMA_REMAP_I2C1_TX
+#define I2C1_TX_DMA_CHANNEL 3U
#endif
/* DMA2 channel4 */
@@ -147,6 +260,14 @@ extern "C" {
#define UART4_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART4_TX_DMA_REQUEST DMA_REMAP_USART4_TX
#define UART4_TX_DMA_CHANNEL 4U
+#elif defined(BSP_SPI5_TX_USING_DMA) && !defined(SPI5_TX_DMA)
+#define SPI5_TX_DMA DMA2
+#define SPI5_TX_DMA_IRQHandler DMA2_Channel4_IRQHandler
+#define SPI5_TX_DMA_CHType DMA2_CH4
+#define SPI5_TX_DMA_IRQ DMA2_Channel4_IRQn
+#define SPI5_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define SPI5_TX_DMA_REQUEST DMA_REMAP_SPI5_TX
+#define SPI5_TX_DMA_CHANNEL 4U
#endif
/* DMA2 channel5 */
@@ -158,6 +279,22 @@ extern "C" {
#define UART5_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART5_TX_DMA_REQUEST DMA_REMAP_UART5_TX
#define UART5_TX_DMA_CHANNEL 5U
+#elif defined(BSP_SPI4_TX_USING_DMA) && !defined(SPI4_TX_DMA)
+#define SPI4_TX_DMA DMA2
+#define SPI4_TX_DMA_IRQHandler DMA2_Channel5_IRQHandler
+#define SPI4_TX_DMA_CHType DMA2_CH5
+#define SPI4_TX_DMA_IRQ DMA2_Channel5_IRQn
+#define SPI4_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define SPI4_TX_DMA_REQUEST DMA_REMAP_SPI4_TX
+#define SPI4_TX_DMA_CHANNEL 5U
+#elif defined(BSP_I2C2_TX_USING_DMA) && !defined(I2C2_TX_DMA)
+#define I2C2_TX_DMA DMA2
+#define I2C2_TX_DMA_IRQHandler DMA2_Channel5_IRQHandler
+#define I2C2_TX_DMA_CHType DMA2_CH5
+#define I2C2_TX_DMA_IRQ DMA2_Channel5_IRQn
+#define I2C2_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define I2C2_TX_DMA_REQUEST DMA_REMAP_I2C2_TX
+#define I2C2_TX_DMA_CHANNEL 5U
#endif
/* DMA2 channel6 */
@@ -169,6 +306,23 @@ extern "C" {
#define UART6_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART6_TX_DMA_REQUEST DMA_REMAP_UART6_TX
#define UART6_TX_DMA_CHANNEL 6U
+#elif defined(BSP_SPI3_TX_USING_DMA) && !defined(SPI3_TX_DMA)
+#define SPI3_TX_DMA DMA2
+#define SPI3_TX_DMA_IRQHandler DMA2_Channel6_IRQHandler
+#define SPI3_TX_DMA_CHType DMA2_CH6
+#define SPI3_TX_DMA_IRQ DMA2_Channel6_IRQn
+#define SPI3_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define SPI3_TX_DMA_REQUEST DMA_REMAP_SPI3_I2S3_TX
+#define SPI3_TX_DMA_CHANNEL 6U
+#elif defined(BSP_I2C3_TX_USING_DMA) && !defined(I2C3_TX_DMA)
+#define I2C3_TX_DMA DMA2
+#define I2C3_TX_DMA_IRQHandler DMA2_Channel6_IRQHandler
+#define I2C3_TX_DMA_CHType DMA2_CH6
+#define I2C3_TX_DMA_IRQ DMA2_Channel6_IRQn
+#define I2C3_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define I2C3_TX_DMA_REQUEST DMA_REMAP_I2C3_TX
+#define I2C3_TX_DMA_CHANNEL 6U
+
#endif
/* DMA2 channel7 */
@@ -180,6 +334,22 @@ extern "C" {
#define UART7_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART7_TX_DMA_REQUEST DMA_REMAP_UART7_TX
#define UART7_TX_DMA_CHANNEL 7U
+#elif defined(BSP_SPI2_TX_USING_DMA) && !defined(SPI2_TX_DMA)
+#define SPI2_TX_DMA DMA2
+#define SPI2_TX_DMA_IRQHandler DMA2_Channel7_IRQHandler
+#define SPI2_TX_DMA_CHType DMA2_CH7
+#define SPI2_TX_DMA_IRQ DMA2_Channel7_IRQn
+#define SPI2_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define SPI2_TX_DMA_REQUEST DMA_REMAP_SPI2_I2S2_TX
+#define SPI2_TX_DMA_CHANNEL 7U
+#elif defined(BSP_I2C4_TX_USING_DMA) && !defined(I2C4_TX_DMA)
+#define I2C4_TX_DMA DMA2
+#define I2C4_TX_DMA_IRQHandler DMA2_Channel7_IRQHandler
+#define I2C4_TX_DMA_CHType DMA2_CH7
+#define I2C4_TX_DMA_IRQ DMA2_Channel7_IRQn
+#define I2C4_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define I2C4_TX_DMA_REQUEST DMA_REMAP_I2C4_TX
+#define I2C4_TX_DMA_CHANNEL 7U
#endif
/* DMA2 channel8 */
@@ -191,6 +361,14 @@ extern "C" {
#define UART8_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART8_TX_DMA_REQUEST DMA_REMAP_UART8_TX
#define UART8_TX_DMA_CHANNEL 8U
+#elif defined(BSP_SPI1_TX_USING_DMA) && !defined(SPI1_TX_DMA)
+#define SPI1_TX_DMA DMA2
+#define SPI1_TX_DMA_IRQHandler DMA2_Channel8_IRQHandler
+#define SPI1_TX_DMA_CHType DMA2_CH8
+#define SPI1_TX_DMA_IRQ DMA2_Channel8_IRQn
+#define SPI1_TX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
+#define SPI1_TX_DMA_REQUEST DMA_REMAP_SPI1_TX
+#define SPI1_TX_DMA_CHANNEL 8U
#endif
#ifdef __cplusplus
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/i2c_hard_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/i2c_hard_config.h
new file mode 100644
index 0000000000..f82c7cb160
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/i2c_hard_config.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-01-24 ox-horse first version
+ */
+
+#ifndef __I2C_HARD_CONFIG_H__
+#define __I2C_HARD_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef BSP_USING_HARD_I2C1
+#ifndef I2C1_BUS_CONFIG
+#define I2C1_BUS_CONFIG \
+ { \
+ .name = "hwi2c1", \
+ .Instance = I2C1, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C1_EV_IRQn, \
+ .erirq_type = I2C1_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPH_I2C1, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C1_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C1 */
+#ifdef BSP_I2C1_RX_USING_DMA
+#ifndef I2C1_RX_DMA_CONFIG
+#define I2C1_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C1_RX_DMA, \
+ .DMAChx = I2C1_RX_DMA_CHType, \
+ .dma_irq = I2C1_RX_DMA_IRQ, \
+ .dma_rcc = I2C1_RX_DMA_RCC, \
+ .request = I2C1_RX_DMA_REQUEST, \
+ .channel = I2C1_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C1_RX_DMA_CONFIG */
+#endif /* BSP_I2C1_RX_USING_DMA */
+#ifdef BSP_I2C1_TX_USING_DMA
+#ifndef I2C1_TX_DMA_CONFIG
+#define I2C1_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C1_TX_DMA, \
+ .DMAChx = I2C1_TX_DMA_CHType, \
+ .dma_irq = I2C1_TX_DMA_IRQ, \
+ .dma_rcc = I2C1_TX_DMA_RCC, \
+ .request = I2C1_TX_DMA_REQUEST, \
+ .channel = I2C1_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C1_TX_DMA_CONFIG */
+#endif /* BSP_I2C1_TX_USING_DMA */
+
+
+#ifdef BSP_USING_HARD_I2C2
+#ifndef I2C2_BUS_CONFIG
+#define I2C2_BUS_CONFIG \
+ { \
+ .name = "hwi2c2", \
+ .Instance = I2C2, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C2_EV_IRQn, \
+ .erirq_type = I2C2_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPH_I2C2, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C2_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C2 */
+#ifdef BSP_I2C2_RX_USING_DMA
+#ifndef I2C2_RX_DMA_CONFIG
+#define I2C2_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C2_RX_DMA, \
+ .DMAChx = I2C2_RX_DMA_CHType, \
+ .dma_irq = I2C2_RX_DMA_IRQ, \
+ .dma_rcc = I2C2_RX_DMA_RCC, \
+ .request = I2C2_RX_DMA_REQUEST, \
+ .channel = I2C2_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C2_RX_DMA_CONFIG */
+#endif /* BSP_I2C2_RX_USING_DMA */
+#ifdef BSP_I2C2_TX_USING_DMA
+#ifndef I2C2_TX_DMA_CONFIG
+#define I2C2_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C2_TX_DMA, \
+ .DMAChx = I2C2_TX_DMA_CHType, \
+ .dma_irq = I2C2_TX_DMA_IRQ, \
+ .dma_rcc = I2C2_TX_DMA_RCC, \
+ .request = I2C2_TX_DMA_REQUEST, \
+ .channel = I2C2_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C2_TX_DMA_CONFIG */
+#endif /* BSP_I2C2_TX_USING_DMA */
+
+
+#ifdef BSP_USING_HARD_I2C3
+#ifndef I2C3_BUS_CONFIG
+#define I2C3_BUS_CONFIG \
+ { \
+ .name = "hwi2c3", \
+ .Instance = I2C3, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C3_EV_IRQn, \
+ .erirq_type = I2C3_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPH_I2C3, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C3_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C3 */
+#ifdef BSP_I2C3_RX_USING_DMA
+#ifndef I2C3_RX_DMA_CONFIG
+#define I2C3_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C3_RX_DMA, \
+ .DMAChx = I2C3_RX_DMA_CHType, \
+ .dma_irq = I2C3_RX_DMA_IRQ, \
+ .dma_rcc = I2C3_RX_DMA_RCC, \
+ .request = I2C3_RX_DMA_REQUEST, \
+ .channel = I2C3_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C3_RX_DMA_CONFIG */
+#endif /* BSP_I2C3_RX_USING_DMA */
+#ifdef BSP_I2C3_TX_USING_DMA
+#ifndef I2C3_TX_DMA_CONFIG
+#define I2C3_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C3_TX_DMA, \
+ .DMAChx = I2C3_TX_DMA_CHType, \
+ .dma_irq = I2C3_TX_DMA_IRQ, \
+ .dma_rcc = I2C3_TX_DMA_RCC, \
+ .request = I2C3_TX_DMA_REQUEST, \
+ .channel = I2C3_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C3_TX_DMA_CONFIG */
+#endif /* BSP_I2C3_TX_USING_DMA */
+
+
+#ifdef BSP_USING_HARD_I2C4
+#ifndef I2C4_BUS_CONFIG
+#define I2C4_BUS_CONFIG \
+ { \
+ .name = "hwi2c4", \
+ .Instance = I2C4, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C4_EV_IRQn, \
+ .erirq_type = I2C4_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPH_I2C4, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C4_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C4 */
+#ifdef BSP_I2C4_RX_USING_DMA
+#ifndef I2C4_RX_DMA_CONFIG
+#define I2C4_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C4_RX_DMA, \
+ .DMAChx = I2C4_RX_DMA_CHType, \
+ .dma_irq = I2C4_RX_DMA_IRQ, \
+ .dma_rcc = I2C4_RX_DMA_RCC, \
+ .request = I2C4_RX_DMA_REQUEST, \
+ .channel = I2C4_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C4_RX_DMA_CONFIG */
+#endif /* BSP_I2C4_RX_USING_DMA */
+#ifdef BSP_I2C4_TX_USING_DMA
+#ifndef I2C4_TX_DMA_CONFIG
+#define I2C4_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C4_TX_DMA, \
+ .DMAChx = I2C4_TX_DMA_CHType, \
+ .dma_irq = I2C4_TX_DMA_IRQ, \
+ .dma_rcc = I2C4_TX_DMA_RCC, \
+ .request = I2C4_TX_DMA_REQUEST, \
+ .channel = I2C4_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C4_TX_DMA_CONFIG */
+#endif /* BSP_I2C4_TX_USING_DMA */
+
+#ifdef __cplusplus
+}
+
+#endif
+
+#endif /*__I2C_HARD_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/spi_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/spi_config.h
new file mode 100644
index 0000000000..6b0b97cdef
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h47x_48x/spi_config.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-03 hu-wenhao first version
+ */
+
+#ifndef __SPI_CONFIG_H__
+#define __SPI_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef BSP_USING_SPI1
+#ifndef SPI1_BUS_CONFIG
+#define SPI1_BUS_CONFIG \
+ { \
+ .SPIx = SPI1, \
+ .bus_name = "spi1", \
+ .irq_type = SPI1_IRQn, \
+ }
+#endif /* SPI1_BUS_CONFIG */
+#endif /* BSP_USING_SPI1 */
+#ifdef BSP_SPI1_TX_USING_DMA
+#ifndef SPI1_TX_DMA_CONFIG
+#define SPI1_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI1_TX_DMA, \
+ .DMAChx = SPI1_TX_DMA_CHType, \
+ .dma_irq = SPI1_TX_DMA_IRQ, \
+ .dma_rcc = SPI1_TX_DMA_RCC, \
+ .request = SPI1_TX_DMA_REQUEST, \
+ .channel = SPI1_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI1_TX_DMA_CONFIG */
+#endif /* BSP_SPI1_TX_USING_DMA */
+#ifdef BSP_SPI1_RX_USING_DMA
+#ifndef SPI1_RX_DMA_CONFIG
+#define SPI1_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI1_RX_DMA, \
+ .DMAChx = SPI1_RX_DMA_CHType, \
+ .dma_irq = SPI1_RX_DMA_IRQ, \
+ .dma_rcc = SPI1_RX_DMA_RCC, \
+ .request = SPI1_RX_DMA_REQUEST, \
+ .channel = SPI1_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI1_RX_DMA_CONFIG */
+#endif /* BSP_SPI1_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI2
+#ifndef SPI2_BUS_CONFIG
+#define SPI2_BUS_CONFIG \
+ { \
+ .SPIx = SPI2, \
+ .bus_name = "spi2", \
+ .irq_type = SPI2_I2S2_IRQn, \
+ }
+#endif /* SPI2_BUS_CONFIG */
+#endif /* BSP_USING_SPI2 */
+#ifdef BSP_SPI2_TX_USING_DMA
+#ifndef SPI2_TX_DMA_CONFIG
+#define SPI2_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI2_TX_DMA, \
+ .DMAChx = SPI2_TX_DMA_CHType, \
+ .dma_irq = SPI2_TX_DMA_IRQ, \
+ .dma_rcc = SPI2_TX_DMA_RCC, \
+ .request = SPI2_TX_DMA_REQUEST, \
+ .channel = SPI2_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI2_TX_DMA_CONFIG */
+#endif /* BSP_SPI2_TX_USING_DMA */
+#ifdef BSP_SPI2_RX_USING_DMA
+#ifndef SPI2_RX_DMA_CONFIG
+#define SPI2_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI2_RX_DMA, \
+ .DMAChx = SPI2_RX_DMA_CHType, \
+ .dma_irq = SPI2_RX_DMA_IRQ, \
+ .dma_rcc = SPI2_RX_DMA_RCC, \
+ .request = SPI2_RX_DMA_REQUEST, \
+ .channel = SPI2_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI2_RX_DMA_CONFIG */
+#endif /* BSP_SPI2_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI3
+#ifndef SPI3_BUS_CONFIG
+#define SPI3_BUS_CONFIG \
+ { \
+ .SPIx = SPI3, \
+ .bus_name = "spi3", \
+ .irq_type = SPI3_I2S3_IRQn, \
+ }
+
+#endif /* SPI3_BUS_CONFIG */
+#endif /* BSP_USING_SPI3 */
+#ifdef BSP_SPI3_TX_USING_DMA
+#ifndef SPI3_TX_DMA_CONFIG
+#define SPI3_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI3_TX_DMA, \
+ .DMAChx = SPI3_TX_DMA_CHType, \
+ .dma_irq = SPI3_TX_DMA_IRQ, \
+ .dma_rcc = SPI3_TX_DMA_RCC, \
+ .request = SPI3_TX_DMA_REQUEST, \
+ .channel = SPI3_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI3_TX_DMA_CONFIG */
+#endif /* BSP_SPI3_TX_USING_DMA */
+#ifdef BSP_SPI3_RX_USING_DMA
+#ifndef SPI3_RX_DMA_CONFIG
+#define SPI3_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI3_RX_DMA, \
+ .DMAChx = SPI3_RX_DMA_CHType, \
+ .dma_irq = SPI3_RX_DMA_IRQ, \
+ .dma_rcc = SPI3_RX_DMA_RCC, \
+ .request = SPI3_RX_DMA_REQUEST, \
+ .channel = SPI3_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI3_RX_DMA_CONFIG */
+#endif /* BSP_SPI3_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI4
+#ifndef SPI4_BUS_CONFIG
+#define SPI4_BUS_CONFIG \
+ { \
+ .SPIx = SPI4, \
+ .bus_name = "spi4", \
+ .irq_type = SPI4_IRQn, \
+ }
+#endif /* SPI4_BUS_CONFIG */
+#endif /* BSP_USING_SPI4 */
+#ifdef BSP_SPI4_TX_USING_DMA
+#ifndef SPI4_TX_DMA_CONFIG
+#define SPI4_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI4_TX_DMA, \
+ .DMAChx = SPI4_TX_DMA_CHType, \
+ .dma_irq = SPI4_TX_DMA_IRQ, \
+ .dma_rcc = SPI4_TX_DMA_RCC, \
+ .request = SPI4_TX_DMA_REQUEST, \
+ .channel = SPI4_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI4_TX_DMA_CONFIG */
+#endif /* BSP_SPI4_TX_USING_DMA */
+#ifdef BSP_SPI4_RX_USING_DMA
+#ifndef SPI4_RX_DMA_CONFIG
+#define SPI4_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI4_RX_DMA, \
+ .DMAChx = SPI4_RX_DMA_CHType, \
+ .dma_irq = SPI4_RX_DMA_IRQ, \
+ .dma_rcc = SPI4_RX_DMA_RCC, \
+ .request = SPI4_RX_DMA_REQUEST, \
+ .channel = SPI4_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI4_RX_DMA_CONFIG */
+#endif /* BSP_SPI4_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI5
+#ifndef SPI5_BUS_CONFIG
+#define SPI5_BUS_CONFIG \
+ { \
+ .SPIx = SPI5, \
+ .bus_name = "spi5", \
+ .irq_type = SPI5_IRQn, \
+ }
+#endif /* SPI5_BUS_CONFIG */
+#endif /* BSP_USING_SPI5 */
+#ifdef BSP_SPI5_TX_USING_DMA
+#ifndef SPI5_TX_DMA_CONFIG
+#define SPI5_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI5_TX_DMA, \
+ .DMAChx = SPI5_TX_DMA_CHType, \
+ .dma_irq = SPI5_TX_DMA_IRQ, \
+ .dma_rcc = SPI5_TX_DMA_RCC, \
+ .request = SPI5_TX_DMA_REQUEST, \
+ .channel = SPI5_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI5_TX_DMA_CONFIG */
+#endif /* BSP_SPI5_TX_USING_DMA */
+#ifdef BSP_SPI5_RX_USING_DMA
+#ifndef SPI5_RX_DMA_CONFIG
+#define SPI5_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI5_RX_DMA, \
+ .DMAChx = SPI5_RX_DMA_CHType, \
+ .dma_irq = SPI5_RX_DMA_IRQ, \
+ .dma_rcc = SPI5_RX_DMA_RCC, \
+ .request = SPI5_RX_DMA_REQUEST, \
+ .channel = SPI5_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI5_RX_DMA_CONFIG */
+#endif /* BSP_SPI5_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI6
+#ifndef SPI6_BUS_CONFIG
+#define SPI6_BUS_CONFIG \
+ { \
+ .SPIx = SPI6, \
+ .bus_name = "spi6", \
+ .irq_type = SPI6_IRQn, \
+ }
+#endif /* SPI6_BUS_CONFIG */
+#endif /* BSP_USING_SPI6 */
+#ifdef BSP_SPI6_TX_USING_DMA
+#ifndef SPI6_TX_DMA_CONFIG
+#define SPI6_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI6_TX_DMA, \
+ .DMAChx = SPI6_TX_DMA_CHType, \
+ .dma_irq = SPI6_TX_DMA_IRQ, \
+ .dma_rcc = SPI6_TX_DMA_RCC, \
+ .request = SPI6_TX_DMA_REQUEST, \
+ .channel = SPI6_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI6_TX_DMA_CONFIG */
+#endif /* BSP_SPI6_TX_USING_DMA */
+#ifdef BSP_SPI6_RX_USING_DMA
+#ifndef SPI6_RX_DMA_CONFIG
+#define SPI6_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI6_RX_DMA, \
+ .DMAChx = SPI6_RX_DMA_CHType, \
+ .dma_irq = SPI6_RX_DMA_IRQ, \
+ .dma_rcc = SPI6_RX_DMA_RCC, \
+ .request = SPI6_RX_DMA_REQUEST, \
+ .channel = SPI6_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI6_RX_DMA_CONFIG */
+#endif /* BSP_SPI6_RX_USING_DMA */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__SPI_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/adc_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/adc_config.h
new file mode 100644
index 0000000000..44d41e0af4
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/adc_config.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-28 FUNMSAN first version
+ */
+
+#ifndef __ADC_CONFIG_H__
+#define __ADC_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define N32H49X_ADC_CONFIG(ADC_INSTANCE, ADC_PERIPH) \
+ { \
+ .ADCx = ADC_INSTANCE, \
+ .AHB_periph = ADC_PERIPH, \
+ .EnablePeriphClk = RCC_EnableAHB1PeriphClk, \
+ .ADC_ClkMode = ADC_CTRL3_CKMOD_AHB, \
+ .RCC_ADCPrescaler = RCC_ADCHCLK_DIV16, \
+ .ADC1M_ClkSource = RCC_ADC1MCLK_SRC_HSI, \
+ .ADC1M_ClkPrescaler = RCC_ADC1MCLK_DIV8, \
+ .Rank = 1U, \
+ .ADC_SampleTime = ADC_SAMP_TIME_CYCLES_239_5, \
+ .Init.WorkMode = ADC_WORKMODE_INDEPENDENT, \
+ .Init.MultiChEn = DISABLE, \
+ .Init.ContinueConvEn = DISABLE, \
+ .Init.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE, \
+ .Init.DatAlign = ADC_DAT_ALIGN_R, \
+ .Init.ChsNumber = 1U, \
+ .Init.Resolution = ADC_DATA_RES_12BIT, \
+ }
+
+#ifdef BSP_USING_ADC1
+#ifndef ADC1_CONFIG
+#define ADC1_CONFIG N32H49X_ADC_CONFIG(ADC1, RCC_AHB_PERIPHEN_ADC1)
+#endif /* ADC1_CONFIG */
+#endif /* BSP_USING_ADC1 */
+
+#ifdef BSP_USING_ADC2
+#ifndef ADC2_CONFIG
+#define ADC2_CONFIG N32H49X_ADC_CONFIG(ADC2, RCC_AHB_PERIPHEN_ADC2)
+#endif /* ADC2_CONFIG */
+#endif /* BSP_USING_ADC2 */
+
+#ifdef BSP_USING_ADC3
+#ifndef ADC3_CONFIG
+#define ADC3_CONFIG N32H49X_ADC_CONFIG(ADC3, RCC_AHB_PERIPHEN_ADC3)
+#endif /* ADC3_CONFIG */
+#endif /* BSP_USING_ADC3 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ADC_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dac_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dac_config.h
new file mode 100644
index 0000000000..490257436c
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dac_config.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-28 FUNMSAN first version
+ */
+
+#ifndef __DAC_CONFIG_H__
+#define __DAC_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define N32H49X_DAC_CONFIG(DAC_INSTANCE) \
+ { \
+ .DACx = DAC_INSTANCE, \
+ .DAC_Module = DAC12, \
+ .periph_clk = RCC_APB1_PERIPHEN_DAC12, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ .DAC_clk_pres = 120U, \
+ .Init.DAC_Trigger = DAC_Trigger_Software, \
+ .Init.DAC_Trigger2 = DAC_Trigger2_Software, \
+ .Init.DAC_WaveGeneration = DAC_WaveGeneration_None, \
+ .Init.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0, \
+ .Init.DAC_OutputBuffer = DISABLE, \
+ .Init.DAC_TriggerEnable = ENABLE, \
+ .Init.DAC_ConnectOnChipPeripheral = DISABLE, \
+ .Init.DAC_ConnectExternalPin = ENABLE, \
+ .Init.DAC_DMADoubleDataMode = DISABLE, \
+ .Init.DAC_SignedFormat = DISABLE, \
+ }
+
+#ifdef BSP_USING_DAC1
+#ifndef DAC1_CONFIG
+#define DAC1_CONFIG N32H49X_DAC_CONFIG(DAC1)
+#endif /* DAC1_CONFIG */
+#endif /* BSP_USING_DAC1 */
+
+#ifdef BSP_USING_DAC2
+#ifndef DAC2_CONFIG
+#define DAC2_CONFIG N32H49X_DAC_CONFIG(DAC2)
+#endif /* DAC2_CONFIG */
+#endif /* BSP_USING_DAC2 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DAC_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dma_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dma_config.h
index 2959dabb03..cdc6b803d5 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dma_config.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/dma_config.h
@@ -239,7 +239,7 @@ extern "C" {
#define UART10_RX_DMA_RCC RCC_AHB_PERIPHEN_DMA2
#define UART10_RX_DMA_REQUEST DMA_REMAP_UART10_RX
#define UART10_RX_DMA_CHANNEL 2U
-#elif defined(BSP_USING_SDIO) && !defined(UART10_RX_DMA)
+#elif defined(BSP_USING_SDIO)
#define SDIO_RX_DMA DMA2
#define SDIO_TX_DMA DMA2
#define SDIO_RX_TX_DMA_IRQHandler DMA2_Channel2_IRQHandler
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/i2c_hard_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/i2c_hard_config.h
new file mode 100644
index 0000000000..513bba9e02
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/i2c_hard_config.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-01-24 ox-horse first version
+ */
+
+#ifndef __I2C_HARD_CONFIG_H__
+#define __I2C_HARD_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef BSP_USING_HARD_I2C1
+#ifndef I2C1_BUS_CONFIG
+#define I2C1_BUS_CONFIG \
+ { \
+ .name = "hwi2c1", \
+ .Instance = I2C1, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C1_EV_IRQn, \
+ .erirq_type = I2C1_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPHEN_I2C1, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C1_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C1 */
+#ifdef BSP_I2C1_RX_USING_DMA
+#ifndef I2C1_RX_DMA_CONFIG
+#define I2C1_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C1_RX_DMA, \
+ .DMAChx = I2C1_RX_DMA_CHType, \
+ .dma_irq = I2C1_RX_DMA_IRQ, \
+ .dma_rcc = I2C1_RX_DMA_RCC, \
+ .request = I2C1_RX_DMA_REQUEST, \
+ .channel = I2C1_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C1_RX_DMA_CONFIG */
+#endif /* BSP_I2C1_RX_USING_DMA */
+#ifdef BSP_I2C1_TX_USING_DMA
+#ifndef I2C1_TX_DMA_CONFIG
+#define I2C1_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C1_TX_DMA, \
+ .DMAChx = I2C1_TX_DMA_CHType, \
+ .dma_irq = I2C1_TX_DMA_IRQ, \
+ .dma_rcc = I2C1_TX_DMA_RCC, \
+ .request = I2C1_TX_DMA_REQUEST, \
+ .channel = I2C1_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C1_TX_DMA_CONFIG */
+#endif /* BSP_I2C1_TX_USING_DMA */
+
+
+#ifdef BSP_USING_HARD_I2C2
+#ifndef I2C2_BUS_CONFIG
+#define I2C2_BUS_CONFIG \
+ { \
+ .name = "hwi2c2", \
+ .Instance = I2C2, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C2_EV_IRQn, \
+ .erirq_type = I2C2_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPHEN_I2C2, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C2_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C2 */
+#ifdef BSP_I2C2_RX_USING_DMA
+#ifndef I2C2_RX_DMA_CONFIG
+#define I2C2_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C2_RX_DMA, \
+ .DMAChx = I2C2_RX_DMA_CHType, \
+ .dma_irq = I2C2_RX_DMA_IRQ, \
+ .dma_rcc = I2C2_RX_DMA_RCC, \
+ .request = I2C2_RX_DMA_REQUEST, \
+ .channel = I2C2_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C2_RX_DMA_CONFIG */
+#endif /* BSP_I2C2_RX_USING_DMA */
+#ifdef BSP_I2C2_TX_USING_DMA
+#ifndef I2C2_TX_DMA_CONFIG
+#define I2C2_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C2_TX_DMA, \
+ .DMAChx = I2C2_TX_DMA_CHType, \
+ .dma_irq = I2C2_TX_DMA_IRQ, \
+ .dma_rcc = I2C2_TX_DMA_RCC, \
+ .request = I2C2_TX_DMA_REQUEST, \
+ .channel = I2C2_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C2_TX_DMA_CONFIG */
+#endif /* BSP_I2C2_TX_USING_DMA */
+
+
+#ifdef BSP_USING_HARD_I2C3
+#ifndef I2C3_BUS_CONFIG
+#define I2C3_BUS_CONFIG \
+ { \
+ .name = "hwi2c3", \
+ .Instance = I2C3, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C3_EV_IRQn, \
+ .erirq_type = I2C3_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPHEN_I2C3, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C3_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C3 */
+#ifdef BSP_I2C3_RX_USING_DMA
+#ifndef I2C3_RX_DMA_CONFIG
+#define I2C3_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C3_RX_DMA, \
+ .DMAChx = I2C3_RX_DMA_CHType, \
+ .dma_irq = I2C3_RX_DMA_IRQ, \
+ .dma_rcc = I2C3_RX_DMA_RCC, \
+ .request = I2C3_RX_DMA_REQUEST, \
+ .channel = I2C3_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C3_RX_DMA_CONFIG */
+#endif /* BSP_I2C3_RX_USING_DMA */
+#ifdef BSP_I2C3_TX_USING_DMA
+#ifndef I2C3_TX_DMA_CONFIG
+#define I2C3_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C3_TX_DMA, \
+ .DMAChx = I2C3_TX_DMA_CHType, \
+ .dma_irq = I2C3_TX_DMA_IRQ, \
+ .dma_rcc = I2C3_TX_DMA_RCC, \
+ .request = I2C3_TX_DMA_REQUEST, \
+ .channel = I2C3_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C3_TX_DMA_CONFIG */
+#endif /* BSP_I2C3_TX_USING_DMA */
+
+
+#ifdef BSP_USING_HARD_I2C4
+#ifndef I2C4_BUS_CONFIG
+#define I2C4_BUS_CONFIG \
+ { \
+ .name = "hwi2c4", \
+ .Instance = I2C4, \
+ .timeout = 0x1000, \
+ .evirq_type = I2C4_EV_IRQn, \
+ .erirq_type = I2C4_ER_IRQn, \
+ .scl_af_width = 0, \
+ .sda_af_width = 0, \
+ .df_width = 0, \
+ .periph = RCC_APB1_PERIPHEN_I2C4, \
+ .EnablePeriphClk = RCC_EnableAPB1PeriphClk, \
+ }
+#endif /* I2C4_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C4 */
+#ifdef BSP_I2C4_RX_USING_DMA
+#ifndef I2C4_RX_DMA_CONFIG
+#define I2C4_RX_DMA_CONFIG \
+ { \
+ .DMAy = I2C4_RX_DMA, \
+ .DMAChx = I2C4_RX_DMA_CHType, \
+ .dma_irq = I2C4_RX_DMA_IRQ, \
+ .dma_rcc = I2C4_RX_DMA_RCC, \
+ .request = I2C4_RX_DMA_REQUEST, \
+ .channel = I2C4_RX_DMA_CHANNEL, \
+ }
+#endif /* I2C4_RX_DMA_CONFIG */
+#endif /* BSP_I2C4_RX_USING_DMA */
+#ifdef BSP_I2C4_TX_USING_DMA
+#ifndef I2C4_TX_DMA_CONFIG
+#define I2C4_TX_DMA_CONFIG \
+ { \
+ .DMAy = I2C4_TX_DMA, \
+ .DMAChx = I2C4_TX_DMA_CHType, \
+ .dma_irq = I2C4_TX_DMA_IRQ, \
+ .dma_rcc = I2C4_TX_DMA_RCC, \
+ .request = I2C4_TX_DMA_REQUEST, \
+ .channel = I2C4_TX_DMA_CHANNEL, \
+ }
+#endif /* I2C4_TX_DMA_CONFIG */
+#endif /* BSP_I2C4_TX_USING_DMA */
+
+#ifdef __cplusplus
+}
+
+#endif
+
+#endif /*__I2C_HARD_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/spi_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/spi_config.h
new file mode 100644
index 0000000000..6b0b97cdef
--- /dev/null
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h49x/spi_config.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-03 hu-wenhao first version
+ */
+
+#ifndef __SPI_CONFIG_H__
+#define __SPI_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef BSP_USING_SPI1
+#ifndef SPI1_BUS_CONFIG
+#define SPI1_BUS_CONFIG \
+ { \
+ .SPIx = SPI1, \
+ .bus_name = "spi1", \
+ .irq_type = SPI1_IRQn, \
+ }
+#endif /* SPI1_BUS_CONFIG */
+#endif /* BSP_USING_SPI1 */
+#ifdef BSP_SPI1_TX_USING_DMA
+#ifndef SPI1_TX_DMA_CONFIG
+#define SPI1_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI1_TX_DMA, \
+ .DMAChx = SPI1_TX_DMA_CHType, \
+ .dma_irq = SPI1_TX_DMA_IRQ, \
+ .dma_rcc = SPI1_TX_DMA_RCC, \
+ .request = SPI1_TX_DMA_REQUEST, \
+ .channel = SPI1_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI1_TX_DMA_CONFIG */
+#endif /* BSP_SPI1_TX_USING_DMA */
+#ifdef BSP_SPI1_RX_USING_DMA
+#ifndef SPI1_RX_DMA_CONFIG
+#define SPI1_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI1_RX_DMA, \
+ .DMAChx = SPI1_RX_DMA_CHType, \
+ .dma_irq = SPI1_RX_DMA_IRQ, \
+ .dma_rcc = SPI1_RX_DMA_RCC, \
+ .request = SPI1_RX_DMA_REQUEST, \
+ .channel = SPI1_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI1_RX_DMA_CONFIG */
+#endif /* BSP_SPI1_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI2
+#ifndef SPI2_BUS_CONFIG
+#define SPI2_BUS_CONFIG \
+ { \
+ .SPIx = SPI2, \
+ .bus_name = "spi2", \
+ .irq_type = SPI2_I2S2_IRQn, \
+ }
+#endif /* SPI2_BUS_CONFIG */
+#endif /* BSP_USING_SPI2 */
+#ifdef BSP_SPI2_TX_USING_DMA
+#ifndef SPI2_TX_DMA_CONFIG
+#define SPI2_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI2_TX_DMA, \
+ .DMAChx = SPI2_TX_DMA_CHType, \
+ .dma_irq = SPI2_TX_DMA_IRQ, \
+ .dma_rcc = SPI2_TX_DMA_RCC, \
+ .request = SPI2_TX_DMA_REQUEST, \
+ .channel = SPI2_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI2_TX_DMA_CONFIG */
+#endif /* BSP_SPI2_TX_USING_DMA */
+#ifdef BSP_SPI2_RX_USING_DMA
+#ifndef SPI2_RX_DMA_CONFIG
+#define SPI2_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI2_RX_DMA, \
+ .DMAChx = SPI2_RX_DMA_CHType, \
+ .dma_irq = SPI2_RX_DMA_IRQ, \
+ .dma_rcc = SPI2_RX_DMA_RCC, \
+ .request = SPI2_RX_DMA_REQUEST, \
+ .channel = SPI2_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI2_RX_DMA_CONFIG */
+#endif /* BSP_SPI2_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI3
+#ifndef SPI3_BUS_CONFIG
+#define SPI3_BUS_CONFIG \
+ { \
+ .SPIx = SPI3, \
+ .bus_name = "spi3", \
+ .irq_type = SPI3_I2S3_IRQn, \
+ }
+
+#endif /* SPI3_BUS_CONFIG */
+#endif /* BSP_USING_SPI3 */
+#ifdef BSP_SPI3_TX_USING_DMA
+#ifndef SPI3_TX_DMA_CONFIG
+#define SPI3_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI3_TX_DMA, \
+ .DMAChx = SPI3_TX_DMA_CHType, \
+ .dma_irq = SPI3_TX_DMA_IRQ, \
+ .dma_rcc = SPI3_TX_DMA_RCC, \
+ .request = SPI3_TX_DMA_REQUEST, \
+ .channel = SPI3_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI3_TX_DMA_CONFIG */
+#endif /* BSP_SPI3_TX_USING_DMA */
+#ifdef BSP_SPI3_RX_USING_DMA
+#ifndef SPI3_RX_DMA_CONFIG
+#define SPI3_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI3_RX_DMA, \
+ .DMAChx = SPI3_RX_DMA_CHType, \
+ .dma_irq = SPI3_RX_DMA_IRQ, \
+ .dma_rcc = SPI3_RX_DMA_RCC, \
+ .request = SPI3_RX_DMA_REQUEST, \
+ .channel = SPI3_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI3_RX_DMA_CONFIG */
+#endif /* BSP_SPI3_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI4
+#ifndef SPI4_BUS_CONFIG
+#define SPI4_BUS_CONFIG \
+ { \
+ .SPIx = SPI4, \
+ .bus_name = "spi4", \
+ .irq_type = SPI4_IRQn, \
+ }
+#endif /* SPI4_BUS_CONFIG */
+#endif /* BSP_USING_SPI4 */
+#ifdef BSP_SPI4_TX_USING_DMA
+#ifndef SPI4_TX_DMA_CONFIG
+#define SPI4_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI4_TX_DMA, \
+ .DMAChx = SPI4_TX_DMA_CHType, \
+ .dma_irq = SPI4_TX_DMA_IRQ, \
+ .dma_rcc = SPI4_TX_DMA_RCC, \
+ .request = SPI4_TX_DMA_REQUEST, \
+ .channel = SPI4_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI4_TX_DMA_CONFIG */
+#endif /* BSP_SPI4_TX_USING_DMA */
+#ifdef BSP_SPI4_RX_USING_DMA
+#ifndef SPI4_RX_DMA_CONFIG
+#define SPI4_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI4_RX_DMA, \
+ .DMAChx = SPI4_RX_DMA_CHType, \
+ .dma_irq = SPI4_RX_DMA_IRQ, \
+ .dma_rcc = SPI4_RX_DMA_RCC, \
+ .request = SPI4_RX_DMA_REQUEST, \
+ .channel = SPI4_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI4_RX_DMA_CONFIG */
+#endif /* BSP_SPI4_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI5
+#ifndef SPI5_BUS_CONFIG
+#define SPI5_BUS_CONFIG \
+ { \
+ .SPIx = SPI5, \
+ .bus_name = "spi5", \
+ .irq_type = SPI5_IRQn, \
+ }
+#endif /* SPI5_BUS_CONFIG */
+#endif /* BSP_USING_SPI5 */
+#ifdef BSP_SPI5_TX_USING_DMA
+#ifndef SPI5_TX_DMA_CONFIG
+#define SPI5_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI5_TX_DMA, \
+ .DMAChx = SPI5_TX_DMA_CHType, \
+ .dma_irq = SPI5_TX_DMA_IRQ, \
+ .dma_rcc = SPI5_TX_DMA_RCC, \
+ .request = SPI5_TX_DMA_REQUEST, \
+ .channel = SPI5_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI5_TX_DMA_CONFIG */
+#endif /* BSP_SPI5_TX_USING_DMA */
+#ifdef BSP_SPI5_RX_USING_DMA
+#ifndef SPI5_RX_DMA_CONFIG
+#define SPI5_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI5_RX_DMA, \
+ .DMAChx = SPI5_RX_DMA_CHType, \
+ .dma_irq = SPI5_RX_DMA_IRQ, \
+ .dma_rcc = SPI5_RX_DMA_RCC, \
+ .request = SPI5_RX_DMA_REQUEST, \
+ .channel = SPI5_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI5_RX_DMA_CONFIG */
+#endif /* BSP_SPI5_RX_USING_DMA */
+
+
+#ifdef BSP_USING_SPI6
+#ifndef SPI6_BUS_CONFIG
+#define SPI6_BUS_CONFIG \
+ { \
+ .SPIx = SPI6, \
+ .bus_name = "spi6", \
+ .irq_type = SPI6_IRQn, \
+ }
+#endif /* SPI6_BUS_CONFIG */
+#endif /* BSP_USING_SPI6 */
+#ifdef BSP_SPI6_TX_USING_DMA
+#ifndef SPI6_TX_DMA_CONFIG
+#define SPI6_TX_DMA_CONFIG \
+ { \
+ .DMAy = SPI6_TX_DMA, \
+ .DMAChx = SPI6_TX_DMA_CHType, \
+ .dma_irq = SPI6_TX_DMA_IRQ, \
+ .dma_rcc = SPI6_TX_DMA_RCC, \
+ .request = SPI6_TX_DMA_REQUEST, \
+ .channel = SPI6_TX_DMA_CHANNEL, \
+ }
+#endif /* SPI6_TX_DMA_CONFIG */
+#endif /* BSP_SPI6_TX_USING_DMA */
+#ifdef BSP_SPI6_RX_USING_DMA
+#ifndef SPI6_RX_DMA_CONFIG
+#define SPI6_RX_DMA_CONFIG \
+ { \
+ .DMAy = SPI6_RX_DMA, \
+ .DMAChx = SPI6_RX_DMA_CHType, \
+ .dma_irq = SPI6_RX_DMA_IRQ, \
+ .dma_rcc = SPI6_RX_DMA_RCC, \
+ .request = SPI6_RX_DMA_REQUEST, \
+ .channel = SPI6_RX_DMA_CHANNEL, \
+ }
+#endif /* SPI6_RX_DMA_CONFIG */
+#endif /* BSP_SPI6_RX_USING_DMA */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__SPI_CONFIG_H__ */
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h7xx/dma_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h7xx/dma_config.h
index e83eec4310..e666d29fc6 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h7xx/dma_config.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/config/h7xx/dma_config.h
@@ -492,7 +492,10 @@ extern "C" {
#define SPI3_RX_DMA_IRQ DMA2_Channel7_IRQn
#define SPI3_RX_DMA_HANDSHAK DMA_CH_HARDWARE_HANDSHAKING_IF_7
#define SPI3_RX_DMA_DMA_RCC RCC_AHB1_PERIPHEN_M7_DMA2
-#define SPI3_RX_DMA_DMA_CHANNEL DMA_CHANNEL_5
+/* DMAMUX1 output 15 feeds DMA2 channel 7 (output N -> DMA(N/8+1) ch(N%8)),
+ * so the channel must match the IRQ/handshake below; DMA_CHANNEL_5 was a
+ * copy-paste defect that armed ch5 while the request lands on ch7. */
+#define SPI3_RX_DMA_DMA_CHANNEL DMA_CHANNEL_7
#define SPI3_RX_DMA_DMAMUX_CHANNEL DMAMUX_CHANNEL_15
#define SPI3_RX_DMA_DMAMUX_REQUEST DMAMUX1_REQUEST_SPI3_RX
#endif
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_adc.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_adc.c
index 6e31a8dc82..746e23f087 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_adc.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_adc.c
@@ -6,18 +6,34 @@
* Change Logs:
* Date Author Notes
* 2026-01-24 ox-horse first version
+ * 2026-08-28 FUNMSAN add N32H47_48x and N32H49x support
*/
#include <board.h>
#include <rtthread.h>
-#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
+#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || \
+ (defined(SOC_SERIES_N32H47x_48x) && defined(BSP_USING_ADC4))
+
+#if defined(SOC_SERIES_N32H7xx)
+#include "n32h7xx_adc.h"
+#include "n32h7xx_rcc.h"
+#elif defined(SOC_SERIES_N32H47x_48x)
+#include "n32h47x_48x_adc.h"
+#include "n32h47x_48x_rcc.h"
+#elif defined(SOC_SERIES_N32H49x)
+#include "n32h49x_adc.h"
+#include "n32h49x_rcc.h"
+#endif
+
#include "drv_config.h"
//#define DRV_DEBUG
#define LOG_TAG "drv.adc"
#include <drv_log.h>
+#define N32_ADC_POLL_TIMEOUT 1000000U
+
typedef struct
{
@@ -28,6 +44,10 @@ typedef struct
ADC_CTRL3_CKMOD ADC_ClkMode;
uint32_t Pll_CLK_source;
uint32_t RCC_ADCPrescaler;
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ uint32_t ADC1M_ClkSource;
+ uint32_t ADC1M_ClkPrescaler;
+#endif
uint32_t Rank;
uint32_t ADC_SampleTime;
@@ -47,6 +67,10 @@ static ADC_InitInfo_t adc_config[] = {
#ifdef BSP_USING_ADC3
ADC3_CONFIG,
#endif
+
+#if defined(SOC_SERIES_N32H47x_48x) && defined(BSP_USING_ADC4)
+ ADC4_CONFIG,
+#endif
};
@@ -54,6 +78,10 @@ struct n32_adc
{
ADC_InitInfo_t ADC_Info;
struct rt_adc_device n32_adc_device;
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ rt_bool_t calibrated;
+ rt_bool_t enabled;
+#endif
};
@@ -121,9 +149,11 @@ static rt_err_t n32_adc_get_channel(rt_int8_t rt_channel, uint32_t *n32_channel)
case 18:
*n32_channel = ADC_CH_18;
break;
+#ifdef ADC_CH_19
case 19:
*n32_channel = ADC_CH_19;
break;
+#endif
#if defined(SOC_SERIES_N32H7xx)
#ifdef ADC3_Channel_19_VREFINT
@@ -143,6 +173,18 @@ static rt_err_t n32_adc_get_channel(rt_int8_t rt_channel, uint32_t *n32_channel)
*n32_channel = ADC3_Channel_18_Temperture_Sensor;
break;
#endif /* ADC3_Channel_18_Temperture_Sensor */
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ case RT_ADC_INTERN_CH_VREF:
+ *n32_channel = ADC1_Channel_18_VREFINT;
+ break;
+
+ case RT_ADC_INTERN_CH_VBAT:
+ *n32_channel = ADC1_Channel_17_Battery_DIV2;
+ break;
+
+ case RT_ADC_INTERN_CH_TEMPER:
+ *n32_channel = ADC1_Channel_16_Temperture_Sensor;
+ break;
#endif
default:
@@ -155,12 +197,20 @@ static rt_err_t n32_adc_get_channel(rt_int8_t rt_channel, uint32_t *n32_channel)
static rt_err_t n32_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
{
+#if defined(SOC_SERIES_N32H7xx)
volatile uint32_t index = 0;
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ rt_uint32_t timeout;
+ struct n32_adc *adc_obj;
+#endif
uint32_t ADC_Channel;
ADC_InitInfo_t *n32_adc_info;
RT_ASSERT(device != RT_NULL);
n32_adc_info = device->parent.user_data;
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ adc_obj = rt_container_of(device, struct n32_adc, n32_adc_device);
+#endif
if (enabled)
{
@@ -229,6 +279,82 @@ static rt_err_t n32_adc_enabled(struct rt_adc_device *device, rt_int8_t channel,
/* Start ADC Software Conversion */
ADC_EnableSoftwareStartConv(n32_adc_info->ADCx, ENABLE);
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ if (channel == RT_ADC_INTERN_CH_TEMPER)
+ {
+ if (n32_adc_info->ADCx != ADC1)
+ {
+ LOG_E("%s not supported", device->parent.parent.name);
+ return -RT_EINVAL;
+ }
+ ADC_EnableTempSensorVrefint(ENABLE);
+ }
+ else if (channel == RT_ADC_INTERN_CH_VREF)
+ {
+#if defined(SOC_SERIES_N32H47x_48x)
+ if ((n32_adc_info->ADCx != ADC1) && (n32_adc_info->ADCx != ADC2))
+#elif defined(SOC_SERIES_N32H49x)
+ if ((n32_adc_info->ADCx != ADC1) && (n32_adc_info->ADCx != ADC2) &&
+ (n32_adc_info->ADCx != ADC3))
+#endif
+ {
+ LOG_E("%s not supported", device->parent.parent.name);
+ return -RT_EINVAL;
+ }
+ ADC_EnableTempSensorVrefint(ENABLE);
+ }
+ else if (channel == RT_ADC_INTERN_CH_VBAT)
+ {
+ if (n32_adc_info->ADCx != ADC1)
+ {
+ LOG_E("%s not supported", device->parent.parent.name);
+ return -RT_EINVAL;
+ }
+ ADC_EnableBatteryVoltageMonitor(n32_adc_info->ADCx, ENABLE);
+ }
+
+ if (adc_obj->enabled == RT_FALSE)
+ {
+ /* RDY/PDRDY are sticky write-one-to-clear flags. Clear the status
+ * from the previous power cycle before waiting for a new RDY. */
+ ADC_ClearFlag(n32_adc_info->ADCx, ADC_FLAG_RDY);
+ ADC_ClearFlag(n32_adc_info->ADCx, ADC_FLAG_PDRDY);
+
+ ADC_Enable(n32_adc_info->ADCx, ENABLE);
+ timeout = N32_ADC_POLL_TIMEOUT;
+ while (ADC_GetFlagStatus(n32_adc_info->ADCx, ADC_FLAG_RDY) == RESET)
+ {
+ if (timeout-- == 0U)
+ {
+ ADC_Enable(n32_adc_info->ADCx, DISABLE);
+ LOG_E("%s ready timeout", device->parent.parent.name);
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /* The calibration factor is retained while the ADC is disabled. Re-running
+ * calibration on every RT_ADC_CMD_ENABLE can leave a new calibration in
+ * progress because the vendor status API also checks the old factor. */
+ if (adc_obj->calibrated == RT_FALSE)
+ {
+ ADC_CalibrationOperation(n32_adc_info->ADCx, ADC_CALIBRATION_SINGLE_MODE);
+ timeout = N32_ADC_POLL_TIMEOUT;
+ while (ADC_GetCalibrationStatus(n32_adc_info->ADCx, ADC_CALIBRATION_SINGLE_MODE) != RESET)
+ {
+ if (timeout-- == 0U)
+ {
+ ADC_Enable(n32_adc_info->ADCx, DISABLE);
+ LOG_E("%s calibration timeout", device->parent.parent.name);
+ return -RT_ETIMEOUT;
+ }
+ }
+ adc_obj->calibrated = RT_TRUE;
+ }
+
+ adc_obj->enabled = RT_TRUE;
+ }
+
+ ADC_ConfigRegularChannel(n32_adc_info->ADCx, ADC_Channel, n32_adc_info->Rank, n32_adc_info->ADC_SampleTime);
#endif
}
else
@@ -252,6 +378,26 @@ static rt_err_t n32_adc_enabled(struct rt_adc_device *device, rt_int8_t channel,
/* Disable ADC */
ADC_Enable(n32_adc_info->ADCx, DISABLE);
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ if ((channel == RT_ADC_INTERN_CH_VREF) || (channel == RT_ADC_INTERN_CH_TEMPER))
+ {
+ ADC_EnableTempSensorVrefint(DISABLE);
+ }
+ else if (channel == RT_ADC_INTERN_CH_VBAT)
+ {
+ ADC_EnableBatteryVoltageMonitor(n32_adc_info->ADCx, DISABLE);
+ }
+
+ if (adc_obj->enabled == RT_TRUE)
+ {
+ ADC_Enable(n32_adc_info->ADCx, DISABLE);
+ adc_obj->enabled = RT_FALSE;
+
+ /* ADC_Enable(DISABLE) clears ON directly. PDRDY is not asserted in
+ * every power mode, so it must not be a mandatory completion event. */
+ ADC_ClearFlag(n32_adc_info->ADCx, ADC_FLAG_RDY);
+ ADC_ClearFlag(n32_adc_info->ADCx, ADC_FLAG_PDRDY);
+ }
#endif
}
@@ -263,6 +409,9 @@ static rt_err_t n32_adc_get_value(struct rt_adc_device *device, rt_int8_t channe
{
uint16_t Convert_Value = 0;
ADC_InitInfo_t *n32_adc_info;
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ rt_uint32_t timeout;
+#endif
RT_ASSERT(device != RT_NULL);
RT_ASSERT(value != RT_NULL);
@@ -286,6 +435,28 @@ static rt_err_t n32_adc_get_value(struct rt_adc_device *device, rt_int8_t channe
{
Convert_Value *= 4U;
}
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ /* Start one software conversion for the selected regular channel */
+ ADC_EnableSoftwareStartConv(n32_adc_info->ADCx, ENABLE);
+
+ timeout = N32_ADC_POLL_TIMEOUT;
+ while (ADC_GetFlagStatus(n32_adc_info->ADCx, ADC_FLAG_ENDC) != SET)
+ {
+ if (timeout-- == 0U)
+ {
+ LOG_E("%s conversion timeout", device->parent.parent.name);
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ ADC_ClearFlag(n32_adc_info->ADCx, ADC_FLAG_ENDC);
+ ADC_ClearFlag(n32_adc_info->ADCx, ADC_FLAG_STR);
+ Convert_Value = ADC_GetDat(n32_adc_info->ADCx);
+
+ if (channel == RT_ADC_INTERN_CH_VBAT)
+ {
+ Convert_Value *= 2U;
+ }
#endif
*value = Convert_Value;
@@ -315,6 +486,30 @@ static rt_uint8_t n32_adc_get_resolution(struct rt_adc_device *device)
Resolution = 10;
break;
}
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ case ADC_DATA_RES_12BIT:
+ {
+ Resolution = 12;
+ break;
+ }
+
+ case ADC_DATA_RES_10BIT:
+ {
+ Resolution = 10;
+ break;
+ }
+
+ case ADC_DATA_RES_8BIT:
+ {
+ Resolution = 8;
+ break;
+ }
+
+ case ADC_DATA_RES_6BIT:
+ {
+ Resolution = 6;
+ break;
+ }
#endif
default:
break;
@@ -368,6 +563,19 @@ static int n32_adc_init(void)
name_buf[3] = '3';
}
#endif
+#if defined(ADC4)
+ if (n32_adc_obj[i].ADC_Info.ADCx == ADC4)
+ {
+ name_buf[3] = '4';
+ }
+#endif
+
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ n32_adc_obj[i].ADC_Info.EnablePeriphClk(n32_adc_obj[i].ADC_Info.AHB_periph, ENABLE);
+ ADC_ConfigClk(n32_adc_obj[i].ADC_Info.ADC_ClkMode, n32_adc_obj[i].ADC_Info.RCC_ADCPrescaler);
+ RCC_ConfigAdc1mClk(n32_adc_obj[i].ADC_Info.ADC1M_ClkSource,
+ n32_adc_obj[i].ADC_Info.ADC1M_ClkPrescaler);
+#endif
ADC_Init(n32_adc_obj[i].ADC_Info.ADCx, &n32_adc_obj[i].ADC_Info.Init);
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_config.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_config.h
index 42e6334d2c..7240f96602 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_config.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_config.h
@@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2026-01-24 ox-horse first version
+ * 2026-08-28 FUNMSAN add N32H47_48x and N32H49x support
*/
#ifndef __DRV_CONFIG_H_
@@ -34,11 +35,19 @@ extern "C" {
#elif defined(SOC_SERIES_N32H49x)
#include "h49x/dma_config.h"
#include "h49x/uart_config.h"
+#include "h49x/adc_config.h"
+#include "h49x/dac_config.h"
#include "h49x/can_config.h"
+#include "h49x/spi_config.h"
+#include "h49x/i2c_hard_config.h"
#elif defined(SOC_SERIES_N32H47x_48x)
#include "h47x_48x/dma_config.h"
#include "h47x_48x/uart_config.h"
+#include "h47x_48x/adc_config.h"
+#include "h47x_48x/dac_config.h"
#include "h47x_48x/can_config.h"
+#include "h47x_48x/spi_config.h"
+#include "h47x_48x/i2c_hard_config.h"
#endif /* defined(SOC_SERIES_N32H7xx) */
#ifdef __cplusplus
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_dac.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_dac.c
index 16f4b9bb55..1a4256f3af 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_dac.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_dac.c
@@ -7,15 +7,28 @@
* Date Author Notes
* 2026-01-24 ox-horse first version
* 2026-06-09 li.mengmeng port for N32H7xx
+ * 2026-08-28 FUNMSAN add N32H47_48x and N32H49x support
*/
#include <board.h>
#include <rtthread.h>
-#if defined(BSP_USING_DAC1) || defined(BSP_USING_DAC2)
+#if defined(BSP_USING_DAC1) || defined(BSP_USING_DAC2) || \
+ (defined(SOC_SERIES_N32H47x_48x) && (defined(BSP_USING_DAC3) || defined(BSP_USING_DAC4) || \
+ defined(BSP_USING_DAC5) || defined(BSP_USING_DAC6) || defined(BSP_USING_DAC7) || \
+ defined(BSP_USING_DAC8)))
+#if defined(SOC_SERIES_N32H7xx)
#include "n32h7xx_rcc.h"
#include "n32h7xx_dac.h"
+#elif defined(SOC_SERIES_N32H47x_48x)
+#include "n32h47x_48x_rcc.h"
+#include "n32h47x_48x_dac.h"
+#elif defined(SOC_SERIES_N32H49x)
+#include "n32h49x_rcc.h"
+#include "n32h49x_dac.h"
+#endif
+
#include "drv_config.h"
//#define DRV_DEBUG
@@ -46,9 +59,32 @@ static DAC_InitInfo_t dac_config[] = {
DAC2_CONFIG,
#endif
-};
+#if defined(SOC_SERIES_N32H47x_48x)
+#ifdef BSP_USING_DAC3
+ DAC3_CONFIG,
+#endif
-static struct n32_dac n32_dac_obj[sizeof(dac_config) / sizeof(dac_config[0])];
+#ifdef BSP_USING_DAC4
+ DAC4_CONFIG,
+#endif
+
+#ifdef BSP_USING_DAC5
+ DAC5_CONFIG,
+#endif
+
+#ifdef BSP_USING_DAC6
+ DAC6_CONFIG,
+#endif
+
+#ifdef BSP_USING_DAC7
+ DAC7_CONFIG,
+#endif
+
+#ifdef BSP_USING_DAC8
+ DAC8_CONFIG,
+#endif
+#endif /* SOC_SERIES_N32H47x_48x */
+};
struct n32_dac
{
@@ -56,6 +92,8 @@ struct n32_dac
struct rt_dac_device n32_dac_device;
};
+static struct n32_dac n32_dac_obj[sizeof(dac_config) / sizeof(dac_config[0])];
+
static rt_err_t n32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
{
DAC_InitInfo_t *n32_dac_info;
@@ -86,7 +124,7 @@ static rt_uint8_t n32_dac_get_resolution(struct rt_dac_device *device)
{
RT_ASSERT(device != RT_NULL);
- /* N32H7xx DAC supports 12-bit resolution */
+ /* N32H7xx and N32H47x/48x DACs support 12-bit resolution */
return 12;
}
@@ -142,13 +180,48 @@ static int n32_dac_init(void)
{
name_buf[3] = '2';
}
+#if defined(SOC_SERIES_N32H47x_48x)
+ else if (n32_dac_obj[i].DAC_Info.DACx == DAC3)
+ {
+ name_buf[3] = '3';
+ }
+ else if (n32_dac_obj[i].DAC_Info.DACx == DAC4)
+ {
+ name_buf[3] = '4';
+ }
+ else if (n32_dac_obj[i].DAC_Info.DACx == DAC5)
+ {
+ name_buf[3] = '5';
+ }
+ else if (n32_dac_obj[i].DAC_Info.DACx == DAC6)
+ {
+ name_buf[3] = '6';
+ }
+ else if (n32_dac_obj[i].DAC_Info.DACx == DAC7)
+ {
+ name_buf[3] = '7';
+ }
+ else if (n32_dac_obj[i].DAC_Info.DACx == DAC8)
+ {
+ name_buf[3] = '8';
+ }
+#endif /* SOC_SERIES_N32H47x_48x */
/* Enable DAC peripheral clock */
n32_dac_obj[i].DAC_Info.EnablePeriphClk(n32_dac_obj[i].DAC_Info.periph_clk, ENABLE);
/* Config DAC12 prescaler factor,DAC_CLK = 1M*/
DAC_ConfigClkPrescaler(n32_dac_obj[i].DAC_Info.DAC_Module, n32_dac_obj[i].DAC_Info.DAC_clk_pres);
+#if defined(SOC_SERIES_N32H7xx) || defined(SOC_SERIES_N32H49x)
DAC_SetHighFrequencyMode(n32_dac_obj[i].DAC_Info.DAC_Module, DAC_HIGH_FREQ_MODE_BELOW_160M);
+#elif defined(SOC_SERIES_N32H47x_48x)
+ /* The high-frequency mode field is only available for DAC1~DAC4. */
+ if ((n32_dac_obj[i].DAC_Info.DAC_Module == DAC12) ||
+ (n32_dac_obj[i].DAC_Info.DAC_Module == DAC34))
+ {
+ DAC_SetHighFrequencyMode(n32_dac_obj[i].DAC_Info.DAC_Module, DAC_HIGH_FREQ_MODE_BELOW_160M);
+ }
+#endif
/* Initialize DAC */
DAC_Init(n32_dac_obj[i].DAC_Info.DACx, &n32_dac_obj[i].DAC_Info.Init);
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.c
index 071538a173..115f54a44a 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.c
@@ -9,6 +9,7 @@
*/
#include "drv_config.h"
+#include <string.h>
#include "drv_eth.h"
#include <netif/ethernetif.h>
#include <lwipopts.h>
@@ -99,10 +100,12 @@ static rt_err_t rt_n32_eth_init(rt_device_t dev)
struct rt_n32_eth *eth = (struct rt_n32_eth *)dev;
EthFuncStatusType status;
+#if defined(SOC_SERIES_N32H7xx)
/* Enable or disable PWR Clock */
RCC_EnableAHB5PeriphClk2(RCC_AHB5_PERIPHEN_PWR, ENABLE);
/* Enable or disable the power domain of the ETH */
PWR_MoudlePowerEnable(ETH_PWR_CTRL, ENABLE);
+#endif
/* Enable or disable ETH Clock */
ETH_RCC_ENABLE_AHB_PERIPHEN_CLK(ETH_RCC_AHB_PERIPHEN, ENABLE);
@@ -132,7 +135,7 @@ static rt_err_t rt_n32_eth_init(rt_device_t dev)
ETH_DeInit(ETH);
/* Set ETH initialization parameters by default */
- ETH_StructInit(ETH, &sETH_InitParam);
+ ETH_STRUCT_INIT(&sETH_InitParam);
/* Modify ETH initialization parameters (only override StructInit defaults) */
/* MAC Configuration */
@@ -687,6 +690,44 @@ static void phy_linkchange(void)
phy_speed_new |= PHY_FULL_DUPLEX;
}
+#elif defined(PHY_USING_DM9162EP)
+ /* DM9162EP: read PHY specific status register (0x11) for speed/duplex */
+ ETH_ReadPHYRegister(ETH, phy_addr, PHY_SDSR, &SR);
+ LOG_D("DM9162EP status reg is 0x%X", (unsigned int)SR);
+
+ if (PHY_Status_SPEED_100M(SR))
+ {
+ phy_speed_new |= PHY_100M;
+ }
+ else
+ {
+ phy_speed_new |= PHY_10M;
+ }
+
+ if (PHY_Status_FULL_DUPLEX(SR))
+ {
+ phy_speed_new |= PHY_FULL_DUPLEX;
+ }
+
+#elif defined(PHY_USING_LAN8720A)
+ /* LAN8720A: read PHY specific status register (0x1F) for speed/duplex */
+ ETH_ReadPHYRegister(ETH, phy_addr, PHY_SDSR, &SR);
+ LOG_D("LAN8720A status reg is 0x%X", (unsigned int)SR);
+
+ if (PHY_Status_SPEED_100M(SR))
+ {
+ phy_speed_new |= PHY_100M;
+ }
+ else
+ {
+ phy_speed_new |= PHY_10M;
+ }
+
+ if (PHY_Status_FULL_DUPLEX(SR))
+ {
+ phy_speed_new |= PHY_FULL_DUPLEX;
+ }
+
#else
/* Generic PHY: read from status register only, no extended info */
phy_speed_new |= PHY_100M;
@@ -703,12 +744,15 @@ static void phy_linkchange(void)
{
LOG_I("link up");
+#if defined(SOC_SERIES_N32H7xx)
if (phy_speed & PHY_1000M)
{
LOG_D("1000Mbps");
n32_eth_device.ETH_Speed = ETH_SPEED_1000M;
}
- else if (phy_speed & PHY_100M)
+ else
+#endif
+ if (phy_speed & PHY_100M)
{
LOG_D("100Mbps");
n32_eth_device.ETH_Speed = ETH_SPEED_100M;
@@ -734,7 +778,7 @@ static void phy_linkchange(void)
* in MACCFG (PS[15], FES[14], DM[13]), then restart everything. */
ETH_StopIT(ETH, &sEthInfo);
MODIFY_REG(ETH->MACCFG,
- (ETH_MACCFG_PS | ETH_MACCFG_FES | ETH_MACCFG_DM),
+ ETH_MACCFG_SPEED_DUPLEX_MASK,
(n32_eth_device.ETH_Speed | n32_eth_device.ETH_Mode));
ETH_StartIT(ETH, &sEthInfo);
@@ -894,7 +938,7 @@ static int rt_hw_n32_eth_init(void)
/* Set default speed based on media interface:
* GMII → 1000M, MII/RMII → 100M. Actual speed is updated after PHY auto-negotiation. */
-#if (ETH_MEDIA_INTERFACE == ETH_GMII_MODE)
+#if defined(SOC_SERIES_N32H7xx) && (ETH_MEDIA_INTERFACE == ETH_GMII_MODE)
n32_eth_device.ETH_Speed = ETH_SPEED_1000M;
#else
n32_eth_device.ETH_Speed = ETH_SPEED_100M;
@@ -1026,6 +1070,10 @@ const char *n32_eth_get_phy_name(void)
return "RTL8211EG";
#elif defined(PHY_USING_YT8522H)
return "YT8522H";
+#elif defined(PHY_USING_DM9162EP)
+ return "DM9162EP";
+#elif defined(PHY_USING_LAN8720A)
+ return "LAN8720A";
#else
return "Unknown";
#endif
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.h
index 6a636d4dd0..f0812418a9 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_eth.h
@@ -15,9 +15,15 @@
#include <rthw.h>
#include <rtdevice.h>
#include <board.h>
+#if defined(SOC_SERIES_N32H47x_48x)
+#include "n32h47x_48x_eth.h"
+#elif defined(SOC_SERIES_N32H49x)
+#include "n32h49x_eth.h"
+#elif defined(SOC_SERIES_N32H7xx)
#include "n32h7xx_eth.h"
#include "n32h7xx_rcc.h"
#include "n32h7xx_pwr.h"
+#endif
#ifdef __cplusplus
extern "C" {
@@ -25,6 +31,14 @@ extern "C" {
/* ======================= ETH Instance Selection ======================= */
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+/* n32h47x_48x / n32h49x have a single ETH instance; ETH pointer & ETH_IRQn come from the device header. */
+#define ETH_RCC_ENABLE_AHB_PERIPHEN_CLK RCC_EnableAHBPeriphClk
+#define ETH_RCC_AHB_PERIPHEN RCC_AHB_PERIPHEN_ETH
+#define ETH_GLOBAL_IRQ ETH_IRQn
+#define ETH_GLOBAL_IRQHANDLER ETH_IRQHandler
+
+#elif defined(SOC_SERIES_N32H7xx)
#if defined(BSP_USING_ETH1)
#define ETH ETH1
#define ETH_RCC_ENABLE_AHB_PERIPHEN_CLK RCC_EnableAHB2PeriphClk2
@@ -49,6 +63,8 @@ extern "C" {
#endif /* BSP_USING_ETH1 / BSP_USING_ETH2 */
+#endif /* SOC_SERIES_N32H47x_48x / SOC_SERIES_N32H7xx */
+
/* ======================= Media Interface Selection ======================= */
#if defined(ETH_INTERFACE_USING_GMII)
@@ -58,7 +74,21 @@ extern "C" {
#elif defined(ETH_INTERFACE_USING_RMII)
#define ETH_MEDIA_INTERFACE ETH_RMII_MODE
#else
-#define ETH_MEDIA_INTERFACE ETH_GMII_MODE
+#error "No ETH media interface selected (define ETH_INTERFACE_USING_GMII/MII/RMII)"
+#endif
+
+/* ======================= MACCFG Speed/Duplex Bit Mask ======================= */
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+#define ETH_MACCFG_SPEED_DUPLEX_MASK (ETH_SPEED_100M | ETH_FULL_DUPLEX_MODE)
+#else
+#define ETH_MACCFG_SPEED_DUPLEX_MASK (ETH_MACCFG_PS | ETH_MACCFG_FES | ETH_MACCFG_DM)
+#endif
+
+/* ======================= ETH_Init Param Helper ======================= */
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+#define ETH_STRUCT_INIT(p) ETH_StructInit(p)
+#else
+#define ETH_STRUCT_INIT(p) ETH_StructInit(ETH, p)
#endif
/* ======================= Standard IEEE 802.3 PHY Registers ======================= */
@@ -141,6 +171,29 @@ extern "C" {
#define PHY_INT_MASK ((1 << 15) | (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10))
#endif /* PHY_USING_YT8522H */
+/* ======================= DM9162EP PHY Specific Registers ======================= */
+
+#ifdef PHY_USING_DM9162EP
+/* DM9162EP is a Fast Ethernet PHY supporting MII/RMII, up to 100M */
+#define PHY_DM9162EP_ID1 0x0181U
+#define PHY_DM9162EP_ID2 0xB8A0U
+
+/* DM9162EP PHY Specific Status Register (0x11)
+ * bit15 = 100M Full-Duplex, bit14 = 100M Half-Duplex,
+ * bit13 = 10M Full-Duplex, bit12 = 10M Half-Duplex */
+#define PHY_SDSR 0x11U
+#define PHY_Status_SPEED_100M(sr) (((sr) & ((1 << 15) | (1 << 14))) != 0)
+#define PHY_Status_SPEED_10M(sr) (!PHY_Status_SPEED_100M(sr))
+#define PHY_Status_FULL_DUPLEX(sr) (((sr) & ((1 << 15) | (1 << 13))) != 0)
+
+/* DM9162EP PHY Specific Interrupt Registers
+ * 0x15 Interrupt Source Flag / Interrupt Mask */
+#define PHY_INTERRUPT_FLAG_REG 0x15U
+#define PHY_INTERRUPT_MASK_REG 0x15U
+#define PHY_INT_MASK 0U
+
+#endif /* PHY_USING_DM9162EP */
+
/* ======================= RTL8211EG PHY Specific Registers ======================= */
#ifdef PHY_USING_RTL8211EG
@@ -166,6 +219,28 @@ extern "C" {
#define PHY_INT_MASK ((1 << 15) | (1 << 11) | (1 << 10))
#endif /* PHY_USING_RTL8211EG */
+/* ======================= LAN8720A PHY Specific Registers ======================= */
+
+#ifdef PHY_USING_LAN8720A
+/* LAN8720A is a Fast Ethernet PHY supporting MII/RMII, up to 100M */
+#define PHY_LAN8720A_ID1 0x0007U
+#define PHY_LAN8720A_ID2 0xC0F1U
+
+/* LAN8720A PHY Specific Status Register (0x1F)
+ * bit4 = Full-Duplex, bit3 = 100M, bit2 = 10M */
+#define PHY_SDSR 0x1FU
+#define PHY_Status_SPEED_100M(sr) (((sr) & (1 << 3)) != 0)
+#define PHY_Status_SPEED_10M(sr) (((sr) & (1 << 2)) != 0)
+#define PHY_Status_FULL_DUPLEX(sr) (((sr) & (1 << 4)) != 0)
+
+/* LAN8720A PHY Specific Interrupt Registers
+ * 0x1D Interrupt Source Flag, 0x1E Interrupt Mask */
+#define PHY_INTERRUPT_FLAG_REG 0x1DU
+#define PHY_INTERRUPT_MASK_REG 0x1EU
+#define PHY_INT_MASK (1 << 4)
+
+#endif /* PHY_USING_LAN8720A */
+
/* ======================= Buffer & Descriptor Configuration ======================= */
#ifndef ETH_TX_DESC_NUMBER
@@ -175,7 +250,12 @@ extern "C" {
#define ETH_RX_DESC_NUMBER ((uint32_t)4U)
#endif
-/* ETH_MAX_PACKET_SIZE is defined in n32h7xx_eth.h (1528U) */
+/* ETH_MAX_PACKET_SIZE is defined in n32h7xx_eth.h (1528U); n32h47x_48x has no such macro. */
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+#ifndef ETH_MAX_PACKET_SIZE
+#define ETH_MAX_PACKET_SIZE (1528U)
+#endif
+#endif
#define ETH_TX_BUF_SIZE (ETH_TX_DESC_NUMBER * ETH_MAX_PACKET_SIZE)
#define ETH_RX_BUF_SIZE (ETH_RX_DESC_NUMBER * ETH_MAX_PACKET_SIZE)
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.c
index f63d680db4..a3ab1844c3 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.c
@@ -24,40 +24,17 @@
static uint32_t pin_irq_enable_mask = 0;
-#if defined(GPIOK)
+
#if defined(SOC_SERIES_N32H7xx)
+
+#define __N32_PORT_MAX 11u
+
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
#define __N32_PORT_MAX 8u
+
#endif
-#elif defined(GPIOJ)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOI)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOH)
-#if defined(SOC_SERIES_N32H7xx)
-#define __N32_PORT_MAX 16u
-#elif defined(SOC_SERIES_N32H49x)
-#define __N32_PORT_MAX 6u
-#elif defined(SOC_SERIES_N32H47x_48x)
-#define __N32_PORT_MAX 7u
-#endif
-#elif defined(GPIOG)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOF)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOE)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOD)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOC)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOB)
-#define __N32_PORT_MAX 16u
-#elif defined(GPIOA)
-#define __N32_PORT_MAX 16u
-#else
-#define __N32_PORT_MAX 0u
-#error Unsupported N32 GPIO peripheral.
-#endif
+
#define PIN_STPORT_MAX __N32_PORT_MAX
@@ -390,12 +367,12 @@ static rt_err_t n32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
break;
case PIN_IRQ_MODE_FALLING:
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
- GPIO_InitStructure.GPIO_Pull = GPIO_PULL_DOWN;
+ GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
break;
case PIN_IRQ_MODE_RISING_FALLING:
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
- GPIO_InitStructure.GPIO_Pull = GPIO_NO_PULL;
+ GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
break;
}
@@ -476,25 +453,49 @@ rt_inline void pin_irq_hdr(int irqno)
void N32_GPIO_EXTI_Callback(uint16_t line_num)
{
-#if defined(SOC_SERIES_N32H7xx)
- if (pin_irq_hdr_tab[line_num].pin != -1 && EXTI_GetITStatus(line_num) != RESET)
+#if defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+ if (EXTI_GetITStatus(line_num) != RESET)
{
/* Clear EXTI line pending bit */
EXTI_ClrITPendBit(line_num);
- pin_irq_hdr(line_num);
- }
-#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
- {
- rt_int32_t idx = bit2bitno(line_num);
- if (idx >= 0 && idx < (rt_int32_t)ITEM_NUM(pin_irq_hdr_tab) && pin_irq_hdr_tab[idx].pin != -1 && EXTI_GetITStatus(line_num) != RESET)
+ uint8_t index = 0;
+ uint32_t mask = line_num;
+
+ if (mask & 0xFF00)
+ {
+ index += 8;
+ mask >>= 8;
+ }
+ if (mask & 0xF0)
+ {
+ index += 4;
+ mask >>= 4;
+ }
+ if (mask & 0xC)
+ {
+ index += 2;
+ mask >>= 2;
+ }
+ if (mask & 0x2)
{
- /* Clear EXTI line pending bit */
- EXTI_ClrITPendBit(line_num);
+ index += 1;
+ }
- pin_irq_hdr(idx);
+ if ((index < 16) && (pin_irq_hdr_tab[index].pin != -1))
+ {
+ pin_irq_hdr(index);
}
}
+#elif defined(SOC_SERIES_N32H7xx)
+ if (pin_irq_hdr_tab[line_num].pin != -1 && EXTI_GetITStatus(line_num) != RESET)
+ {
+ /* Clear EXTI line pending bit */
+ EXTI_ClrITPendBit(line_num);
+
+ pin_irq_hdr(line_num);
+ }
#endif
}
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.h
index db0ff4852b..65db994088 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_gpio.h
@@ -14,6 +14,7 @@
#include <rtdevice.h>
#include <board.h>
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.c
index 3fa639d58d..e5f88e87a5 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.c
@@ -18,9 +18,11 @@
#if defined(BSP_USING_HARD_I2C1) || defined(BSP_USING_HARD_I2C2) || defined(BSP_USING_HARD_I2C3) || defined(BSP_USING_HARD_I2C4) || defined(BSP_USING_HARD_I2C5) || \
defined(BSP_USING_HARD_I2C6) || defined(BSP_USING_HARD_I2C7) || defined(BSP_USING_HARD_I2C8) || defined(BSP_USING_HARD_I2C9) || defined(BSP_USING_HARD_I2C10)
+#define MAX_NBYTE_SIZE (255U)
+
+#if defined(SOC_SERIES_N32H7xx)
#define I2C_CTRL2_NBYTES_POS (16U)
-#define MAX_NBYTE_SIZE (255U)
#define I2C_NO_STARTSTOP (0x00000000U)
#define I2C_START_READ (I2C_CTRL2_START | I2C_CTRL2_RWN)
@@ -40,14 +42,157 @@
/* Slave address | Transfer direction | START generation | STOP generation | Number of bytes | NBYTES reload mode | Automatic end mode */
#define I2C_CTRL2_CLEAR (I2C_CTRL2_SADR | I2C_CTRL2_RWN | I2C_CTRL2_START | I2C_CTRL2_STOP | I2C_CTRL2_BYTECNT | I2C_CTRL2_REFILL | I2C_CTRL2_AUTOSTOP)
+static rt_bool_t first_valid_rx_isr = RT_FALSE;
+
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+#define I2C_RELOAD_MODE (0x00000000U)
+#define I2C_FIRST_FRAME (0x00000000U)
+#define I2C_FIRST_AND_NEXT_FRAME (0x00000000U)
+#define I2C_LAST_FRAME (0x00000000U)
+#define I2C_LAST_FRAME_NO_STOP (0x00000000U)
+
+#endif
//#define DRV_DEBUG
#define LOG_TAG "drv.i2c.hw"
#include <drv_log.h>
-static rt_bool_t first_valid_rx_isr = RT_FALSE;
static void i2c_master_ev_isr_handler_it(struct n32_i2c *drv_i2c);
static void i2c_master_ev_isr_handler_dma(struct n32_i2c *drv_i2c);
+#if defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+/* Wait for the bus to fall idle before asserting a new START.
+ *
+ * Asserting START while a previous STOP is still on the wire wedges the state
+ * machine: BUSY stays set, SB stays set, the address sits unsent in DAT and
+ * ADDRF never arrives. Callers must abort the transfer rather than start it.
+ */
+static rt_err_t n32_i2c_wait_bus_idle(I2C_Module *Instance)
+{
+ rt_uint32_t timeout = 1000000U;
+
+ while (((Instance->STS2 & I2C_STS2_BUSY) == I2C_STS2_BUSY) && (--timeout > 0U))
+ {
+ }
+
+ return (timeout != 0U) ? RT_EOK : -RT_ETIMEOUT;
+}
+
+/* Clear residue left by an aborted transfer before asserting a new START.
+ *
+ * A STOPGEN that was latched with no frame to terminate stays pending and would
+ * tear down the START we are about to generate. Stale status flags would
+ * likewise fire the moment the new transfer re-enables the error interrupt.
+ */
+static void n32_i2c_prepare_start(I2C_Module *Instance)
+{
+ Instance->CTRL1 &= ~(I2C_CTRL1_STOPGEN | I2C_CTRL1_STARTGEN);
+
+ I2C_ClrIntPendingBit(Instance,
+ I2C_INT_ACKFAIL | I2C_INT_BUSERR | I2C_INT_ARLOST |
+ I2C_INT_OVERRUN | I2C_INT_PECERR);
+}
+
+/* Tear down a transfer that the waiting thread has given up on.
+ *
+ * Must disarm the ISR before returning: master_xfer's callers pass stack
+ * buffers, so a late RXDATNE writing through transfer.pBuffPtr would corrupt
+ * a stack frame that no longer exists once the caller unwinds.
+ */
+static void n32_i2c_abort_transfer(struct n32_i2c *i2c_obj)
+{
+ I2C_Module *Instance = i2c_obj->config->Instance;
+
+ /* Disable interrupts and DMA first - stop the ISR touching pBuffPtr */
+ I2C_ConfigInt(Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, DISABLE);
+ I2C_EnableDMA(Instance, DISABLE);
+
+ i2c_obj->i2c_isr_callback = RT_NULL;
+ i2c_obj->transfer.pBuffPtr = RT_NULL;
+ i2c_obj->transfer.XferCount = 0;
+ i2c_obj->transfer.XferSize = 0;
+ i2c_obj->transfer.state = I2C_READY;
+
+ /* Release the bus only if we still own it, then clear residue */
+ if ((Instance->STS2 & I2C_STS2_BUSY) == I2C_STS2_BUSY)
+ {
+ Instance->CTRL1 |= I2C_CTRL1_STOPGEN;
+ (void)n32_i2c_wait_bus_idle(Instance);
+ }
+
+ n32_i2c_prepare_start(Instance);
+}
+
+/* Generate START, send the slave address, and clear ADDRF so the data phase
+ * (and therefore the DMA request) can begin. The DMA paths cannot rely on the
+ * event ISR to clear ADDRF (they enable EVTINTEN only after the DMA transfer
+ * completes, to catch STOPF), so the address phase is handled synchronously.
+ */
+static rt_err_t n32_i2c_master_start_addr(struct n32_i2c *i2c, uint8_t DevAddress, uint8_t Direction)
+{
+ I2C_Module *Instance = i2c->config->Instance;
+
+ /* Wait for the previous STOP to complete */
+ if (n32_i2c_wait_bus_idle(Instance) != RT_EOK)
+ {
+ return -RT_ETIMEOUT;
+ }
+
+ /* Drop any STOPGEN/flags left latched by an aborted transfer */
+ n32_i2c_prepare_start(Instance);
+
+ /* Generate START condition */
+ I2C_GenerateStart(Instance, ENABLE);
+
+ /* Wait for START generation to complete before sending address */
+ {
+ rt_uint32_t timeout = 1000000U;
+ while (!(Instance->STS1 & I2C_STS1_STARTBF) && (--timeout > 0U))
+ {
+ }
+ if (timeout == 0U)
+ {
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /* Send the 7-bit slave address (this write clears STARTBF) */
+ I2C_SendAddr7bit(Instance, DevAddress, Direction);
+
+ /* Wait for the address phase to finish, then clear ADDRF so the data phase
+ * (and therefore the DMA request) can begin. */
+ {
+ rt_uint32_t timeout = 1000000U;
+ while (!(Instance->STS1 & (I2C_STS1_ADDRF | I2C_STS1_ACKFAIL)) && (--timeout > 0U))
+ {
+ }
+ if (timeout == 0U)
+ {
+ return -RT_ETIMEOUT;
+ }
+ if (Instance->STS1 & I2C_STS1_ACKFAIL)
+ {
+ return -RT_ERROR;
+ }
+ /* Clear ADDRF by reading STS1 then STS2 */
+ {
+ volatile uint32_t sr1 = Instance->STS1;
+ volatile uint32_t sr2 = Instance->STS2;
+ (void)sr1;
+ (void)sr2;
+ }
+ }
+
+ return RT_EOK;
+}
+#endif /* defined(SOC_SERIES_N32H49x) */
+
+#if defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+#define I2C_ABORT_ON_TIMEOUT(obj) n32_i2c_abort_transfer(obj)
+#else
+#define I2C_ABORT_ON_TIMEOUT(obj) ((obj)->transfer.state = I2C_READY)
+#endif
+
enum
{
#ifdef BSP_USING_HARD_I2C1
@@ -166,6 +311,41 @@ static rt_ssize_t n32_iic_transfer_by_dma(struct n32_i2c_config *config, uint8_t
/* Enable the specified DMA channel */
DMA_ChannelCmd(dma_config->Instance, dma_config->dma_channel, ENABLE);
+
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Disable DMA channel before reconfiguration */
+ DMA_EnableChannel(dma_config->DMAChx, DISABLE);
+
+ /* Configure DMA request remapping */
+ DMA_RequestRemap(dma_config->request, dma_config->DMAChx, ENABLE);
+
+ {
+ DMA_InitType *dma_init_str;
+
+ if (is_rx)
+ {
+ dma_init_str = &config->dma_rx_init_str;
+ dma_init_str->PeriphAddr = (uint32_t)&config->Instance->DAT;
+ dma_init_str->MemAddr = (uint32_t)pData;
+ dma_init_str->Direction = DMA_DIR_PERIPH_SRC;
+ }
+ else
+ {
+ dma_init_str = &config->dma_tx_init_str;
+ dma_init_str->PeriphAddr = (uint32_t)&config->Instance->DAT;
+ dma_init_str->MemAddr = (uint32_t)pData;
+ dma_init_str->Direction = DMA_DIR_PERIPH_DST;
+ }
+ dma_init_str->BufSize = Size;
+
+ DMA_Init(dma_config->DMAChx, dma_init_str);
+ }
+
+ /* Enable transfer complete interrupt */
+ DMA_ConfigInt(dma_config->DMAChx, DMA_INT_TXC, ENABLE);
+
+ /* Enable the specified DMA channel */
+ DMA_EnableChannel(dma_config->DMAChx, ENABLE);
#endif
return Size;
@@ -175,11 +355,13 @@ static rt_ssize_t n32_iic_transfer_by_dma(struct n32_i2c_config *config, uint8_t
static rt_err_t n32_i2c_dma_init(struct n32_i2c_config *config, rt_bool_t is_rx)
{
struct dma_config *dma_config;
- DMA_ChInitType DMA_ChInitStr;
+
RT_ASSERT(config != RT_NULL);
#if defined(SOC_SERIES_N32H7xx)
+
+ DMA_ChInitType DMA_ChInitStr;
/* Enable DMAMUX clock */
RCC_EnableAHB1PeriphClk1(RCC_AHB1_PERIPHEN_M7_DMAMUX1, ENABLE);
@@ -235,6 +417,53 @@ static rt_err_t n32_i2c_dma_init(struct n32_i2c_config *config, rt_bool_t is_rx)
{
return -RT_ERROR;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ {
+ DMA_InitType *dma_init_str;
+
+ if (is_rx)
+ {
+ dma_config = config->dma_rx;
+ dma_init_str = &config->dma_rx_init_str;
+
+ /* DMA clock enable */
+ RCC_EnableAHBPeriphClk(dma_config->dma_rcc, ENABLE);
+
+ /* Initialize the persistent DMA init struct */
+ DMA_StructInit(dma_init_str);
+ dma_init_str->PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
+ dma_init_str->MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
+ dma_init_str->MemoryInc = DMA_MEM_INC_ENABLE;
+ dma_init_str->Direction = DMA_DIR_PERIPH_SRC;
+ dma_init_str->Priority = DMA_PRIORITY_HIGH;
+ dma_init_str->PeriphAddr = (uint32_t)&config->Instance->DAT;
+ dma_init_str->MemAddr = (uint32_t)RT_NULL;
+ }
+ else
+ {
+ dma_config = config->dma_tx;
+ dma_init_str = &config->dma_tx_init_str;
+
+ /* DMA clock enable */
+ RCC_EnableAHBPeriphClk(dma_config->dma_rcc, ENABLE);
+
+ /* Initialize the persistent DMA init struct */
+ DMA_StructInit(dma_init_str);
+ dma_init_str->PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
+ dma_init_str->MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
+ dma_init_str->MemoryInc = DMA_MEM_INC_ENABLE;
+ dma_init_str->Direction = DMA_DIR_PERIPH_DST;
+ dma_init_str->Priority = DMA_PRIORITY_HIGH;
+ dma_init_str->PeriphAddr = (uint32_t)&config->Instance->DAT;
+ dma_init_str->MemAddr = (uint32_t)RT_NULL;
+ }
+
+ /* Disable channel before configuration */
+ DMA_EnableChannel(dma_config->DMAChx, DISABLE);
+ }
+#endif
+
+#if defined(SOC_SERIES_N32H7xx) || defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
/* enable dma irq */
NVIC_SetPriority(dma_config->dma_irq, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(dma_config->dma_irq);
@@ -246,8 +475,8 @@ static rt_err_t n32_i2c_dma_init(struct n32_i2c_config *config, rt_bool_t is_rx)
static rt_err_t n32_i2c_init(struct n32_i2c *i2c_drv)
{
rt_err_t ret;
- uint32_t BusTim_Reg = 0;
- I2C_InitType I2C_InitStructure;
+
+
RT_ASSERT(i2c_drv != RT_NULL);
struct n32_i2c_config *cfg = i2c_drv->config;
@@ -256,6 +485,8 @@ static rt_err_t n32_i2c_init(struct n32_i2c *i2c_drv)
cfg->EnablePeriphClk(cfg->periph, ENABLE);
#if defined(SOC_SERIES_N32H7xx)
+ I2C_InitType I2C_InitStructure;
+ uint32_t BusTim_Reg;
/* Call I2C_Configuration() from an external file */
I2C_Configuration();
/* Disable IIC */
@@ -278,10 +509,13 @@ static rt_err_t n32_i2c_init(struct n32_i2c *i2c_drv)
}
#endif
+#if defined(SOC_SERIES_N32H7xx)
+
/* Deinitializes the I2Cx peripheral registers to their default reset values */
I2C_DeInit(cfg->Instance);
I2C_InitStruct(&I2C_InitStructure);
+
I2C_InitStructure.Timing = ((BusTim_Reg != 0) ? BusTim_Reg : cfg->timing);
I2C_InitStructure.OwnAddress1 = 0x0;
I2C_InitStructure.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
@@ -290,10 +524,14 @@ static rt_err_t n32_i2c_init(struct n32_i2c *i2c_drv)
I2C_InitStructure.OwnAddress2Masks = I2C_ADDRESS2MASK_NONE;
I2C_InitStructure.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2C_InitStructure.NoStretchMode = I2C_NOSTRCH_DISABLE;
+
I2C_Init(cfg->Instance, &I2C_InitStructure);
I2C_Enable(cfg->Instance, ENABLE);
+#endif
+
+
#if defined(SOC_SERIES_N32H7xx)
/* Configure Analogue filter */
I2C_EnableAnalogFilter(cfg->Instance, ENABLE);
@@ -304,6 +542,16 @@ static rt_err_t n32_i2c_init(struct n32_i2c *i2c_drv)
/* Configure Digital filter */
I2C_SetDigitalFilterWidth(cfg->Instance, cfg->df_width);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Configure Analogue filter */
+ I2C_EnableSCLAnalogFilter(cfg->Instance, ENABLE);
+ I2C_EnableSDAAnalogFilter(cfg->Instance, ENABLE);
+ I2C_SetSCLAnalogFilterWidth(cfg->Instance, cfg->scl_af_width);
+ I2C_SetSDAAnalogFilterWidth(cfg->Instance, cfg->sda_af_width);
+
+ /* Configure Digital filter */
+ I2C_SetSCLDigitalFilterWidth(cfg->Instance, cfg->df_width);
+ I2C_SetSDADigitalFilterWidth(cfg->Instance, cfg->df_width);
#endif /* defined(SOC_SERIES_N32H7xx) */
/* I2C2 DMA Init */
@@ -334,6 +582,7 @@ static rt_err_t n32_i2c_init(struct n32_i2c *i2c_drv)
static rt_err_t n32_i2c_master_seq_receive_it(struct n32_i2c *i2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
{
+#if defined(SOC_SERIES_N32H7xx)
uint32_t setmask;
uint32_t xfermode;
@@ -373,10 +622,91 @@ static rt_err_t n32_i2c_master_seq_receive_it(struct n32_i2c *i2c, uint16_t DevA
{
return -RT_EBUSY;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+ if (i2c->transfer.state == I2C_READY)
+ {
+ /* Set transfer parameters */
+ i2c->transfer.state = I2C_BUSY_RX;
+ i2c->transfer.pBuffPtr = pData;
+ i2c->transfer.XferCount = Size;
+ i2c->transfer.XferOptions = XferOptions;
+ i2c->i2c_isr_callback = i2c_master_ev_isr_handler_it;
+
+ /* If Size > MAX_NBYTE_SIZE, use reload mode */
+ if (Size > MAX_NBYTE_SIZE)
+ {
+ i2c->transfer.XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ i2c->transfer.XferSize = i2c->transfer.XferCount;
+ }
+
+
+#if defined(SOC_SERIES_N32H49x)
+ I2C_EnableByteNum(i2c->config->Instance, ENABLE);
+ /* Set the number of bytes to receive via BYTENUM register */
+ I2C_SetMasterReceivedDataBytesNum(i2c->config->Instance, i2c->transfer.XferSize);
+#elif defined(SOC_SERIES_N32H47x_48x)
+ I2C_EnableBYTENUM(i2c->config->Instance, ENABLE);
+ I2C_SetReceivedDataBytesNum(i2c->config->Instance, i2c->transfer.XferSize);
+#endif
+ /* Enable ACK for multi-byte receive (NACK for last byte handled in ISR) */
+ if (i2c->transfer.XferCount > 1U)
+ {
+ I2C_ConfigAck(i2c->config->Instance, ENABLE);
+ }
+
+ /* Wait for the previous STOP to complete. Toggling PE here would not
+ * reset the state machine while BUSY is set, and could hold the lines.
+ */
+ if (n32_i2c_wait_bus_idle(i2c->config->Instance) != RT_EOK)
+ {
+ i2c->transfer.state = I2C_READY;
+ return -RT_ETIMEOUT;
+ }
+
+ /* Drop any STOPGEN/flags left latched by an aborted transfer */
+ n32_i2c_prepare_start(i2c->config->Instance);
+
+ /* Generate START condition */
+ I2C_GenerateStart(i2c->config->Instance, ENABLE);
+
+ /* Wait for START generation to complete before sending address */
+ {
+ rt_uint32_t timeout = 1000000U;
+ while (!(i2c->config->Instance->STS1 & I2C_STS1_STARTBF) && (--timeout > 0U))
+ {
+ }
+ if (timeout == 0U)
+ {
+ i2c->transfer.state = I2C_READY;
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /* Send START and 7-bit slave address with read direction.
+ * This write also clears STARTBF, which must happen before the event
+ * interrupt is enabled - an unhandled pending SB would storm the ISR.
+ */
+ I2C_SendAddr7bit(i2c->config->Instance, (uint8_t)(DevAddress), I2C_DIRECTION_RECV);
+
+ /* Enable Buffer, Event and Error interrupts (after address to avoid STARTBF) */
+ I2C_ConfigInt(i2c->config->Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, ENABLE);
+
+ return RT_EOK;
+ }
+ else
+ {
+ return -RT_EBUSY;
+ }
+#endif
}
static rt_err_t n32_i2c_master_seq_send_it(struct n32_i2c *i2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
{
+#if defined(SOC_SERIES_N32H7xx)
uint32_t setmask;
uint32_t xfermode;
@@ -406,9 +736,17 @@ static rt_err_t n32_i2c_master_seq_send_it(struct n32_i2c *i2c, uint16_t DevAddr
/* Slave address | Transfer direction | START generation | STOP generation | Number of bytes | NBYTES reload mode | Automatic end mode */
setmask = ((uint32_t)DevAddress & I2C_CTRL2_SADR) | (uint32_t)I2C_START_WRITE | (((uint32_t)i2c->transfer.XferSize << I2C_CTRL2_NBYTES_POS) & I2C_CTRL2_BYTECNT) | (uint32_t)xfermode;
- /* Wait for bus idele */
- while ((i2c->config->Instance->STSINT & I2C_STSINT_BUSY) == I2C_STSINT_BUSY)
+ /* Wait for bus idle with timeout to prevent deadlock */
{
+ rt_uint32_t timeout_cnt = 1000000U;
+ while ((i2c->config->Instance->STSINT & I2C_STSINT_BUSY) == I2C_STSINT_BUSY && (--timeout_cnt > 0U))
+ {
+ }
+ if (timeout_cnt == 0U)
+ {
+ i2c->transfer.state = I2C_READY;
+ return -RT_ETIMEOUT;
+ }
}
/* Set IIC CTRL2 Register */
@@ -420,16 +758,82 @@ static rt_err_t n32_i2c_master_seq_send_it(struct n32_i2c *i2c, uint16_t DevAddr
{
return -RT_EBUSY;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+ if (i2c->transfer.state == I2C_READY)
+ {
+ /* Set transfer parameters */
+ i2c->transfer.state = I2C_BUSY_TX;
+ i2c->transfer.pBuffPtr = pData;
+ i2c->transfer.XferCount = Size;
+ i2c->transfer.XferOptions = XferOptions;
+ i2c->i2c_isr_callback = i2c_master_ev_isr_handler_it;
+
+ /* If Size > MAX_NBYTE_SIZE, use reload mode */
+ if (Size > MAX_NBYTE_SIZE)
+ {
+ i2c->transfer.XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ i2c->transfer.XferSize = i2c->transfer.XferCount;
+ }
+
+ /* Wait for the previous STOP to complete. Toggling PE here would not
+ * reset the state machine while BUSY is set, and could hold the lines.
+ */
+ if (n32_i2c_wait_bus_idle(i2c->config->Instance) != RT_EOK)
+ {
+ i2c->transfer.state = I2C_READY;
+ return -RT_ETIMEOUT;
+ }
+
+ /* Drop any STOPGEN/flags left latched by an aborted transfer */
+ n32_i2c_prepare_start(i2c->config->Instance);
+
+ /* Generate START condition */
+ I2C_GenerateStart(i2c->config->Instance, ENABLE);
+
+ /* Wait for START generation to complete before sending address */
+ {
+ rt_uint32_t timeout = 1000000U;
+ while (!(i2c->config->Instance->STS1 & I2C_STS1_STARTBF) && (--timeout > 0U))
+ {
+ }
+ if (timeout == 0U)
+ {
+ i2c->transfer.state = I2C_READY;
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /* Send START and 7-bit slave address with write direction.
+ * This write also clears STARTBF, which must happen before the event
+ * interrupt is enabled - an unhandled pending SB would storm the ISR.
+ */
+ I2C_SendAddr7bit(i2c->config->Instance, (uint8_t)(DevAddress), I2C_DIRECTION_SEND);
+
+ /* Enable Buffer, Event and Error interrupts (after address to avoid STARTBF) */
+ I2C_ConfigInt(i2c->config->Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, ENABLE);
+
+ return RT_EOK;
+ }
+ else
+ {
+ return -RT_EBUSY;
+ }
+#endif
}
static rt_err_t n32_i2c_master_seq_receive_dma(struct n32_i2c *i2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
{
+#if defined(SOC_SERIES_N32H7xx)
uint32_t setmask;
uint32_t xfermode;
+#endif
if (i2c->transfer.state == I2C_READY)
{
- first_valid_rx_isr = RT_FALSE;
/* Set transfer parameters */
i2c->transfer.state = I2C_BUSY_RX;
i2c->transfer.pBuffPtr = pData;
@@ -441,18 +845,23 @@ static rt_err_t n32_i2c_master_seq_receive_dma(struct n32_i2c *i2c, uint16_t Dev
if (Size > MAX_NBYTE_SIZE)
{
i2c->transfer.XferSize = MAX_NBYTE_SIZE;
+#if defined(SOC_SERIES_N32H7xx)
xfermode = I2C_RELOAD_MODE; // Use reload mode
+#endif
}
else
{
i2c->transfer.XferSize = i2c->transfer.XferCount;
+#if defined(SOC_SERIES_N32H7xx)
xfermode = i2c->transfer.XferOptions;
+#endif
}
if (i2c->transfer.XferSize > 0U)
{
n32_iic_transfer_by_dma(i2c->config, i2c->transfer.pBuffPtr, i2c->transfer.XferSize, RT_TRUE);
+#if defined(SOC_SERIES_N32H7xx)
/* Slave address | Transfer direction | START generation | STOP generation | Number of bytes | NBYTES reload mode | Automatic end mode */
setmask = ((uint32_t)DevAddress & I2C_CTRL2_SADR) | (uint32_t)I2C_START_READ | (((uint32_t)i2c->transfer.XferSize << I2C_CTRL2_NBYTES_POS) & I2C_CTRL2_BYTECNT) | (uint32_t)xfermode;
@@ -467,11 +876,45 @@ static rt_err_t n32_i2c_master_seq_receive_dma(struct n32_i2c *i2c, uint16_t Dev
/* Enable DMA Request */
i2c->config->Instance->CTRL1 |= I2C_CTRL1_DMARDEN;
+
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Update XferCount value */
+ i2c->transfer.XferCount -= i2c->transfer.XferSize;
+#if defined(SOC_SERIES_N32H49x)
+ I2C_EnableByteNum(i2c->config->Instance, ENABLE);
+ /* Set the number of bytes to receive via BYTENUM register */
+ I2C_SetMasterReceivedDataBytesNum(i2c->config->Instance, i2c->transfer.XferSize);
+#elif defined(SOC_SERIES_N32H47x_48x)
+ I2C_EnableBYTENUM(i2c->config->Instance, ENABLE);
+ I2C_SetReceivedDataBytesNum(i2c->config->Instance, i2c->transfer.XferSize);
+#endif
+ /* Enable ACK so the slave keeps sending; BYTENUM auto-NACKs the
+ * last byte once the configured count is reached. */
+ I2C_ConfigAck(i2c->config->Instance, ENABLE);
+
+ /* Enable DMA Request */
+ I2C_EnableDMA(i2c->config->Instance, ENABLE);
+
+ /* Enable Buffer and Error interrupts */
+ I2C_ConfigInt(i2c->config->Instance, I2C_INT_BUF | I2C_INT_ERR, ENABLE);
+
+ /* Generate START, send the slave address, and clear ADDRF so the
+ * data phase (and thus the DMA request) can begin. */
+ {
+ rt_err_t start_ret = n32_i2c_master_start_addr(i2c, (uint8_t)DevAddress, I2C_DIRECTION_RECV);
+ if (start_ret != RT_EOK)
+ {
+ i2c->transfer.state = I2C_READY;
+ return start_ret;
+ }
+ }
+#endif
}
else
{
i2c->i2c_isr_callback = i2c_master_ev_isr_handler_it;
+#if defined(SOC_SERIES_N32H7xx)
/* Slave address | Transfer direction | START generation | STOP generation | Number of bytes | NBYTES reload mode | Automatic end mode */
setmask = ((uint32_t)DevAddress & I2C_CTRL2_SADR) | (uint32_t)I2C_START_READ | (((uint32_t)i2c->transfer.XferSize << I2C_CTRL2_NBYTES_POS) & I2C_CTRL2_BYTECNT) | (uint32_t)I2C_AUTOEND_MODE;
@@ -479,6 +922,11 @@ static rt_err_t n32_i2c_master_seq_receive_dma(struct n32_i2c *i2c, uint16_t Dev
MODIFY_REG(i2c->config->Instance->CTRL2, I2C_CTRL2_CLEAR, (uint32_t)setmask);
i2c->config->Instance->CTRL1 |= (I2C_CTRL1_ERRIE | I2C_CTRL1_TFCIE | I2C_CTRL1_STOPIE | I2C_CTRL1_NAKIE | I2C_CTRL1_WDRIE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Empty transfer - send START+ADDR then generate STOP */
+ I2C_ConfigInt(i2c->config->Instance, I2C_INT_EVENT | I2C_INT_ERR, ENABLE);
+ I2C_SendAddr7bit(i2c->config->Instance, (uint8_t)(DevAddress), I2C_DIRECTION_RECV);
+#endif
}
return RT_EOK;
@@ -491,8 +939,10 @@ static rt_err_t n32_i2c_master_seq_receive_dma(struct n32_i2c *i2c, uint16_t Dev
static rt_err_t n32_i2c_master_seq_send_dma(struct n32_i2c *i2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
{
+#if defined(SOC_SERIES_N32H7xx)
uint32_t setmask;
uint32_t xfermode;
+#endif
if (i2c->transfer.state == I2C_READY)
{
@@ -507,18 +957,23 @@ static rt_err_t n32_i2c_master_seq_send_dma(struct n32_i2c *i2c, uint16_t DevAdd
if (Size > MAX_NBYTE_SIZE)
{
i2c->transfer.XferSize = MAX_NBYTE_SIZE;
+#if defined(SOC_SERIES_N32H7xx)
xfermode = I2C_RELOAD_MODE; // Use reload mode
+#endif
}
else
{
i2c->transfer.XferSize = i2c->transfer.XferCount;
+#if defined(SOC_SERIES_N32H7xx)
xfermode = i2c->transfer.XferOptions;
+#endif
}
if (i2c->transfer.XferSize > 0U)
{
n32_iic_transfer_by_dma(i2c->config, i2c->transfer.pBuffPtr, i2c->transfer.XferSize, RT_FALSE);
+#if defined(SOC_SERIES_N32H7xx)
/* Slave address | Transfer direction | START generation | STOP generation | Number of bytes | NBYTES reload mode | Automatic end mode */
setmask = ((uint32_t)DevAddress & I2C_CTRL2_SADR) | (uint32_t)I2C_START_WRITE | (((uint32_t)i2c->transfer.XferSize << I2C_CTRL2_NBYTES_POS) & I2C_CTRL2_BYTECNT) | (uint32_t)xfermode;
@@ -533,11 +988,39 @@ static rt_err_t n32_i2c_master_seq_send_dma(struct n32_i2c *i2c, uint16_t DevAdd
/* Enable DMA Request */
i2c->config->Instance->CTRL1 |= I2C_CTRL1_DMAWREN;
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Update XferCount value */
+ i2c->transfer.XferCount -= i2c->transfer.XferSize;
+
+ /* Enable DMA Request */
+ I2C_EnableDMA(i2c->config->Instance, ENABLE);
+
+ /* If this is the last frame, enable DMA Last Transfer to auto-generate STOP */
+ if (i2c->transfer.XferCount == 0U)
+ {
+ I2C_EnableDmaLastSend(i2c->config->Instance, ENABLE);
+ }
+
+ /* Enable Buffer and Error interrupts */
+ I2C_ConfigInt(i2c->config->Instance, I2C_INT_BUF | I2C_INT_ERR, ENABLE);
+
+ /* Generate START, send the slave address, and clear ADDRF so the
+ * data phase (and thus the DMA request) can begin. */
+ {
+ rt_err_t start_ret = n32_i2c_master_start_addr(i2c, (uint8_t)DevAddress, I2C_DIRECTION_SEND);
+ if (start_ret != RT_EOK)
+ {
+ i2c->transfer.state = I2C_READY;
+ return start_ret;
+ }
+ }
+#endif
}
else
{
i2c->i2c_isr_callback = i2c_master_ev_isr_handler_it;
+#if defined(SOC_SERIES_N32H7xx)
/* Slave address | Transfer direction | START generation | STOP generation | Number of bytes | NBYTES reload mode | Automatic end mode */
setmask = ((uint32_t)DevAddress & I2C_CTRL2_SADR) | (uint32_t)I2C_START_WRITE | (((uint32_t)i2c->transfer.XferSize << I2C_CTRL2_NBYTES_POS) & I2C_CTRL2_BYTECNT) | (uint32_t)I2C_AUTOEND_MODE;
@@ -545,6 +1028,11 @@ static rt_err_t n32_i2c_master_seq_send_dma(struct n32_i2c *i2c, uint16_t DevAdd
MODIFY_REG(i2c->config->Instance->CTRL2, I2C_CTRL2_CLEAR, (uint32_t)setmask);
i2c->config->Instance->CTRL1 |= (I2C_CTRL1_ERRIE | I2C_CTRL1_TFCIE | I2C_CTRL1_STOPIE | I2C_CTRL1_NAKIE | I2C_CTRL1_WDRIE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Empty transfer - send START+ADDR then generate STOP */
+ I2C_ConfigInt(i2c->config->Instance, I2C_INT_EVENT | I2C_INT_ERR, ENABLE);
+ I2C_SendAddr7bit(i2c->config->Instance, (uint8_t)(DevAddress), I2C_DIRECTION_SEND);
+#endif
}
return RT_EOK;
@@ -596,7 +1084,7 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
next_msg = &msgs[i + 1];
next_flag = next_msg->flags;
- timeout = msg->len / TRANS_TIMEOUT_PERSEC + 2;
+ timeout = msg->len * TRANS_TIMEOUT_PERSEC + 10;
if (next_flag & RT_I2C_NO_START)
{
if ((next_flag & RT_I2C_RD) == (msg->flags & RT_I2C_RD))
@@ -637,6 +1125,8 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
if (rt_completion_wait(completion, timeout) != RT_EOK)
{
LOG_D("receive time out");
+ /* Disarm the ISR before the caller's buffer goes out of scope */
+ I2C_ABORT_ON_TIMEOUT(i2c_obj);
goto out;
}
}
@@ -658,9 +1148,12 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
LOG_D("[%s:%d]I2C Write error(%d)!\n", __func__, __LINE__, ret);
goto out;
}
+
if (rt_completion_wait(completion, timeout) != RT_EOK)
{
LOG_D("transmit time out");
+ /* Disarm the ISR before the caller's buffer goes out of scope */
+ I2C_ABORT_ON_TIMEOUT(i2c_obj);
goto out;
}
}
@@ -669,7 +1162,8 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
/* last msg */
msg = &msgs[i];
- timeout = msg->len / TRANS_TIMEOUT_PERSEC + 2;
+
+ timeout = msg->len * TRANS_TIMEOUT_PERSEC + 10;
if (msg->flags & RT_I2C_NO_STOP)
{
@@ -692,7 +1186,6 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
}
else
{
- uint32_t itflags = READ_REG(i2c_obj->config->Instance->STSINT);
ret = n32_i2c_master_seq_receive_it(i2c_obj, (msg->addr << 1), msg->buf, msg->len, mode);
}
if (ret != RT_EOK)
@@ -703,6 +1196,8 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
if (rt_completion_wait(completion, timeout) != RT_EOK)
{
LOG_D("receive time out");
+ /* Disarm the ISR before the caller's buffer goes out of scope */
+ I2C_ABORT_ON_TIMEOUT(i2c_obj);
goto out;
}
}
@@ -724,17 +1219,25 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
LOG_D("[%s:%d]I2C Write error(%d)!\n", __func__, __LINE__, ret);
goto out;
}
+
if (rt_completion_wait(completion, timeout) != RT_EOK)
{
LOG_D("transmit time out");
+ /* Disarm the ISR before the caller's buffer goes out of scope */
+ I2C_ABORT_ON_TIMEOUT(i2c_obj);
goto out;
}
}
+
LOG_D("xfer end %d mags\r\n", num);
+
return num;
out:
- return (i - 1);
+ /* Return the number of messages actually transferred: msgs[i] is the one
+ * that failed, so the preceding i messages succeeded.
+ */
+ return i;
}
@@ -853,6 +1356,7 @@ static void n32_get_dma_info(void)
static void i2c_flush_wdr(I2C_Module *Instance)
{
+#if defined(SOC_SERIES_N32H7xx)
/* If a pending WRAVL flag is set, Write a dummy data in WDR to clear it */
if ((((Instance->STSINT) & I2C_STSINT_WRAVL) == I2C_STSINT_WRAVL) ? SET : RESET)
{
@@ -864,27 +1368,46 @@ static void i2c_flush_wdr(I2C_Module *Instance)
{
Instance->STSINT |= I2C_STSINT_WRE;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* If TX data register is empty, clear the flag without sending a spurious byte */
+ if (Instance->STS1 & I2C_STS1_TXDATE)
+ {
+ Instance->STS1 = I2C_STS1_TXDATE;
+ }
+#endif
}
static void i2c_it_error_handler(struct n32_i2c *drv_i2c, uint32_t itflags)
{
- uint32_t setmask;
I2C_StateTypeDef tmpstate = drv_i2c->transfer.state;
drv_i2c->transfer.pBuffPtr = RT_NULL;
drv_i2c->transfer.XferCount = 0;
+#if defined(SOC_SERIES_N32H7xx)
+ uint32_t setmask;
setmask = I2C_CTRL1_TFCIE | I2C_CTRL1_WDRIE | I2C_CTRL1_RDRIE | I2C_CTRL1_STOPIE | I2C_CTRL1_NAKIE | I2C_CTRL1_ERRIE;
/* Disable all interrupts */
drv_i2c->config->Instance->CTRL1 &= (~(setmask));
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Disable all interrupts */
+ I2C_ConfigInt(drv_i2c->config->Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, DISABLE);
+#endif
drv_i2c->transfer.state = I2C_READY;
drv_i2c->i2c_isr_callback = RT_NULL;
+ /* Wake the waiting thread. Do not rt_completion_init() here: that clears
+ * the suspended-thread pointer, so a thread already blocked in
+ * rt_completion_wait() would never be woken and could only exit by timeout.
+ */
+ rt_completion_done(&drv_i2c->completion);
+
/* Abort DMA TX transfer */
if ((tmpstate == I2C_BUSY_TX) && (drv_i2c->i2c_dma_flag & I2C_USING_TX_DMA_FLAG) == I2C_USING_TX_DMA_FLAG)
{
+#if defined(SOC_SERIES_N32H7xx)
if ((drv_i2c->config->Instance->CTRL1 & I2C_CTRL1_DMAWREN) == I2C_CTRL1_DMAWREN)
{
drv_i2c->config->Instance->CTRL1 &= ~I2C_CTRL1_DMAWREN;
@@ -895,11 +1418,18 @@ static void i2c_it_error_handler(struct n32_i2c *drv_i2c, uint32_t itflags)
DMA_ChannelEventCmd(drv_i2c->config->dma_tx->Instance, drv_i2c->config->dma_tx->dma_channel, DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE, DISABLE);
DMA_ClearChannelEventStatus(drv_i2c->config->dma_tx->Instance, drv_i2c->config->dma_tx->dma_channel, DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+ DMA_ConfigInt(drv_i2c->config->dma_tx->DMAChx, DMA_INT_TXC, DISABLE);
+ DMA_EnableChannel(drv_i2c->config->dma_tx->DMAChx, DISABLE);
+#endif
}
/* Abort DMA RX transfer */
if ((tmpstate == I2C_BUSY_RX) && (drv_i2c->i2c_dma_flag & I2C_USING_RX_DMA_FLAG) == I2C_USING_RX_DMA_FLAG)
{
+#if defined(SOC_SERIES_N32H7xx)
if ((drv_i2c->config->Instance->CTRL1 & I2C_CTRL1_DMARDEN) == I2C_CTRL1_DMARDEN)
{
drv_i2c->config->Instance->CTRL1 &= ~I2C_CTRL1_DMARDEN;
@@ -910,8 +1440,15 @@ static void i2c_it_error_handler(struct n32_i2c *drv_i2c, uint32_t itflags)
DMA_ChannelEventCmd(drv_i2c->config->dma_rx->Instance, drv_i2c->config->dma_rx->dma_channel, DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE, DISABLE);
DMA_ClearChannelEventStatus(drv_i2c->config->dma_rx->Instance, drv_i2c->config->dma_rx->dma_channel, DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+
+ DMA_ConfigInt(drv_i2c->config->dma_rx->DMAChx, DMA_INT_TXC, DISABLE);
+ DMA_EnableChannel(drv_i2c->config->dma_rx->DMAChx, DISABLE);
+#endif
}
+#if defined(SOC_SERIES_N32H7xx)
if (((((itflags & I2C_STSINT_NAKF) == I2C_STSINT_NAKF) ? SET : RESET) != RESET) ||
((((itflags & I2C_STSINT_BSER) == I2C_STSINT_BSER) ? SET : RESET) != RESET))
{
@@ -919,10 +1456,59 @@ static void i2c_it_error_handler(struct n32_i2c *drv_i2c, uint32_t itflags)
LOG_D("I2C NACK Error or BUS Error now stoped");
drv_i2c->config->Instance->CTRL1 |= I2C_CTRL1_STOPIE;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ {
+ uint32_t sts1 = READ_REG(drv_i2c->config->Instance->STS1);
+ if ((sts1 & I2C_STS1_ACKFAIL) || (sts1 & I2C_STS1_BUSERR))
+ {
+ /* Send stop signal to prevent bus lock-up */
+ LOG_D("I2C NACK Error or BUS Error now stoped");
+ }
+#ifdef N32X_DRV_I2C_DEBUG
+ else
+ {
+ /* Unexpected error flags: also send STOP to release the bus.
+ * Without STOP, the I2C peripheral state machine remains stuck
+ * (e.g. START sent but no STOP), causing all subsequent transfers
+ * to fail with bus busy or timeout.
+ */
+ LOG_W("I2C unexpected error flags 0x%08lX, sending STOP", sts1);
+ }
+#endif
+ /* Clear the latched error flags before leaving. ERRINTEN is disabled
+ * above, so a flag left set here stays quiet only until the next
+ * transfer re-enables it - at which point it fires immediately and
+ * aborts a transaction that had not yet done anything wrong.
+ */
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance,
+ I2C_INT_ACKFAIL | I2C_INT_BUSERR | I2C_INT_ARLOST |
+ I2C_INT_OVERRUN | I2C_INT_PECERR);
+
+ /* Release the bus only if we still own it.
+ *
+ * Do NOT re-enable the event interrupt to wait for STOPF: on this IP
+ * STOPF is only raised in slave mode, so the interrupt would never
+ * arrive, leaving EVTINTEN enabled with no callback installed. Poll the
+ * STOP out instead - bounded, ~10us at 100kHz.
+ *
+ * Asserting STOPGEN when the bus is already idle (NACK released SDA, or
+ * BYTENUM auto-STOP already ended the frame) latches the bit with no
+ * transfer to terminate. It then collides with the next START: the
+ * START is generated, SB sets, and the stray STOP immediately tears it
+ * down and drops us out of master mode.
+ */
+ if ((drv_i2c->config->Instance->STS2 & I2C_STS2_BUSY) == I2C_STS2_BUSY)
+ {
+ drv_i2c->config->Instance->CTRL1 |= I2C_CTRL1_STOPGEN;
+ (void)n32_i2c_wait_bus_idle(drv_i2c->config->Instance);
+ }
+ }
+#endif
}
static void i2c_it_master_complete(struct n32_i2c *drv_i2c, uint32_t itflags)
{
+#if defined(SOC_SERIES_N32H7xx)
uint32_t setmask;
__IO uint32_t tmpreg;
@@ -966,6 +1552,42 @@ static void i2c_it_master_complete(struct n32_i2c *drv_i2c, uint32_t itflags)
}
i2c_flush_wdr(drv_i2c->config->Instance);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Clear STOP Flag */
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_STOPF);
+
+ /* Disable DMA */
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+
+ /* Disable interrupts */
+ I2C_ConfigInt(drv_i2c->config->Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, DISABLE);
+
+ drv_i2c->i2c_isr_callback = RT_NULL;
+
+ {
+ uint32_t sts1 = READ_REG(drv_i2c->config->Instance->STS1);
+
+ if (sts1 & I2C_STS1_ACKFAIL)
+ {
+ /* Clear NACK Flag */
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_ACKFAIL);
+ }
+
+ /* Fetch Last receive data */
+ if (sts1 & I2C_STS1_RXDATNE)
+ {
+ /* Read data from DAT */
+ __IO uint32_t tmpreg = (uint8_t)drv_i2c->config->Instance->DAT;
+ RT_UNUSED(tmpreg);
+ }
+
+ /* Flush TX if needed */
+ if (sts1 & I2C_STS1_TXDATE)
+ {
+ drv_i2c->config->Instance->STS1 = I2C_STS1_TXDATE;
+ }
+ }
+#endif
drv_i2c->transfer.state = I2C_READY;
rt_completion_done(&drv_i2c->completion);
@@ -973,18 +1595,28 @@ static void i2c_it_master_complete(struct n32_i2c *drv_i2c, uint32_t itflags)
static void i2c_it_completion_done(struct n32_i2c *drv_i2c)
{
- uint32_t setmask;
-
/* I2C Write */
if (drv_i2c->transfer.state == I2C_BUSY_TX)
{
drv_i2c->transfer.state = I2C_READY;
drv_i2c->i2c_isr_callback = RT_NULL;
+#if defined(SOC_SERIES_N32H7xx)
+ uint32_t setmask;
setmask = I2C_CTRL1_TFCIE | I2C_CTRL1_WDRIE | I2C_CTRL1_STOPIE | I2C_CTRL1_NAKIE | I2C_CTRL1_ERRIE;
/* Disable interrupt */
drv_i2c->config->Instance->CTRL1 &= (~(setmask));
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Generate STOP condition to end the transaction */
+ drv_i2c->config->Instance->CTRL1 |= I2C_CTRL1_STOPGEN;
+
+ /* Disable interrupts */
+ I2C_ConfigInt(drv_i2c->config->Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, DISABLE);
+
+ /* Disable DMA */
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+#endif
rt_completion_done(&drv_i2c->completion);
}
@@ -994,17 +1626,62 @@ static void i2c_it_completion_done(struct n32_i2c *drv_i2c)
drv_i2c->transfer.state = I2C_READY;
drv_i2c->i2c_isr_callback = RT_NULL;
+#if defined(SOC_SERIES_N32H7xx)
+ uint32_t setmask;
setmask = I2C_CTRL1_TFCIE | I2C_CTRL1_RDRIE | I2C_CTRL1_STOPIE | I2C_CTRL1_NAKIE | I2C_CTRL1_ERRIE;
/* Disable interrupt */
drv_i2c->config->Instance->CTRL1 &= (~(setmask));
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Generate STOP condition to end the transaction */
+ drv_i2c->config->Instance->CTRL1 |= I2C_CTRL1_STOPGEN;
+
+ /* Disable interrupts */
+ I2C_ConfigInt(drv_i2c->config->Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, DISABLE);
+
+ /* Disable DMA */
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+#endif
rt_completion_done(&drv_i2c->completion);
}
}
+static void i2c_dma_completion_done(struct n32_i2c *drv_i2c)
+{
+#if defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ if (drv_i2c->transfer.state == I2C_BUSY_TX)
+ {
+ /* TX: the final byte is still in the shift register when the DMA
+ * completes and DMALAST does not auto-generate STOP. Wait for BSF (last
+ * byte fully sent and acknowledged), then generate STOP and complete. */
+ rt_uint32_t timeout = 1000000U;
+ while (!(drv_i2c->config->Instance->STS1 & I2C_STS1_BSF) && (--timeout > 0U))
+ {
+ }
+ /* Clear BSF so it cannot fire a spurious event interrupt on the next
+ * transfer, where BUFINTEN is re-enabled before the address phase. */
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_BSF);
+
+ i2c_it_completion_done(drv_i2c);
+ }
+ else /* I2C_BUSY_RX */
+ {
+ /* RX: BYTENUM already auto-generates STOP after the last byte, so tear
+ * down and complete without asserting STOPGEN (a stray STOP would
+ * collide with the next START). */
+ drv_i2c->transfer.state = I2C_READY;
+ drv_i2c->i2c_isr_callback = RT_NULL;
+ I2C_ConfigInt(drv_i2c->config->Instance, I2C_INT_BUF | I2C_INT_EVENT | I2C_INT_ERR, DISABLE);
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+ rt_completion_done(&drv_i2c->completion);
+ }
+#endif
+}
+
static void i2c_master_ev_isr_handler_it(struct n32_i2c *drv_i2c)
{
+#if defined(SOC_SERIES_N32H7xx)
uint16_t devaddress;
uint32_t setmask;
/* Get current IT Flags and IT sources value */
@@ -1125,10 +1802,139 @@ static void i2c_master_ev_isr_handler_it(struct n32_i2c *drv_i2c)
{
i2c_it_master_complete(drv_i2c, itflags);
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+ volatile uint32_t itflags = READ_REG(drv_i2c->config->Instance->STS1);
+ volatile uint32_t itsources = READ_REG(drv_i2c->config->Instance->CTRL2);
+
+ /* START condition generated (SB) - must never be left pending.
+ *
+ * SB is an event-interrupt source cleared only by reading STS1 followed by
+ * writing DAT. The normal setup path writes the address itself before
+ * enabling interrupts, so seeing SB here means the transfer is out of sync
+ * (e.g. a START asserted while a previous STOP was still on the wire).
+ * Returning without clearing it would re-assert the IRQ immediately and
+ * storm this handler at preempt priority 2, starving SysTick and hanging
+ * the system. Abort the transfer instead.
+ */
+ if ((itflags & I2C_STS1_STARTBF) && (itsources & I2C_CTRL2_EVTINTEN))
+ {
+ LOG_W("I2C unexpected STARTBF, aborting transfer");
+ i2c_it_error_handler(drv_i2c, itflags);
+ return;
+ }
+
+ /* Address sent (master mode) - read STS2 to clear ADDRF */
+ if ((itflags & I2C_STS1_ADDRF) && (itsources & I2C_CTRL2_EVTINTEN))
+ {
+ /* Clear ADDRF by reading STS2. TXDATE/RXDATNE will be set next. */
+ volatile uint32_t tmp = drv_i2c->config->Instance->STS2;
+ (void)tmp;
+
+ /* Zero-length transfer (e.g. I2C scan) - generate STOP immediately */
+ if (drv_i2c->transfer.XferCount == 0U)
+ {
+ i2c_it_completion_done(drv_i2c);
+ }
+ }
+
+ /* ACKFAIL (NACK) interrupt */
+ if ((itflags & I2C_STS1_ACKFAIL) && (itsources & I2C_CTRL2_ERRINTEN))
+ {
+ i2c_it_error_handler(drv_i2c, itflags);
+ /* The transfer is already torn down (pBuffPtr NULL, state READY) and
+ * the latched error flags were cleared inside the handler. Fall
+ * through only to the flag checks below would touch the dead
+ * transfer: the independent TXDATE block writes through pBuffPtr,
+ * which the handler just set to NULL. Return like the STARTBF path
+ * above does. */
+ return;
+ }
+ /* RX data register not empty */
+ else if ((itflags & I2C_STS1_RXDATNE) && (itsources & I2C_CTRL2_BUFINTEN))
+ {
+ /* Disable ACK before reading the last byte (to send NACK and end slave TX) */
+ if (drv_i2c->transfer.XferCount == 1U)
+ {
+ I2C_ConfigAck(drv_i2c->config->Instance, DISABLE);
+ }
+
+ /* Read data from DAT */
+ *drv_i2c->transfer.pBuffPtr = (uint8_t)drv_i2c->config->Instance->DAT;
+
+ /* Increment Buffer pointer */
+ drv_i2c->transfer.pBuffPtr++;
+
+ drv_i2c->transfer.XferSize--;
+ drv_i2c->transfer.XferCount--;
+
+ /* DAT read also clears BSF, so handle completion here when done */
+ if (drv_i2c->transfer.XferCount == 0U)
+ {
+ i2c_it_completion_done(drv_i2c);
+ }
+ }
+ /* TX data register empty - independent check, must run alongside BSF */
+ if ((itflags & I2C_STS1_TXDATE) && (itsources & I2C_CTRL2_BUFINTEN))
+ {
+ if (drv_i2c->transfer.XferSize > 0)
+ {
+ /* Write data to DAT */
+ drv_i2c->config->Instance->DAT = *drv_i2c->transfer.pBuffPtr;
+
+ /* Increment Buffer pointer */
+ drv_i2c->transfer.pBuffPtr++;
+
+ drv_i2c->transfer.XferSize--;
+ drv_i2c->transfer.XferCount--;
+ }
+ }
+
+ /* Byte Sequence Finished - independent check, handles completion when XferCount == 0 */
+ if ((itflags & I2C_STS1_BSF) && (itsources & I2C_CTRL2_BUFINTEN))
+ {
+ /* Clear BSF flag */
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_BSF);
+
+ /* Transfer complete - BYTENUM expired (RX) or all bytes sent (TX) */
+ i2c_it_completion_done(drv_i2c);
+ }
+
+ /* STOPF interrupt */
+ if ((itflags & I2C_STS1_STOPF) && (itsources & I2C_CTRL2_EVTINTEN))
+ {
+ i2c_it_master_complete(drv_i2c, itflags);
+ }
+
+ /* Catch-all for error flags that reached this handler.
+ *
+ * itflags is STS1 and itsources is CTRL2 - they have unrelated bit layouts,
+ * so they must never be AND-ed together. (Masking them against each other
+ * made this check dead code: CLKFREQ in CTRL2[7:0] carries the peripheral
+ * clock in MHz, so which STS1 bits appeared "enabled" depended purely on
+ * the clock value.) Gate on the single error-enable bit instead, and test
+ * only flags that genuinely indicate a fault - a mid-transfer NACK from a
+ * marginal bus lands here.
+ */
+ {
+ const uint32_t error_flags = I2C_STS1_BUSERR | I2C_STS1_ARLOST | I2C_STS1_OVERRUN | I2C_STS1_PECERR;
+ uint32_t unexpected = itflags & error_flags;
+
+ if (unexpected && (itsources & I2C_CTRL2_ERRINTEN) && (drv_i2c->transfer.state == I2C_BUSY_TX || drv_i2c->transfer.state == I2C_BUSY_RX))
+ {
+ LOG_W("I2C error flags 0x%08X, sts1=0x%08X",
+ (unsigned int)unexpected, (unsigned int)itflags);
+ i2c_it_error_handler(drv_i2c, itflags);
+ }
+ }
+
+
+#endif
}
static void i2c_master_ev_isr_handler_dma(struct n32_i2c *drv_i2c)
{
+#if defined(SOC_SERIES_N32H7xx)
uint16_t devaddress;
uint32_t setmask;
uint32_t xfermode;
@@ -1227,11 +2033,41 @@ static void i2c_master_ev_isr_handler_dma(struct n32_i2c *drv_i2c)
{
/* Nothing to do */
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ volatile uint32_t itflags = READ_REG(drv_i2c->config->Instance->STS1);
+ volatile uint32_t itsources = READ_REG(drv_i2c->config->Instance->CTRL2);
+
+ /* ACKFAIL (NACK) interrupt */
+ if ((itflags & I2C_STS1_ACKFAIL) && (itsources & I2C_CTRL2_ERRINTEN))
+ {
+ /* Clear ACKFAIL flag */
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_ACKFAIL);
+
+ /* Enable STOP detection via Event interrupt to complete the transfer */
+ I2C_ConfigInt(drv_i2c->config->Instance, I2C_INT_EVENT, ENABLE);
+
+ /* Generate STOP */
+ drv_i2c->config->Instance->CTRL1 |= I2C_CTRL1_STOPGEN;
+
+ /* Flush TX data register */
+ i2c_flush_wdr(drv_i2c->config->Instance);
+ }
+ /* STOPF interrupt */
+ else if ((itflags & I2C_STS1_STOPF) && (itsources & I2C_CTRL2_EVTINTEN))
+ {
+ i2c_it_master_complete(drv_i2c, itflags);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+#endif
}
static void i2c_master_er_isr_handler(struct n32_i2c *drv_i2c)
{
uint32_t tmperror = 0;
+#if defined(SOC_SERIES_N32H7xx)
volatile uint32_t itflags = READ_REG(drv_i2c->config->Instance->STSINT);
volatile uint32_t itsources = READ_REG(drv_i2c->config->Instance->CTRL1);
@@ -1271,7 +2107,7 @@ static void i2c_master_er_isr_handler(struct n32_i2c *drv_i2c)
drv_i2c->config->Instance->INTCLR = I2C_INTCLR_CRCCLR;
}
- /* I2C PEC error interrupt occurred */
+ /* I2C timeout error interrupt occurred */
if (((((itflags & I2C_STSINT_TMOUT) == I2C_STSINT_TMOUT) ? SET : RESET) != RESET) &&
((((itsources & I2C_CTRL1_ERRIE) == I2C_CTRL1_ERRIE) ? SET : RESET) != RESET))
{
@@ -1284,6 +2120,51 @@ static void i2c_master_er_isr_handler(struct n32_i2c *drv_i2c)
{
i2c_it_error_handler(drv_i2c, itflags);
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+ volatile uint32_t itflags = READ_REG(drv_i2c->config->Instance->STS1);
+ volatile uint32_t itsources = READ_REG(drv_i2c->config->Instance->CTRL2);
+
+ /* I2C Bus error interrupt occurred */
+ if ((itflags & I2C_STS1_BUSERR) && (itsources & I2C_CTRL2_ERRINTEN))
+ {
+ tmperror |= I2C_STS1_BUSERR;
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_BUSERR);
+ }
+
+ /* I2C Over-Run/Under-Run interrupt occurred */
+ if ((itflags & I2C_STS1_OVERRUN) && (itsources & I2C_CTRL2_ERRINTEN))
+ {
+ tmperror |= I2C_STS1_OVERRUN;
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_OVERRUN);
+ }
+
+ /* I2C Arbitration Loss error interrupt occurred */
+ if ((itflags & I2C_STS1_ARLOST) && (itsources & I2C_CTRL2_ERRINTEN))
+ {
+ tmperror |= I2C_STS1_ARLOST;
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_ARLOST);
+ }
+
+ /* I2C ACKFAIL error interrupt occurred */
+ if ((itflags & I2C_STS1_ACKFAIL) && (itsources & I2C_CTRL2_ERRINTEN))
+ {
+ tmperror |= I2C_STS1_ACKFAIL;
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_ACKFAIL);
+ }
+
+ /* I2C PEC error interrupt occurred */
+ if ((itflags & I2C_STS1_PECERR) && (itsources & I2C_CTRL2_ERRINTEN))
+ {
+ tmperror |= I2C_STS1_PECERR;
+ I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_PECERR);
+ }
+
+ if (tmperror != 0)
+ {
+ i2c_it_error_handler(drv_i2c, itflags);
+ }
+#endif
}
static void i2c_master_ev_isr_handler(struct n32_i2c *drv_i2c)
@@ -1331,6 +2212,9 @@ static void i2c_master_dma_receive_isr_handler(struct n32_i2c *drv_i2c)
n32_iic_transfer_by_dma(drv_i2c->config, drv_i2c->transfer.pBuffPtr, drv_i2c->transfer.XferSize, RT_TRUE);
+ /* Update XferCount for the upcoming frame */
+ drv_i2c->transfer.XferCount -= drv_i2c->transfer.XferSize;
+
/* Enable TC interrupts */
drv_i2c->config->Instance->CTRL1 |= I2C_CTRL1_TFCIE;
}
@@ -1339,6 +2223,125 @@ static void i2c_master_dma_receive_isr_handler(struct n32_i2c *drv_i2c)
DMA_ClearChannelEventStatus(drv_i2c->config->dma_rx->Instance, drv_i2c->config->dma_rx->dma_channel, DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
}
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ {
+ DMA_Module *dma_module = (DMA_Module *)((uint32_t)drv_i2c->config->dma_rx->DMAChx < DMA2_BASE ? DMA1 : DMA2);
+ uint32_t dma_int_tc = 0;
+ if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA1_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (drv_i2c->config->dma_rx->DMAChx == DMA2_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+
+ RT_ASSERT(dma_int_tc != 0);
+
+ if (dma_int_tc != 0 && DMA_GetIntStatus(dma_int_tc, dma_module) == SET)
+ {
+ /* Disable DMA Request */
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+
+ /* Last transfer: DMALAST (TX) / BYTENUM (RX) auto-generate STOP, so
+ * complete directly instead of waiting for STOPF (slave-mode only). */
+ if (drv_i2c->transfer.XferCount == 0U)
+ {
+ i2c_dma_completion_done(drv_i2c);
+ }
+ /* else prepare a new DMA transfer */
+ else
+ {
+ /* Update Buffer pointer */
+ drv_i2c->transfer.pBuffPtr += drv_i2c->transfer.XferSize;
+
+ /* Set the XferSize to transfer */
+ if (drv_i2c->transfer.XferCount > MAX_NBYTE_SIZE)
+ {
+ drv_i2c->transfer.XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ drv_i2c->transfer.XferSize = drv_i2c->transfer.XferCount;
+ }
+
+ n32_iic_transfer_by_dma(drv_i2c->config, drv_i2c->transfer.pBuffPtr, drv_i2c->transfer.XferSize, RT_TRUE);
+
+ /* Update XferCount for the upcoming frame */
+ drv_i2c->transfer.XferCount -= drv_i2c->transfer.XferSize;
+
+#if defined(SOC_SERIES_N32H49x)
+ I2C_EnableByteNum(drv_i2c->config->Instance, ENABLE);
+ /* Set the number of bytes to receive via BYTENUM register */
+ I2C_SetMasterReceivedDataBytesNum(drv_i2c->config->Instance, drv_i2c->transfer.XferSize);
+#elif defined(SOC_SERIES_N32H47x_48x)
+ I2C_EnableBYTENUM(drv_i2c->config->Instance, ENABLE);
+ I2C_SetReceivedDataBytesNum(drv_i2c->config->Instance, drv_i2c->transfer.XferSize);
+#endif
+ /* Re-enable DMA */
+ I2C_EnableDMA(drv_i2c->config->Instance, ENABLE);
+ }
+
+ /* Clear interrupt pending bit */
+ DMA_ClrIntPendingBit(dma_int_tc, dma_module);
+ }
+ }
#endif
}
#endif
@@ -1377,7 +2380,7 @@ static void i2c_master_dma_send_isr_handler(struct n32_i2c *drv_i2c)
drv_i2c->transfer.XferSize = drv_i2c->transfer.XferCount;
}
- n32_iic_transfer_by_dma(drv_i2c->config, drv_i2c->transfer.pBuffPtr, drv_i2c->transfer.XferSize, RT_TRUE);
+ n32_iic_transfer_by_dma(drv_i2c->config, drv_i2c->transfer.pBuffPtr, drv_i2c->transfer.XferSize, RT_FALSE);
/* Enable TC interrupts */
drv_i2c->config->Instance->CTRL1 |= I2C_CTRL1_TFCIE;
@@ -1387,6 +2390,123 @@ static void i2c_master_dma_send_isr_handler(struct n32_i2c *drv_i2c)
DMA_ClearChannelEventStatus(drv_i2c->config->dma_tx->Instance, drv_i2c->config->dma_tx->dma_channel, DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
}
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ {
+ DMA_Module *dma_module = (DMA_Module *)((uint32_t)drv_i2c->config->dma_tx->DMAChx < DMA2_BASE ? DMA1 : DMA2);
+ uint32_t dma_int_tc = 0;
+ if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA1_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (drv_i2c->config->dma_tx->DMAChx == DMA2_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+
+ RT_ASSERT(dma_int_tc != 0);
+
+ if (dma_int_tc != 0 && DMA_GetIntStatus(dma_int_tc, dma_module) == SET)
+ {
+ /* Disable DMA Request */
+ I2C_EnableDMA(drv_i2c->config->Instance, DISABLE);
+
+ /* Last transfer: DMALAST (TX) / BYTENUM (RX) auto-generate STOP, so
+ * complete directly instead of waiting for STOPF (slave-mode only). */
+ if (drv_i2c->transfer.XferCount == 0U)
+ {
+ i2c_dma_completion_done(drv_i2c);
+ }
+ /* else prepare a new DMA transfer */
+ else
+ {
+ /* Update Buffer pointer */
+ drv_i2c->transfer.pBuffPtr += drv_i2c->transfer.XferSize;
+
+ /* Set the XferSize to transfer */
+ if (drv_i2c->transfer.XferCount > MAX_NBYTE_SIZE)
+ {
+ drv_i2c->transfer.XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ drv_i2c->transfer.XferSize = drv_i2c->transfer.XferCount;
+ }
+
+ /* Update XferCount for the upcoming frame */
+ drv_i2c->transfer.XferCount -= drv_i2c->transfer.XferSize;
+
+ n32_iic_transfer_by_dma(drv_i2c->config, drv_i2c->transfer.pBuffPtr, drv_i2c->transfer.XferSize, RT_FALSE);
+
+ /* Set DMALAST if this is the last frame */
+ if (drv_i2c->transfer.XferCount == 0U)
+ {
+ I2C_EnableDmaLastSend(drv_i2c->config->Instance, ENABLE);
+ }
+
+ /* Re-enable DMA */
+ I2C_EnableDMA(drv_i2c->config->Instance, ENABLE);
+ }
+
+ /* Clear interrupt pending bit */
+ DMA_ClrIntPendingBit(dma_int_tc, dma_module);
+ }
+ }
#endif
}
#endif
@@ -1406,7 +2526,7 @@ void I2C1_EV_IRQHandler(void)
rt_interrupt_leave();
}
/**
- * @brief This function handles I2C2 error interrupt.
+ * @brief This function handles I2C1 error interrupt.
*/
void I2C1_ER_IRQHandler(void)
{
@@ -1445,6 +2565,167 @@ void I2C1_TX_DMA_IRQHandler(void)
#endif /* defined(BSP_I2C1_TX_USING_DMA) && defined(I2C1_TX_DMA_IRQHandler) */
#endif /* BSP_USING_HARD_I2C1 */
+#ifdef BSP_USING_HARD_I2C2
+/**
+ * @brief This function handles I2C2 event interrupt.
+ */
+void I2C2_EV_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_ev_isr_handler(&i2c_objs[I2C2_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+/**
+ * @brief This function handles I2C2 error interrupt.
+ */
+void I2C2_ER_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_er_isr_handler(&i2c_objs[I2C2_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#if defined(BSP_I2C2_RX_USING_DMA) && defined(I2C2_RX_DMA_IRQHandler)
+void I2C2_RX_DMA_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_dma_receive_isr_handler(&i2c_objs[I2C2_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* defined(BSP_I2C2_RX_USING_DMA) && defined(I2C2_RX_DMA_IRQHandler) */
+
+#if defined(BSP_I2C2_TX_USING_DMA) && defined(I2C2_TX_DMA_IRQHandler)
+void I2C2_TX_DMA_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_dma_send_isr_handler(&i2c_objs[I2C2_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* defined(BSP_I2C2_TX_USING_DMA) && defined(I2C2_TX_DMA_IRQHandler) */
+#endif /* BSP_USING_HARD_I2C2 */
+
+#ifdef BSP_USING_HARD_I2C3
+/**
+ * @brief This function handles I2C3 event interrupt.
+ */
+void I2C3_EV_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_ev_isr_handler(&i2c_objs[I2C3_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+/**
+ * @brief This function handles I2C2 error interrupt.
+ */
+void I2C3_ER_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_er_isr_handler(&i2c_objs[I2C3_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#if defined(BSP_I2C3_RX_USING_DMA) && defined(I2C3_RX_DMA_IRQHandler)
+void I2C3_RX_DMA_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_dma_receive_isr_handler(&i2c_objs[I2C3_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* defined(BSP_I2C3_RX_USING_DMA) && defined(I2C3_RX_DMA_IRQHandler) */
+
+#if defined(BSP_I2C3_TX_USING_DMA) && defined(I2C3_TX_DMA_IRQHandler)
+void I2C3_TX_DMA_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_dma_send_isr_handler(&i2c_objs[I2C3_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* defined(BSP_I2C3_TX_USING_DMA) && defined(I2C3_TX_DMA_IRQHandler) */
+#endif /* BSP_USING_HARD_I2C3 */
+
+#ifdef BSP_USING_HARD_I2C4
+/**
+ * @brief This function handles I2C2 event interrupt.
+ */
+void I2C4_EV_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_ev_isr_handler(&i2c_objs[I2C4_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+/**
+ * @brief This function handles I2C2 error interrupt.
+ */
+void I2C4_ER_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_er_isr_handler(&i2c_objs[I2C4_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#if defined(BSP_I2C4_RX_USING_DMA) && defined(I2C4_RX_DMA_IRQHandler)
+void I2C4_RX_DMA_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_dma_receive_isr_handler(&i2c_objs[I2C4_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* defined(BSP_I2C4_RX_USING_DMA) && defined(I2C4_RX_DMA_IRQHandler) */
+
+#if defined(BSP_I2C4_TX_USING_DMA) && defined(I2C4_TX_DMA_IRQHandler)
+void I2C4_TX_DMA_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ i2c_master_dma_send_isr_handler(&i2c_objs[I2C4_INDEX]);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* defined(BSP_I2C4_TX_USING_DMA) && defined(I2C4_TX_DMA_IRQHandler) */
+#endif /* BSP_USING_HARD_I2C4 */
int rt_hw_hw_i2c_init(void)
{
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.h
index 28c83ec6de..6f137ac664 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_hard_i2c.h
@@ -40,7 +40,9 @@ struct n32_i2c_config
{
const char *name;
I2C_Module *Instance;
+#if defined(SOC_SERIES_N32H7xx)
rt_uint32_t timing;
+#endif
rt_uint32_t timeout;
IRQn_Type evirq_type;
IRQn_Type erirq_type;
@@ -51,9 +53,16 @@ struct n32_i2c_config
uint32_t periph;
void (*EnablePeriphClk)(uint32_t periph, FunctionalState cmd);
+#if defined(SOC_SERIES_N32H7xx)
void (*I2CKerClkSource)(uint32_t CLK_source);
+#endif
struct dma_config *dma_rx, *dma_tx;
+
+#if defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ DMA_InitType dma_rx_init_str;
+ DMA_InitType dma_tx_init_str;
+#endif
};
struct hard_i2c_transfer
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_nand.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_nand.c
index 4f611b727c..9b2c781a11 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_nand.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_nand.c
@@ -34,8 +34,103 @@ static FEMC_InitType NAND_InitStructure = { 0 };
#define NAND_BANK_ADDR ((uint32_t)0xB0000000)
#endif
+#endif /* SOC_SERIES_N32H7xx */
+
+/* Standard NAND flash commands (platform independent) */
+#define NAND_CMD_READ_1ST ((uint8_t)0x00)
+#define NAND_CMD_READ_2ND ((uint8_t)0x30)
+#define NAND_CMD_WRITE_1ST ((uint8_t)0x80)
+#define NAND_CMD_WRITE_2ND ((uint8_t)0x10)
+#define NAND_CMD_ERASE_1ST ((uint8_t)0x60)
+#define NAND_CMD_ERASE_2ND ((uint8_t)0xD0)
+#define NAND_CMD_READ_ID ((uint8_t)0x90)
+#define NAND_CMD_STATUS ((uint8_t)0x70)
+#define NAND_CMD_RESET ((uint8_t)0xFF)
+
+/* NAND status bits */
+#define NAND_STATUS_READY ((uint32_t)0x40)
+#define NAND_STATUS_ERROR ((uint32_t)0x01)
+
+#if defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+/*
+ * N32H47x/48x and N32H49x FEMC NAND support.
+ *
+ * The FEMC NAND controller of these two series uses the classic
+ * HADDR[17:16] area-select model.
+ * Bank2 base = 0x70000000
+ * Bank3 base = 0x80000000
+ *
+ * HADDR[17:16]:
+ * 00 -> data area
+ * 01 -> command area
+ * 1x -> address area.
+ * A16 drives CLE, A17 drives ALE.
+ */
+
+/* NAND bank base address derived from Kconfig */
+#ifdef BSP_USING_NAND_BANK2
+#define NAND_BANK_ADDR ((uint32_t)0x70000000U)
+#define NAND_BANK FEMC_NAND_BANK2
#endif
+#ifdef BSP_USING_NAND_BANK3
+#define NAND_BANK_ADDR ((uint32_t)0x80000000U)
+#define NAND_BANK FEMC_NAND_BANK3
+#endif
+
+#ifndef NAND_BANK_ADDR
+#error "No FEMC NAND bank selected. Enable BSP_USING_NAND_BANK2 or BSP_USING_NAND_BANK3 in Kconfig."
+#endif
+
+/* FEMC NAND address areas */
+#define NAND_CMD_AREA ((uint32_t)0x00010000U) /* bit16 = CLE */
+#define NAND_ADDR_AREA ((uint32_t)0x00020000U) /* bit17 = ALE */
+#define NAND_DATA_AREA ((uint32_t)0x00000000U)
+
+/*
+ * Wait for NAND operation completion
+ *
+ * NWAIT hardware wait (FEMC_NAND_NWAIT_ENABLE) blocks the CPU inside the
+ * data/status access itself, so the 0x70 status read below returns the final
+ * status. A software poll with timeout is kept as a safety net in case the
+ * NWAIT line is not connected or a device stalls.
+ *
+ * Returns -RT_EIO if the error bit is set, -RT_ETIMEOUT on timeout.
+ */
+static rt_err_t nand_wait_status(void)
+{
+ uint32_t timeout = 0x100000;
+ uint32_t bank = NAND_BANK_ADDR;
+ uint8_t status;
+
+ do
+ {
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_STATUS; /* 0x70 */
+ status = *(__IO uint8_t *)(bank | NAND_DATA_AREA);
+
+ if (status & NAND_STATUS_ERROR)
+ {
+ return -RT_EIO;
+ }
+ if (status & NAND_STATUS_READY)
+ {
+ return RT_EOK;
+ }
+ timeout--;
+ rt_thread_delay(rt_tick_from_millisecond(1));
+ } while (timeout);
+
+ return -RT_ETIMEOUT;
+}
+
+/* Send NAND RESET (0xFF) and wait until the device is ready. */
+static rt_err_t nand_reset(void)
+{
+ *(__IO uint8_t *)(NAND_BANK_ADDR | NAND_CMD_AREA) = NAND_CMD_RESET;
+ return nand_wait_status();
+}
+#endif /* SOC_SERIES_N32H47x_48x || SOC_SERIES_N32H49x */
+
static struct rt_mtd_nand_device _nand_dev;
/*
@@ -49,8 +144,10 @@ static struct rt_mtd_nand_device _nand_dev;
* [10:3] Start command
* [2:0] Byte lane strobes (AXI standard)
*/
+#if defined(SOC_SERIES_N32H7xx)
#define NAND_CMD_AREA ((uint32_t)0x00000000) /* bit19 = 0 */
#define NAND_DATA_AREA ((uint32_t)0x00080000) /* bit19 = 1 */
+#endif /* SOC_SERIES_N32H7xx */
/*
* Address cycle count auto-derived from Kconfig NAND chip parameters.
@@ -79,6 +176,7 @@ static struct rt_mtd_nand_device _nand_dev;
#define NAND_RW_ADDR_CYCLES (2 + NAND_ROW_ADDR_CYCLES)
#define NAND_ERASE_ADDR_CYCLES NAND_ROW_ADDR_CYCLES
+#if defined(SOC_SERIES_N32H7xx)
/* Encode cycle count into AXI address bits [23:21] */
#define NAND_ADDR_CYCLES(n) ((uint32_t)(n) << 21)
@@ -89,21 +187,7 @@ static struct rt_mtd_nand_device _nand_dev;
#define NAND_ECC_LAST_ENABLE ((uint32_t)0x00000400)
#define NAND_ECC_LAST_DISABLE ((uint32_t)0x00000000)
-
-/* Standard NAND flash commands */
-#define NAND_CMD_READ_1ST ((uint8_t)0x00)
-#define NAND_CMD_READ_2ND ((uint8_t)0x30)
-#define NAND_CMD_WRITE_1ST ((uint8_t)0x80)
-#define NAND_CMD_WRITE_2ND ((uint8_t)0x10)
-#define NAND_CMD_ERASE_1ST ((uint8_t)0x60)
-#define NAND_CMD_ERASE_2ND ((uint8_t)0xD0)
-#define NAND_CMD_READ_ID ((uint8_t)0x90)
-#define NAND_CMD_STATUS ((uint8_t)0x70)
-#define NAND_CMD_RESET ((uint8_t)0xFF)
-
-/* NAND status bits */
-#define NAND_STATUS_READY ((uint32_t)0x40)
-#define NAND_STATUS_ERROR ((uint32_t)0x01)
+#endif /* SOC_SERIES_N32H7xx */
/*
* FEMC uses Hamming code with 1-bit correction / 2-bit detection.
@@ -163,11 +247,50 @@ static rt_err_t rt_nand_init(void)
reset_cmd = NAND_BANK_ADDR | NAND_ADDR_CYCLES(0) | NAND_CMD_END_DISABLE | NAND_CMD_AREA | (NAND_CMD_RESET << 3);
*((__IO uint16_t *)reset_cmd) = 0x0000;
}
-#endif
-
return RT_EOK;
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ /* FEMC NAND init */
+ FEMC_NandInitType nandInit = { 0 };
+ FEMC_NandTimingInitType timing = { 0 };
+
+ /* Make sure the FEMC clock is enabled. GPIO is configured by the board
+ * layer (not here), but the FEMC peripheral clock must be on. */
+ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_FEMC, ENABLE);
+
+ FEMC_InitNandStruct(&nandInit);
+
+ /* Bank select from Kconfig */
+ nandInit.Bank = NAND_BANK;
+
+#ifdef BSP_USING_NAND_BUS_WIDTH_8B
+ nandInit.MemDataWidth = FEMC_NAND_BUS_WIDTH_8B;
+#endif /* BSP_USING_NAND_BUS_WIDTH_8B */
+
+#ifdef BSP_USING_NAND_BUS_WIDTH_16B
+ nandInit.MemDataWidth = FEMC_NAND_BUS_WIDTH_16B;
+#endif /* BSP_USING_NAND_BUS_WIDTH_16B */
+
+ /* Wait feature (NWAIT) enabled; ECC disabled for now (matches demo) */
+ nandInit.WaitFeatureEnable = FEMC_NAND_NWAIT_ENABLE;
+ nandInit.EccEnable = FEMC_NAND_ECC_DISABLE;
+ nandInit.EccPageSize = FEMC_NAND_ECC_PAGE_2048BYTES;
+
+ /* Timing (incl. TCLR/TAR) from board/ports/femc_timing.c */
+ FEMC_Nand_Timing_Config(&nandInit, &timing);
+
+ FEMC_InitNand(&nandInit);
+ FEMC_EnableNand(nandInit.Bank, ENABLE);
+
+ /* Reset NAND chip */
+ return nand_reset();
+#else
+ /* Unsupported platform: the SOC series macro is always selected by the
+ * BSP Kconfig, so this branch should never be compiled. */
+ return -RT_ERROR;
+#endif
}
+#if defined(SOC_SERIES_N32H7xx)
/*
* Wait for NAND operation to complete via FEMC busy flag.
*
@@ -231,6 +354,7 @@ static rt_err_t nand_check_status(uint32_t bank_addr)
return -RT_ETIMEOUT;
}
+#endif /* SOC_SERIES_N32H7xx */
/*
* ===========================================================================
@@ -244,6 +368,7 @@ static rt_err_t nand_check_status(uint32_t bank_addr)
* Pack bytes 1-4 (Device + 3rd + 4th + 5th), discard byte 0 (Maker ID).
* This matches the stm32mp1 convention in the RT-Thread codebase.
*/
+#if defined(SOC_SERIES_N32H7xx)
static rt_err_t _read_id(struct rt_mtd_nand_device *device)
{
uint32_t cmd_addr, data_addr;
@@ -272,8 +397,37 @@ static rt_err_t _read_id(struct rt_mtd_nand_device *device)
return (rt_err_t)id;
}
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+static rt_err_t _read_id(struct rt_mtd_nand_device *device)
+{
+ uint32_t bank = NAND_BANK_ADDR;
+ uint8_t id_bytes[5];
+ rt_uint32_t id;
+
+ /* READ_ID (0x90) + 1 address byte, then read 5 ID bytes */
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_READ_ID;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = 0x00;
+
+ for (uint8_t i = 0; i < 5; i++)
+ {
+ id_bytes[i] = *(__IO uint8_t *)(bank | NAND_DATA_AREA);
+ }
+
+ LOG_D("NAND ID: %02X %02X %02X %02X %02X",
+ id_bytes[0], id_bytes[1], id_bytes[2], id_bytes[3], id_bytes[4]);
+
+ /* Pack bytes 1-4 into 32-bit return value (byte 0 = Maker ID, discarded) */
+ id = (rt_uint32_t)id_bytes[1] << 24;
+ id |= (rt_uint32_t)id_bytes[2] << 16;
+ id |= (rt_uint32_t)id_bytes[3] << 8;
+ id |= (rt_uint32_t)id_bytes[4];
+
+ return (rt_err_t)id;
+}
+#endif
/* read one page (data + spare) */
+#if defined(SOC_SERIES_N32H7xx)
static rt_err_t _read_page(struct rt_mtd_nand_device *device,
rt_off_t page,
rt_uint8_t *data, rt_uint32_t data_len,
@@ -341,8 +495,69 @@ static rt_err_t _read_page(struct rt_mtd_nand_device *device,
}
return ret;
}
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+static rt_err_t _read_page(struct rt_mtd_nand_device *device,
+ rt_off_t page,
+ rt_uint8_t *data, rt_uint32_t data_len,
+ rt_uint8_t *spare, rt_uint32_t spare_len)
+{
+ uint32_t bank = NAND_BANK_ADDR;
+ uint32_t row_addr = (uint32_t)page;
+ uint32_t i;
+ rt_err_t ret;
+
+ /* Command phase: READ_1ST + column(2x 0) + row(NAND_ROW_ADDR_CYCLES) + READ_2ND */
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_READ_1ST;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = 0x00;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = 0x00;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)(row_addr & 0xFF);
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)((row_addr >> 8) & 0xFF);
+#if NAND_ROW_ADDR_CYCLES == 3
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)((row_addr >> 16) & 0xFF);
+#endif
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_READ_2ND;
+
+ /*
+ * Read main data area one byte at a time.
+ *
+ * NOTE: do NOT send a READ STATUS (0x70) between the 0x30 command and
+ * the data reads below. 0x70 switches the NAND into status-output mode,
+ * so the data area would return the status register (e.g. 0xE0) instead
+ * of the page contents. This mirrors demo's FEMC_Nand_ReadPage_Byte():
+ * data is read directly after 0x30 and relies on the NWAIT feature
+ * (FEMC_NAND_NWAIT_ENABLE) to stall the CPU until the page is ready.
+ *
+ * The data area can be accessed with 8/16/32-bit AHB accesses regardless
+ * of the NAND bus width (FEMC splits wide accesses automatically, see
+ * FEMC manual "supported memories and operations"). The byte loop is
+ * used here for simplicity and maximum compatibility.
+ */
+ if (data && data_len)
+ {
+ for (i = 0; i < data_len; i++)
+ {
+ data[i] = *(__IO uint8_t *)(bank | NAND_DATA_AREA);
+ }
+ }
+
+ /* spare area read not implemented yet */
+
+ /*
+ * Check status after the data has been read, mirroring demo's
+ * FEMC_Nand_ReadPage_Byte -> FEMC_Nand_GetStatus(). A READ STATUS (0x70)
+ * after the data phase is safe and checks for any pending read error.
+ */
+ ret = nand_wait_status();
+ if (ret != RT_EOK)
+ {
+ LOG_E("read page %d status error %d", (int)page, ret);
+ }
+ return ret;
+}
+#endif
/* write one page (data + spare) */
+#if defined(SOC_SERIES_N32H7xx)
static rt_err_t _write_page(struct rt_mtd_nand_device *device,
rt_off_t page,
const rt_uint8_t *data, rt_uint32_t data_len,
@@ -436,6 +651,101 @@ static rt_err_t _write_page(struct rt_mtd_nand_device *device,
}
return ret;
}
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+static rt_err_t _write_page(struct rt_mtd_nand_device *device,
+ rt_off_t page,
+ const rt_uint8_t *data, rt_uint32_t data_len,
+ const rt_uint8_t *spare, rt_uint32_t spare_len)
+{
+ uint32_t bank = NAND_BANK_ADDR;
+ uint32_t row_addr = (uint32_t)page;
+ uint32_t i;
+ rt_err_t ret;
+
+ /* Command phase: WRITE_1ST + column(2x 0) + row(NAND_ROW_ADDR_CYCLES) */
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_WRITE_1ST;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = 0x00;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = 0x00;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)(row_addr & 0xFF);
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)((row_addr >> 8) & 0xFF);
+#if NAND_ROW_ADDR_CYCLES == 3
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)((row_addr >> 16) & 0xFF);
+#endif
+
+ /*
+ * Data phase: write main data to the data area.
+ *
+ * @note FEMC manual "supported memories and operations": 16-bit NAND
+ * does NOT support 8-bit AHB writes (only 16/32-bit). So for 16-bit bus
+ * use 16-bit accesses, otherwise the byte loop is safe.
+ */
+ if (data && data_len)
+ {
+#ifdef BSP_USING_NAND_BUS_WIDTH_16B
+ /*
+ * 16-bit NAND: 8-bit AHB writes are NOT supported (see FEMC manual
+ * "supported memories and operations"), so data must be written as
+ * 16-bit accesses. If the source buffer is not 16-bit aligned, copy
+ * it into an aligned temporary buffer first.
+ */
+ if (((uint32_t)data & 0x1U) == 0U)
+ {
+ uint16_t *p16 = (uint16_t *)data;
+ uint32_t word_cnt = data_len / 2;
+
+ for (i = 0; i < word_cnt; i++)
+ {
+ *(__IO uint16_t *)(bank | NAND_DATA_AREA) = p16[i];
+ }
+ }
+ else
+ {
+ uint16_t *tmp;
+ uint32_t word_cnt = data_len / 2;
+
+ tmp = rt_malloc(data_len);
+ if (!tmp)
+ {
+ return -RT_ENOMEM;
+ }
+ rt_memcpy(tmp, data, data_len);
+
+ for (i = 0; i < word_cnt; i++)
+ {
+ *(__IO uint16_t *)(bank | NAND_DATA_AREA) = tmp[i];
+ }
+ rt_free(tmp);
+ }
+ /* odd trailing byte */
+ if (data_len & 1)
+ {
+ *(__IO uint8_t *)(bank | NAND_DATA_AREA) = data[data_len - 1];
+ }
+#else
+ for (i = 0; i < data_len; i++)
+ {
+ *(__IO uint8_t *)(bank | NAND_DATA_AREA) = data[i];
+ }
+#endif
+ }
+ else
+ {
+ *(__IO uint8_t *)(bank | NAND_DATA_AREA) = 0x00;
+ }
+
+ /* spare area write not implemented yet */
+
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_WRITE_2ND;
+
+ /* Wait for program completion, then check status */
+ ret = nand_wait_status();
+ if (ret != RT_EOK)
+ {
+ LOG_E("write page %d status error %d", (int)page, ret);
+ }
+ return ret;
+}
+#endif
/* move page (for garbage collection) */
static rt_err_t _move_page(struct rt_mtd_nand_device *device,
@@ -465,6 +775,7 @@ static rt_err_t _move_page(struct rt_mtd_nand_device *device,
}
/* erase one block */
+#if defined(SOC_SERIES_N32H7xx)
static rt_err_t _erase_block(struct rt_mtd_nand_device *device, rt_uint32_t block)
{
uint32_t cmd_addr;
@@ -508,6 +819,31 @@ static rt_err_t _erase_block(struct rt_mtd_nand_device *device, rt_uint32_t bloc
}
return ret;
}
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+static rt_err_t _erase_block(struct rt_mtd_nand_device *device, rt_uint32_t block)
+{
+ uint32_t bank = NAND_BANK_ADDR;
+ uint32_t row_addr = block * device->pages_per_block;
+ rt_err_t ret;
+
+ /* Convert block number to row address (no column address for erase) */
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_ERASE_1ST;
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)(row_addr & 0xFF);
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)((row_addr >> 8) & 0xFF);
+#if NAND_ROW_ADDR_CYCLES == 3
+ *(__IO uint8_t *)(bank | NAND_ADDR_AREA) = (uint8_t)((row_addr >> 16) & 0xFF);
+#endif
+ *(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_ERASE_2ND;
+
+ /* Wait for erase completion, then check status */
+ ret = nand_wait_status();
+ if (ret != RT_EOK)
+ {
+ LOG_E("erase block %d status error %d", (int)block, ret);
+ }
+ return ret;
+}
+#endif
/*
* Check if a block is bad.
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.c
index 84d17a85b1..f8b5d12019 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.c
@@ -9,10 +9,9 @@
#include "board.h"
-#if defined(BSP_USING_QSPI2)
+#if defined(BSP_USING_QSPI2) || defined(BSP_USING_QSPI)
#include "drv_qspi.h"
-#include "n32h7xx_xspi_v2.h"
#include "drv_config.h"
#include <string.h>
@@ -22,11 +21,14 @@
#define XSPI_TIMEOUT_TICKS (1000U)
#define DMA_TRANS_MIN_LEN (10U)
+#if defined(SOC_SERIES_N32H7xx)
#define XSPI_XIP_BASE_ADDR 0x90000000
+#endif
static struct rt_spi_bus _xspi_bus;
static struct n32_xspi _n32_xspi;
+#if !defined(SOC_SERIES_N32H47x_48x)
static rt_err_t xspi_wait_flag(XSPI_Module *xspi, uint32_t flag, uint32_t timeout)
{
@@ -43,23 +45,24 @@ static rt_err_t xspi_wait_flag(XSPI_Module *xspi, uint32_t flag, uint32_t timeou
return RT_EOK;
}
-static void XSPI_Wait_Tx_Compelete(void)
+static void xspi_wait_tx_complete(XSPI_Module *xspi)
{
- while (XSPI_GetFlagStatus(xSPI2, XSPI_TXFE_FLAG) != SET)
+ while (XSPI_GetFlagStatus(xspi, XSPI_TXFE_FLAG) != SET)
{
}
- while (XSPI_GetFlagStatus(xSPI2, XSPI_BUSY_FLAG) != RESET)
+ while (XSPI_GetFlagStatus(xspi, XSPI_BUSY_FLAG) != RESET)
{
}
}
-static rt_err_t xspi_wait_flag_clear(XSPI_Module *xspi, uint32_t flag, uint32_t timeout)
+static rt_err_t xspi_wait_busy(XSPI_Module *xspi, uint32_t timeout)
{
uint32_t tickstart = rt_tick_get();
- while (XSPI_GetFlagStatus(xspi, flag) != RESET)
+ /* wait until the transfer completes (BUSY flag cleared) */
+ while (XSPI_GetFlagStatus(xspi, XSPI_BUSY_FLAG) == SET)
{
if (((rt_tick_get() - tickstart) >= timeout) && (timeout != 0xFFFFFFFFU))
{
@@ -70,11 +73,6 @@ static rt_err_t xspi_wait_flag_clear(XSPI_Module *xspi, uint32_t flag, uint32_t
return RT_EOK;
}
-static rt_err_t xspi_wait_busy(XSPI_Module *xspi, uint32_t timeout)
-{
- return xspi_wait_flag_clear(xspi, XSPI_BUSY_FLAG, timeout);
-}
-
/* ---- multi-line helpers ---- */
static uint32_t xspi_get_transfer_type(uint8_t instr_lines, uint8_t addr_lines)
@@ -115,6 +113,7 @@ static uint32_t xspi_get_frame_format(uint8_t lines)
return XSPI_STANDARD_MODE;
}
}
+
static void xspi_config_enhanced_for_msg(struct n32_xspi *xspi_config,
struct rt_qspi_message *qspi_msg,
uint32_t transfer_mode, rt_uint8_t ddr_enabled)
@@ -306,7 +305,7 @@ static rt_err_t xspi_spi_transmit(struct n32_xspi *xspi_drv, struct rt_qspi_mess
XSPI_SetNumberOfDataFrame(xspi, qspi_msg->parent.length);
- XSPI_Wait_Tx_Compelete();
+ xspi_wait_tx_complete(xspi);
XSPI_Enable(xspi, ENABLE);
@@ -335,7 +334,7 @@ static rt_err_t xspi_spi_transmit(struct n32_xspi *xspi_drv, struct rt_qspi_mess
}
}
- XSPI_Wait_Tx_Compelete();
+ xspi_wait_tx_complete(xspi);
if (recv_buf)
{
@@ -409,7 +408,7 @@ static rt_err_t xspi_spi_send(struct n32_xspi *xspi_drv, struct rt_qspi_message
XSPI_Enable(xspi, ENABLE);
- XSPI_Wait_Tx_Compelete();
+ xspi_wait_tx_complete(xspi);
XSPI_ClearRxFIFO(xspi);
@@ -441,7 +440,7 @@ static rt_err_t xspi_spi_send(struct n32_xspi *xspi_drv, struct rt_qspi_message
}
}
- XSPI_Wait_Tx_Compelete();
+ xspi_wait_tx_complete(xspi);
XSPI_Enable(xspi, DISABLE);
@@ -493,7 +492,7 @@ static rt_err_t xspi_spi_receive(struct n32_xspi *xspi_drv, struct rt_qspi_messa
XSPI_SetTXStartFIFOThreshold(xspi, (qspi_msg->parent.length - 1));
}
- while (i < qspi_msg->parent.length + 4) /*Tx Fifo not full*/
+ while (i < qspi_msg->parent.length + 4) /*Tx Fifo not full*/
{
while ((xspi->STS & XSPI_TXFNF_FLAG) != XSPI_TXFNF_FLAG); /*wait tx FIFO not full flag set*/
@@ -506,7 +505,7 @@ static rt_err_t xspi_spi_receive(struct n32_xspi *xspi_drv, struct rt_qspi_messa
xspi->DAT0 = 0xFF;
}
- if ((xspi->STS & XSPI_RXFNE_FLAG)) /*Rx Fifo not empty set*/
+ if ((xspi->STS & XSPI_RXFNE_FLAG)) /*Rx Fifo not empty set*/
{
if (j < 4)
{
@@ -525,7 +524,7 @@ static rt_err_t xspi_spi_receive(struct n32_xspi *xspi_drv, struct rt_qspi_messa
do
{
- if ((xspi->STS & XSPI_RXFNE_FLAG)) /*Rx Fifo not empty set*/
+ if ((xspi->STS & XSPI_RXFNE_FLAG)) /*Rx Fifo not empty set*/
{
*(buf++) = xspi->DAT0; /*read data register*/
}
@@ -547,7 +546,6 @@ static rt_err_t xspi_configure(struct rt_spi_device *device, struct rt_spi_confi
xspi_drv->qspi_cfg = &qspi_dev->config;
xspi_drv->cfg = configuration;
-#if defined(SOC_SERIES_N32H7xx)
/* set scpol/scph value */
switch (xspi_drv->qspi_cfg->parent.mode & 0x03)
{
@@ -618,12 +616,416 @@ static rt_err_t xspi_configure(struct rt_spi_device *device, struct rt_spi_confi
xspi_drv->InitStructure.DataFrameSize = XSPI_FRAME_SIZE_32_BIT;
}
+ return RT_EOK;
+}
-#endif
+#else /* SOC_SERIES_N32H47x_48x: DesignWare-style XSPI, single global instance */
+
+static rt_err_t xspi_wait_flag(uint32_t flag, uint32_t timeout)
+{
+ uint32_t tickstart = rt_tick_get();
+
+ while (XSPI_GetFlagStatus(flag) == RESET)
+ {
+ if (((rt_tick_get() - tickstart) >= timeout) && (timeout != 0xFFFFFFFFU))
+ {
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ return RT_EOK;
+}
+
+static void xspi_wait_tx_complete(void)
+{
+ while (XSPI_GetFlagStatus(XSPI_STS_TXFE) != SET) /* TX FIFO empty */
+ {
+ }
+
+ while (XSPI_GetFlagStatus(XSPI_STS_BUSY) != RESET) /* transfer done */
+ {
+ }
+}
+
+static rt_err_t xspi_wait_busy(uint32_t timeout)
+{
+ uint32_t tickstart = rt_tick_get();
+
+ while (XSPI_GetFlagStatus(XSPI_STS_BUSY) == SET)
+ {
+ if (((rt_tick_get() - tickstart) >= timeout) && (timeout != 0xFFFFFFFFU))
+ {
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ return RT_EOK;
+}
+
+/* data line width -> SPIFRF frame format */
+static uint32_t xspi_get_spifrf(uint8_t lines)
+{
+ switch (lines)
+ {
+ case 2:
+ return XSPI_CTRL0_SPIFRF_DUAL_FORMAT;
+ case 4:
+ return XSPI_CTRL0_SPIFRF_QUAD_FORMAT;
+ case 8:
+ return XSPI_CTRL0_SPIFRF_OCTAL_FORMAT;
+ default:
+ return XSPI_CTRL0_SPIFRF_STANDARD_FORMAT;
+ }
+}
+
+/* instruction/address line width -> enhanced TRANSTYPE */
+static uint32_t xspi_get_transtype(uint8_t instr_lines, uint8_t addr_lines)
+{
+ if (instr_lines == 1 && addr_lines == 1)
+ {
+ return XSPI_ENH_CTRL0_TRANSTYPE_STANDARD;
+ }
+ if (instr_lines == 1 && addr_lines > 1)
+ {
+ return XSPI_ENH_CTRL0_TRANSTYPE_ADDRESS_BY_FRF;
+ }
+ return XSPI_ENH_CTRL0_TRANSTYPE_ALL_BY_FRF;
+}
+
+/* address bit length -> enhanced ADDRLEN */
+static uint32_t xspi_get_addrlen(uint8_t size)
+{
+ switch (size)
+ {
+ case 8:
+ return XSPI_ENH_CTRL0_ADDRLEN_8_BIT;
+ case 16:
+ return XSPI_ENH_CTRL0_ADDRLEN_16_BIT;
+ case 24:
+ return XSPI_ENH_CTRL0_ADDRLEN_24_BIT;
+ case 32:
+ return XSPI_ENH_CTRL0_ADDRLEN_32_BIT;
+ default:
+ return 0;
+ }
+}
+
+/* ---- standard SPI (base mode) ---- */
+
+static rt_err_t xspi_spi_transmit(struct n32_xspi *xspi_drv, struct rt_qspi_message *qspi_msg, uint32_t timeout)
+{
+ uint16_t i = 0, rindex = 0;
+ uint8_t *send_buf = (uint8_t *)qspi_msg->parent.send_buf;
+ uint8_t *recv_buf = (uint8_t *)qspi_msg->parent.recv_buf;
+ uint32_t len = qspi_msg->parent.length;
+
+ xspi_drv->InitStructure.FRF = XSPI_CTRL0_FRF_MOTOROLA;
+ xspi_drv->InitStructure.SPIFRF = XSPI_CTRL0_SPIFRF_STANDARD_FORMAT;
+ xspi_drv->InitStructure.TMOD = (send_buf && !recv_buf) ? XSPI_CTRL0_TMOD_TX_ONLY
+ : XSPI_CTRL0_TMOD_TX_AND_RX;
+ xspi_drv->InitStructure.NDF = len - 1;
+
+ XSPI_Cmd(DISABLE);
+ XSPI_Init(&xspi_drv->InitStructure);
+ if (recv_buf)
+ {
+ XSPI_ClrFifo();
+ }
+ XSPI_Cmd(ENABLE);
+
+ while (i < len)
+ {
+ if (XSPI_GetFlagStatus(XSPI_STS_TXFNF) == SET)
+ {
+ XSPI_SendData(send_buf ? send_buf[i] : 0xFF);
+ i++;
+ }
+
+ /* drain RX FIFO in lockstep to avoid overflow on large full-duplex transfers */
+ if (recv_buf && (XSPI_GetFlagStatus(XSPI_STS_RXFNE) == SET))
+ {
+ if (rindex < len)
+ {
+ recv_buf[rindex++] = (uint8_t)XSPI_ReceiveData();
+ }
+ else
+ {
+ (void)XSPI_ReceiveData();
+ }
+ }
+ }
+
+ xspi_wait_tx_complete();
+
+ if (recv_buf)
+ {
+ while ((rindex < len) && (XSPI_GetFlagStatus(XSPI_STS_RXFNE) == SET))
+ {
+ recv_buf[rindex++] = (uint8_t)XSPI_ReceiveData();
+ }
+ }
+
+ XSPI_Cmd(DISABLE);
+ return RT_EOK;
+}
+
+static rt_err_t xspi_spi_send(struct n32_xspi *xspi_drv, struct rt_qspi_message *qspi_msg, uint32_t timeout)
+{
+ uint16_t i = 0;
+ uint8_t *buf = (uint8_t *)qspi_msg->parent.send_buf;
+ uint32_t len = qspi_msg->parent.length;
+ uint8_t s_data[4] = { 0 };
+
+ if (qspi_msg->instruction.content == 0)
+ {
+ return RT_ERROR;
+ }
+
+ /* base mode full-duplex: clock out instruction(1) + address(3) + data(len),
+ * discard whatever is received. */
+ xspi_drv->InitStructure.FRF = XSPI_CTRL0_FRF_MOTOROLA;
+ xspi_drv->InitStructure.SPIFRF = XSPI_CTRL0_SPIFRF_STANDARD_FORMAT;
+ xspi_drv->InitStructure.TMOD = XSPI_CTRL0_TMOD_TX_AND_RX;
+ xspi_drv->InitStructure.NDF = (len + 4) - 1;
+
+ XSPI_Cmd(DISABLE);
+ XSPI_Init(&xspi_drv->InitStructure);
+ XSPI_ClrFifo();
+ XSPI_Cmd(ENABLE);
+
+ s_data[0] = qspi_msg->instruction.content;
+ s_data[1] = (qspi_msg->address.content & 0xff0000) >> 16;
+ s_data[2] = (qspi_msg->address.content & 0xff00) >> 8;
+ s_data[3] = qspi_msg->address.content & 0xff;
+
+ while (i < len + 4)
+ {
+ if (XSPI_GetFlagStatus(XSPI_STS_TXFNF) == SET)
+ {
+ XSPI_SendData((i < 4) ? s_data[i] : buf[i - 4]);
+ i++;
+ }
+
+ if (XSPI_GetFlagStatus(XSPI_STS_RXFNE) == SET)
+ {
+ (void)XSPI_ReceiveData(); /* discard received bytes */
+ }
+ }
+
+ /* drain the remaining received bytes */
+ while (XSPI_GetFlagStatus(XSPI_STS_RXFNE) == SET)
+ {
+ (void)XSPI_ReceiveData();
+ }
+
+ xspi_wait_tx_complete();
+ XSPI_Cmd(DISABLE);
+ return RT_EOK;
+}
+
+static rt_err_t xspi_spi_receive(struct n32_xspi *xspi_drv, struct rt_qspi_message *qspi_msg, uint32_t timeout)
+{
+ uint16_t i = 0, j = 0;
+ uint8_t *buf = (uint8_t *)qspi_msg->parent.recv_buf;
+ uint32_t len = qspi_msg->parent.length;
+ uint8_t s_data[4] = { 0 };
+
+ if (qspi_msg->instruction.content == 0)
+ {
+ return RT_ERROR;
+ }
+
+ /* base mode full-duplex: clock out instruction(1) + address(3) + dummy(len),
+ * discard the 4 bytes received during the command/address phase. */
+ xspi_drv->InitStructure.FRF = XSPI_CTRL0_FRF_MOTOROLA;
+ xspi_drv->InitStructure.SPIFRF = XSPI_CTRL0_SPIFRF_STANDARD_FORMAT;
+ xspi_drv->InitStructure.TMOD = XSPI_CTRL0_TMOD_TX_AND_RX;
+ xspi_drv->InitStructure.NDF = (len + 4) - 1;
+
+ XSPI_Cmd(DISABLE);
+ XSPI_Init(&xspi_drv->InitStructure);
+ XSPI_ClrFifo();
+ XSPI_Cmd(ENABLE);
+
+ s_data[0] = qspi_msg->instruction.content;
+ s_data[1] = (qspi_msg->address.content & 0xff0000) >> 16;
+ s_data[2] = (qspi_msg->address.content & 0xff00) >> 8;
+ s_data[3] = qspi_msg->address.content & 0xff;
+
+ while (i < len + 4)
+ {
+ if (XSPI_GetFlagStatus(XSPI_STS_TXFNF) == SET)
+ {
+ XSPI_SendData((i < 4) ? s_data[i] : 0xFF);
+ i++;
+ }
+
+ if (XSPI_GetFlagStatus(XSPI_STS_RXFNE) == SET)
+ {
+ uint8_t r = (uint8_t)XSPI_ReceiveData();
+ if (j >= 4)
+ {
+ buf[j - 4] = r; /* drop the 4 command/address echo bytes */
+ }
+ j++;
+ }
+ }
+
+ /* drain the remaining received bytes (len + 4 in total) */
+ while (j < len + 4)
+ {
+ if (XSPI_GetFlagStatus(XSPI_STS_RXFNE) == SET)
+ {
+ uint8_t r = (uint8_t)XSPI_ReceiveData();
+ if (j >= 4)
+ {
+ buf[j - 4] = r;
+ }
+ j++;
+ }
+ }
+
+ XSPI_Cmd(DISABLE);
+ return RT_EOK;
+}
+
+/* ---- enhanced (dual/quad/octal) mode ---- */
+
+static void xspi_config_enhanced(struct n32_xspi *xspi_drv, struct rt_qspi_message *qspi_msg, uint32_t tmod)
+{
+ XSPI_InitType *init = &xspi_drv->InitStructure;
+
+ init->FRF = XSPI_CTRL0_FRF_MOTOROLA;
+ init->SPIFRF = xspi_get_spifrf(qspi_msg->qspi_data_lines);
+ init->TMOD = tmod;
+ init->NDF = qspi_msg->parent.length - 1;
+
+ init->ENHANCED_TRANSTYPE = xspi_get_transtype(qspi_msg->instruction.qspi_lines, qspi_msg->address.qspi_lines);
+ init->ENHANCED_INST_L = (qspi_msg->instruction.qspi_lines == 1)
+ ? XSPI_ENH_CTRL0_INST_L_8_LINE
+ : XSPI_ENH_CTRL0_INST_L_0_LINE;
+ init->ENHANCED_ADDR_L = xspi_get_addrlen(qspi_msg->address.size);
+ init->ENHANCED_WAITCYCLES = ((uint32_t)qspi_msg->dummy_cycles & 0x1FU) << 11U;
+ init->ENHANCED_CLKSTREN = 0;
+
+ if (tmod != XSPI_CTRL0_TMOD_TX_AND_RX)
+ {
+ /* RX/TX-only enhanced mode: enable clock stretch and set RX sample delay = BAUD/2
+ * (mirrors official XSPI_QUAD demo) */
+ init->ENHANCED_CLKSTREN = XSPI_ENH_CTRL0_CLKSTREN;
+ init->SDCN = init->CLKDIV >> 1; /* RX_DELAY = BAUD/2, BAUD = CLKDIV << 1 */
+ }
+}
+
+static rt_err_t xspi_qspi_transmit(struct n32_xspi *xspi_drv, struct rt_qspi_message *qspi_msg, uint32_t timeout)
+{
+ uint8_t *buf = (uint8_t *)qspi_msg->parent.send_buf;
+ uint32_t len = qspi_msg->parent.length, i = 0;
+
+ xspi_config_enhanced(xspi_drv, qspi_msg, XSPI_CTRL0_TMOD_TX_ONLY);
+
+ XSPI_Cmd(DISABLE);
+ XSPI_Init(&xspi_drv->InitStructure);
+ XSPI_Cmd(ENABLE);
+
+ XSPI_SendData(qspi_msg->instruction.content);
+ XSPI_SendData(qspi_msg->address.content);
+
+ while (i < len)
+ {
+ if (XSPI_GetFlagStatus(XSPI_STS_TXFNF) == SET)
+ {
+ XSPI_SendData(buf[i++]);
+ }
+ }
+ xspi_wait_tx_complete();
+ XSPI_Cmd(DISABLE);
return RT_EOK;
}
+static rt_err_t xspi_qspi_receive(struct n32_xspi *xspi_drv, struct rt_qspi_message *qspi_msg, uint32_t timeout)
+{
+ uint8_t *buf = (uint8_t *)qspi_msg->parent.recv_buf;
+ uint32_t len = qspi_msg->parent.length, i = 0;
+
+ xspi_config_enhanced(xspi_drv, qspi_msg, XSPI_CTRL0_TMOD_RX_ONLY);
+
+ XSPI_Cmd(DISABLE);
+ XSPI_Init(&xspi_drv->InitStructure);
+ XSPI_ClrFifo();
+ XSPI_Cmd(ENABLE);
+
+ XSPI_SendData(qspi_msg->instruction.content);
+ XSPI_SendData(qspi_msg->address.content);
+
+ for (i = 0; i < len; i++)
+ {
+ if (xspi_wait_flag(XSPI_STS_RXFNE, timeout) != RT_EOK)
+ {
+ XSPI_Cmd(DISABLE);
+ return -RT_ETIMEOUT;
+ }
+ buf[i] = (uint8_t)XSPI_ReceiveData();
+ }
+
+ xspi_wait_tx_complete();
+ XSPI_Cmd(DISABLE);
+ return RT_EOK;
+}
+
+static rt_err_t xspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
+{
+ struct n32_xspi *xspi_drv = device->bus->parent.user_data;
+ struct rt_qspi_device *qspi_dev = (struct rt_qspi_device *)device;
+
+ xspi_drv->qspi_cfg = &qspi_dev->config;
+ xspi_drv->cfg = configuration;
+
+ /* set scpol/scph value */
+ switch (xspi_drv->qspi_cfg->parent.mode & 0x03)
+ {
+ case RT_SPI_MODE_0:
+ xspi_drv->InitStructure.SCPH = XSPI_CTRL0_SCPH_FIRST_EDGE;
+ xspi_drv->InitStructure.SCPOL = XSPI_CTRL0_SCPOL_LOW;
+ break;
+ case RT_SPI_MODE_1:
+ xspi_drv->InitStructure.SCPH = XSPI_CTRL0_SCPH_SECOND_EDGE;
+ xspi_drv->InitStructure.SCPOL = XSPI_CTRL0_SCPOL_LOW;
+ break;
+ case RT_SPI_MODE_2:
+ xspi_drv->InitStructure.SCPH = XSPI_CTRL0_SCPH_FIRST_EDGE;
+ xspi_drv->InitStructure.SCPOL = XSPI_CTRL0_SCPOL_HIGH;
+ break;
+ case RT_SPI_MODE_3:
+ default:
+ xspi_drv->InitStructure.SCPH = XSPI_CTRL0_SCPH_SECOND_EDGE;
+ xspi_drv->InitStructure.SCPOL = XSPI_CTRL0_SCPOL_HIGH;
+ break;
+ }
+
+ /* data line width -> SPIFRF */
+ xspi_drv->InitStructure.SPIFRF = xspi_get_spifrf(xspi_drv->qspi_cfg->qspi_dl_width);
+
+ /* data frame size -> DFS */
+ if (xspi_drv->qspi_cfg->parent.data_width == 16)
+ {
+ xspi_drv->InitStructure.DFS = XSPI_CTRL0_DFS_16_BIT;
+ }
+ else if (xspi_drv->qspi_cfg->parent.data_width == 32)
+ {
+ xspi_drv->InitStructure.DFS = XSPI_CTRL0_DFS_32_BIT;
+ }
+ else
+ {
+ xspi_drv->InitStructure.DFS = XSPI_CTRL0_DFS_8_BIT;
+ }
+
+ return RT_EOK;
+}
+
+#endif /* !SOC_SERIES_N32H47x_48x */
+
static rt_ssize_t xspixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
RT_ASSERT(device != RT_NULL && device->bus != RT_NULL && message != RT_NULL);
@@ -680,6 +1082,7 @@ static const struct rt_spi_ops n32_xspi_ops = {
};
+#if defined(SOC_SERIES_N32H7xx)
/* XSPI XIP */
static rt_err_t xspi_control(rt_device_t dev, int cmd, void *args)
{
@@ -786,6 +1189,8 @@ static rt_err_t xspi_control(rt_device_t dev, int cmd, void *args)
return -RT_EINVAL;
}
}
+#endif /* SOC_SERIES_N32H7xx */
+
/* ---- bus register + device attach ---- */
static int n32_xspi_register_bus(struct n32_xspi *xspi_drv, const char *name)
@@ -811,6 +1216,19 @@ rt_err_t rt_hw_xspi_device_attach(const char *bus_name, const char *device_name,
if (cfg != RT_NULL)
{
+#if defined(SOC_SERIES_N32H47x_48x)
+ _n32_xspi.InitStructure.MST = cfg->role;
+ _n32_xspi.InitStructure.SSTE = cfg->nss_toggle;
+ _n32_xspi.InitStructure.DFS = cfg->data_frame_size;
+ _n32_xspi.InitStructure.SCPH = cfg->scph;
+ _n32_xspi.InitStructure.SCPOL = cfg->scpol;
+ _n32_xspi.InitStructure.TMOD = cfg->transfer_mode;
+ _n32_xspi.InitStructure.CLKDIV = cfg->baudr << 1; /* BAUD = baudr << 1, see official XSPI_QUAD demo */
+ _n32_xspi.InitStructure.SPIFRF = cfg->frame_format;
+ _n32_xspi.InitStructure.SEN = cfg->slave_sel;
+ _n32_xspi.InitStructure.SES = cfg->rxd_sampling_edge;
+ _n32_xspi.InitStructure.SDCN = cfg->rxd_sample_delay;
+#else
_n32_xspi.InitStructure.Role = cfg->role;
_n32_xspi.InitStructure.NssToggle = cfg->nss_toggle;
@@ -834,6 +1252,7 @@ rt_err_t rt_hw_xspi_device_attach(const char *bus_name, const char *device_name,
_n32_xspi.EnhInitStructure.WaitCycles = cfg->Enhance_WaitCycles;
_n32_xspi.EnhInitStructure.DDREable = cfg->Enhance_DDR;
}
+#endif
}
qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
@@ -856,7 +1275,9 @@ rt_err_t rt_hw_xspi_device_attach(const char *bus_name, const char *device_name,
return result;
}
+#if defined(SOC_SERIES_N32H7xx)
qspi_device->parent.parent.control = xspi_control;
+#endif
return result;
}
@@ -866,20 +1287,31 @@ rt_err_t rt_hw_xspi_device_attach(const char *bus_name, const char *device_name,
static int rt_hw_xspi_bus_init(void)
{
-#if defined(SOC_SERIES_N32H7xx)
+#if defined(SOC_SERIES_N32H47x_48x)
+ /* enable XSPI clock and release reset (single global XSPI instance) */
+ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_XSPI, ENABLE);
+ RCC_EnableAHBPeriphReset(RCC_AHB_PERIPHRST_XSPI);
+
+ _n32_xspi.bus_name = "qspi";
+#elif defined(SOC_SERIES_N32H49x)
+ /* enable XSPI clock and release reset */
+ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_XSPI, ENABLE);
+ RCC_EnableAHBPeriphReset(RCC_AHB_PERIPHRST_XSPI);
+
+ _n32_xspi.xSPIx = XSPI;
+ _n32_xspi.bus_name = "qspi";
+#else
RCC_EnableAHB5PeriphClk2(RCC_AHB5_PERIPHEN_PWR, ENABLE);
RCC_EnableAXIPeriphReset4(RCC_AXI_PERIPHRST_XSPI2);
RCC_EnableAXIPeriphClk4(RCC_AXI_PERIPHEN_M7_XSPI2, ENABLE);
-#endif
-
_n32_xspi.xSPIx = xSPI2;
_n32_xspi.bus_name = "qspi2";
-
+#endif
rt_completion_init(&_n32_xspi.cpt);
- return n32_xspi_register_bus(&_n32_xspi, "qspi2");
+ return n32_xspi_register_bus(&_n32_xspi, _n32_xspi.bus_name);
}
INIT_BOARD_EXPORT(rt_hw_xspi_bus_init);
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.h
index 113e614137..d44f3940be 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_qspi.h
@@ -12,12 +12,19 @@
#include <ipc/completion.h>
#include "drv_common.h"
+#if defined(SOC_SERIES_N32H47x_48x)
+#include "n32h47x_48x_xspi.h"
+#elif defined(SOC_SERIES_N32H49x)
+#include "n32h49x_xspi_v2.h"
+#else
#include "n32h7xx_xspi_v2.h"
+#endif
#ifdef __cplusplus
extern "C" {
#endif
+#if defined(SOC_SERIES_N32H7xx)
struct mdma_config
{
MDMA_ChNumType mdma_channel;
@@ -26,10 +33,12 @@ struct mdma_config
uint32_t dmamux_request;
uint32_t hs_interface;
};
+#endif
#define XSPI_USING_RX_DMA_FLAG (1 << 0)
#define XSPI_USING_TX_DMA_FLAG (1 << 1)
+#if defined(SOC_SERIES_N32H7xx)
typedef enum
{
XSPI_Tx_Rx = 0U,
@@ -38,17 +47,24 @@ typedef enum
XSPI_Idle,
} XSPI_Work_Direct_t;
+#endif
struct n32_xspi
{
+#if defined(SOC_SERIES_N32H47x_48x)
+ XSPI_InitType InitStructure; /* v1: single combined init struct, global XSPI instance */
+#else
XSPI_Module *xSPIx;
- char *bus_name;
XSPI_InitType InitStructure;
XSPI_EnhancedInitType EnhInitStructure;
- XSPI_XIPInitType XIPInitStructure;
+#endif
+ char *bus_name;
struct rt_qspi_configuration *qspi_cfg;
struct rt_spi_configuration *cfg;
+
+#if defined(SOC_SERIES_N32H7xx)
+ XSPI_XIPInitType XIPInitStructure;
XSPI_Work_Direct_t Direct;
rt_uint8_t xspi_dma_flag;
@@ -60,8 +76,10 @@ struct n32_xspi
MDMA_ChInitType RX_DMA_ChInitStr;
} dma;
- rt_uint8_t slave_sel;
rt_uint8_t xip_enabled;
+#endif
+
+ rt_uint8_t slave_sel;
struct rt_completion cpt;
};
@@ -89,6 +107,7 @@ struct n32_xspi_config
uint32_t Enhance_DDR;
};
+#if defined(SOC_SERIES_N32H7xx)
struct xspi_xip_config
{
uint32_t XipInstructLen;
@@ -111,6 +130,7 @@ struct xspi_xip_config
#define XSPI_CTRL_ENTER_XIP 0x01
#define XSPI_CTRL_EXIT_XIP 0x02
#define XSPI_CTRL_GET_XIP_ADDR 0x03
+#endif
rt_err_t rt_hw_xspi_device_attach(const char *bus_name, const char *device_name,
rt_uint8_t data_line_width,
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_sdram.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_sdram.c
index 34e76c09bd..eeb30afc19 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_sdram.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_sdram.c
@@ -13,8 +13,14 @@
#ifdef BSP_USING_SDRAM
#include <sdram_port.h>
+
+#if defined(SOC_SERIES_N32H7xx)
#include <n32h7xx_rcc.h>
#include <n32h7xx_sdram.h>
+#elif defined(SOC_SERIES_N32H49x)
+#include <n32h49x_rcc.h>
+#include <n32h49x_sdram.h>
+#endif
#define DRV_DEBUG
#define LOG_TAG "drv.sdram"
@@ -115,6 +121,7 @@ static SDRAM_DeviceType sdram_device;
* SDRAM Load Mode Register type (from N32 SDK bsp_sdram.h)
* Represents the value sent to the SDRAM chip via LOADMODE command.
*---------------------------------------------------------------------------*/
+#if defined(SOC_SERIES_N32H7xx)
typedef union
{
uint32_t cmd;
@@ -128,6 +135,7 @@ typedef union
uint32_t Reserved : 22;
} Bits;
} SDRAM_LoadModeRegisterType;
+#endif
/* Mode register field values (from N32 SDK bsp_sdram.h) */
#define LOADMODE_BURSTLEN_1 0
@@ -147,9 +155,16 @@ typedef union
*---------------------------------------------------------------------------*/
rt_weak void rt_hw_sdram_clock_init(void)
{
+#if defined(SOC_SERIES_N32H7xx)
/* Configure SDRAM delay chain (board-specific, default 0.2ns step) */
RCC_ConfigSDRAMDelay(RCC_SDRAM_DELAY_0_2NS);
RCC_EnableSDRAMDelayChain(ENABLE);
+#elif defined(SOC_SERIES_N32H49x)
+ /* Configure SDRAM clock */
+ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_SDRAM, ENABLE);
+ /* Configure SDRAM delay chain (board-specific, default 0.5) */
+ SDRAM_ConfigSampleDelay(SDRAM_DELAY_0_5_PERIOD);
+#endif
}
/*----------------------------------------------------------------------------
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.c
index 5188b2639a..734d45fbc3 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.c
@@ -84,6 +84,296 @@ static struct n32_spi_config spi_config[] = {
static struct n32_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])] = { 0 };
+#if defined(SOC_SERIES_N32H7xx)
+/* Static 0xFF fill source for 4-wire full-duplex MASTER receive-only DMA.
+ * A recv-only master still has to clock the bus, so the TX DMA pushes this
+ * fill pattern onto MOSI while the RX DMA captures into the caller's buffer.
+ * Sized for the widest single read of the buffer: one DMA block holds at
+ * most 4095 items, and at 16-bit width that is 4095 * 2 = 8190B (8-bit:
+ * 4095B). LLI nodes never read further because n32_spi_dma_arm re-points
+ * every node's SrcAddr at the base, so each node re-reads at most one block
+ * from the start. Filled once in rt_hw_spi_bus_init and read-only afterwards
+ * -> one shared instance for every SPI bus is safe. */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 6010050)
+#define N32_SPI_DUMMY_ALIGN32 __align(32)
+#else
+#define N32_SPI_DUMMY_ALIGN32 __attribute__((aligned(32)))
+#endif
+N32_SPI_DUMMY_ALIGN32 static rt_uint8_t spi_fd_rxonly_dummy[8192];
+#endif /* SOC_SERIES_N32H7xx */
+
+
+#if defined(SOC_SERIES_N32H7xx)
+/* Build an LLI chain for a 'size'-byte transfer: the memory side advances
+ * 4095B per node while the peripheral (DAT) address stays fixed. Only the
+ * last node has IntEn=1, so the whole chain raises a single TC interrupt. */
+static rt_uint16_t n32_spi_lli_build(DMA_LinkListItemType *lli, const DMA_ChInitType *ch,
+ rt_uint32_t periph_addr, rt_uint32_t mem_addr,
+ rt_bool_t mem_is_src, rt_uint16_t size)
+{
+ rt_uint16_t n = (rt_uint16_t)((size + SPI_DMA_BLOCK_MAX - 1U) / SPI_DMA_BLOCK_MAX);
+ rt_uint16_t i;
+ rt_uint16_t rest = size;
+
+ for (i = 0; i < n; i++)
+ {
+ DMA_LinkListItemType *node = &lli[i];
+ rt_uint16_t blk = (rest > SPI_DMA_BLOCK_MAX) ? SPI_DMA_BLOCK_MAX : rest;
+ rt_bool_t has_next = (i + 1U < n) ? RT_TRUE : RT_FALSE;
+
+ node->SrcAddr = mem_is_src ? (mem_addr + (rt_uint32_t)i * SPI_DMA_BLOCK_MAX) : periph_addr;
+ node->DstAddr = mem_is_src ? periph_addr : (mem_addr + (rt_uint32_t)i * SPI_DMA_BLOCK_MAX);
+ node->pNext = has_next ? &lli[i + 1U] : RT_NULL;
+ node->IntEn = has_next ? 0U : 1U;
+ node->DstTfrWidth = ch->DstTfrWidth;
+ node->SrcTfrWidth = ch->SrcTfrWidth;
+ node->DstAddrCountMode = ch->DstAddrCountMode;
+ node->SrcAddrCountMode = ch->SrcAddrCountMode;
+ node->DstBurstLen = ch->DstBurstLen;
+ node->SrcBurstLen = ch->SrcBurstLen;
+ node->SrcGatherEn = ch->SrcGatherEn;
+ node->DstScatterEn = ch->DstScatterEn;
+ node->TfrTypeFlowCtrl = ch->TfrTypeFlowCtrl;
+ node->DstLinkedListEn = has_next ? 1U : 0U;
+ node->SrcLinkedListEn = has_next ? 1U : 0U;
+ node->BlkTfrSize = blk;
+ rest -= blk;
+ }
+ return n;
+}
+
+/* Arm one RX/TX DMA channel:
+ * - size <= 4095 : single-block transfer (original behaviour)
+ * - size > 4095 : seamless LLI-chain transfer (no software gap
+ * between blocks, so a clock-driven slave never
+ * drops bytes)
+ * - active == RT_FALSE : arm the channel as an empty block (this direction
+ * does not take part in this transfer) */
+static rt_err_t n32_spi_dma_arm(struct n32_spi *spi_drv, rt_bool_t is_rx,
+ rt_bool_t active, uint8_t *buf, rt_uint16_t size)
+{
+ struct dma_config *cfg = is_rx ? spi_drv->config->dma_rx : spi_drv->config->dma_tx;
+ DMA_ChInitType *ch = is_rx ? &spi_drv->dma.RX_DMA_ChInitStr : &spi_drv->dma.TX_DMA_ChInitStr;
+ DMA_LinkListItemType *lli = is_rx ? spi_drv->dma.lli_rx : spi_drv->dma.lli_tx;
+
+ DMA_ChannelCmd(cfg->Instance, cfg->dma_channel, DISABLE);
+
+ if (!DMA_ControllerIsEnabled(cfg->Instance))
+ {
+ DMA_ControllerCmd(cfg->Instance, ENABLE);
+ }
+ DMA_ControllerCmd(cfg->Instance, ENABLE);
+
+ if (!active)
+ {
+ /* Empty arm: this direction does not take part in this transfer */
+ ch->IntEn = 0U;
+ if (is_rx)
+ {
+ ch->DstAddr = (uint32_t)RT_NULL;
+ }
+ else
+ {
+ ch->SrcAddr = (uint32_t)RT_NULL;
+ }
+ ch->BlkTfrSize = 0U;
+ ch->pLinkListItem = RT_NULL;
+ ch->TfrType = DMA_CH_TRANSFER_TYPE_SINGLE_BLOCK;
+ if (DMA_ChannelInit(cfg->Instance, ch, cfg->dma_channel) != 0U)
+ {
+ LOG_E(is_rx ? "Master DMA Rx channel initialization failed."
+ : "Master DMA Tx channel initialization failed.");
+ return -RT_ERROR;
+ }
+ return RT_EOK;
+ }
+
+ /* Active direction: load the buffer address and block size */
+ if (is_rx)
+ {
+ /* Unconditionally drain any stale DAT/RNE byte before arming: once
+ * RDMAEN is set, the first DMA transfer would swallow a leftover byte
+ * as rx[0] (slave first-byte right-shift plus trailing RNE=1).
+ * Cross-case residue is exactly this source. */
+ SPI_I2S_ReceiveData(spi_drv->config->SPIx);
+ SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG);
+
+ ch->DstAddr = (uint32_t)buf;
+ }
+ else
+ {
+ ch->SrcAddr = (uint32_t)buf;
+ }
+
+ if (size > SPI_DMA_BLOCK_MAX)
+ {
+ /* Seamless chain transfer: the whole message is one DMA task, so
+ * there is no reload gap between blocks */
+ rt_uint16_t nodes;
+
+ nodes = n32_spi_lli_build(lli, ch, (uint32_t)&spi_drv->config->SPIx->DAT,
+ (uint32_t)buf, !is_rx, size);
+ if ((!is_rx) && spi_drv->fd_rxonly_dummy_tx)
+ {
+ /* FD master recv-only: the TX source is the 0xFF fill buffer.
+ * Re-point every LLI node at its base - without this the chain
+ * steps 4095B per node and would walk past the fill buffer.
+ * Each node then re-reads its own block (<= 4095 items, <= the
+ * 8192B fill) from the base, which is exactly the constant 0xFF
+ * stream this path must clock. */
+ rt_uint16_t k;
+
+ for (k = 0U; k < nodes; k++)
+ {
+ lli[k].SrcAddr = (uint32_t)buf;
+ }
+ }
+ ch->pLinkListItem = &lli[0];
+ ch->TfrType = DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_LINKED_DSTADR_LINKED;
+ ch->BlkTfrSize = SPI_DMA_BLOCK_MAX; /* channel's first block matches lli[0] */
+ }
+ else
+ {
+ ch->pLinkListItem = RT_NULL;
+ ch->TfrType = DMA_CH_TRANSFER_TYPE_SINGLE_BLOCK;
+ ch->BlkTfrSize = size;
+ }
+ ch->IntEn = 1U;
+
+ if (DMA_ChannelInit(cfg->Instance, ch, cfg->dma_channel) == 0U)
+ {
+ /* Clear stale TC/error events first: a TC flag left by the previous
+ * case would fire a bogus completion interrupt as soon as the channel
+ * is enabled, completing the slave DMA before the real data has
+ * arrived (BUSY stuck; mode2 symptom). */
+ DMA_ClearChannelEventStatus(cfg->Instance, cfg->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE);
+ DMA_ClearChannelEventStatus(cfg->Instance, cfg->dma_channel, DMA_CH_EVENT_ERROR);
+
+ /* Enable transaction complete interrupt event */
+ DMA_ChannelEventCmd(cfg->Instance, cfg->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, ENABLE);
+
+ /* Order matters: set the SPI-side RDMAEN/TDMAEN first, then enable the
+ * DMA channel. The reverse order leaves a window in which a first byte
+ * received by a clock-driven slave is not moved out by any DMA request
+ * and stays in DAT, shifting all following real data (slave rx
+ * right-shift, first byte lost). A slave is armed before the master
+ * clock starts, so this order is safe. */
+ SPI_I2S_EnableDma(spi_drv->config->SPIx,
+ is_rx ? SPI_I2S_DMA_RX : SPI_I2S_DMA_TX, ENABLE);
+
+ /* Enable the specified DMA channel */
+ DMA_ChannelCmd(cfg->Instance, cfg->dma_channel, ENABLE);
+ }
+ else
+ {
+ LOG_E("DMA channel init fail: %s ch%u size=%u (leaving RDMAEN off)",
+ is_rx ? "RX" : "TX", cfg->dma_channel, size);
+ return -RT_ERROR;
+ }
+ return RT_EOK;
+}
+#endif /* SOC_SERIES_N32H7xx */
+
+/* True when this device is a mode2 (CPOL=1/CPHA=0) full-duplex master. Such
+ * transfers use the "engine always-on + warm-engine level-triggered DMA"
+ * scheme (see the SPI_DMA_TransmitReceive notes, the spixfer message tail and
+ * the n32_spi_init configure pre-enable). On the always-selected 4-wire
+ * cross-wiring used by the test board (SPI1 master <-> SPI2 slave), a mode2
+ * slave counts the SCK LOW->HIGH edge of the master SPIEN 0->1 into its bit
+ * phase and the whole frame grid shifts (the slave SPIEN 0->1 by itself also
+ * pulls SCK low; no GPIO pull can fight an ms-scale gap - the vendor demo
+ * only passes because its two enables are ns apart, a timing coincidence
+ * disproved by a log-delay experiment). Keeping the master engine on makes
+ * the slave arm against an SCK line already clamped idle-high by the master's
+ * push-pull driver, and message start no longer creates a 0->1 edge. */
+static rt_bool_t n32_spi_mode2_fd_master(struct n32_spi *spi_drv)
+{
+ return (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER) &&
+ (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_FULLDUPLEX) &&
+ (spi_drv->SPI_InitStructure.CLKPOL == SPI_CLKPOL_HIGH) &&
+ (spi_drv->SPI_InitStructure.CLKPHA == SPI_CLKPHA_FIRST_EDGE);
+}
+
+/* Same always-on treatment for a 3-wire (single-line) mode2 master. Its
+ * per-message cold start (SPIEN 0->1) drops the SCK pad low first and then
+ * rises into the already-enabled mode2 slave, so the slave bit counter
+ * gains one spurious edge and the whole frame grid shifts by one bit
+ * (rx[j] = (b[j-1] & 1) << 7 | b[j] >> 1; modes 0/1/3 sample after the
+ * data lands and are immune). Keeping this engine on clamps SCK idle-high
+ * exactly like the FD variant. Mutually exclusive with it: FD requires
+ * DOUBLELINE_FULLDUPLEX, this requires SINGLELINE, so a bus never matches
+ * both. */
+static rt_bool_t n32_spi_mode2_3w_master(struct n32_spi *spi_drv)
+{
+ return (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER) &&
+ (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_TX ||
+ spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_RX) &&
+ (spi_drv->SPI_InitStructure.CLKPOL == SPI_CLKPOL_HIGH) &&
+ (spi_drv->SPI_InitStructure.CLKPHA == SPI_CLKPHA_FIRST_EDGE);
+}
+
+/* Warm (SPIEN=1) BIDI direction flip for the always-on mode2 3-wire master.
+ * SPI_Init cannot do a TX->RX flip on a live engine: the vendor CLR_MASK
+ * (0xF9F7, n32h7xx_spi.c) preserves bit14 (BIDIOE) under its &=, so Init
+ * with SINGLELINE_RX silently leaves the engine in TX and a BA leg then
+ * waits for an RX-DMA interrupt that can never fire. Toggle only the
+ * BIDI output-enable bit instead, keeping SPIEN=1 so SCK never drops:
+ * bit14 set = TX (master drives, line clamped idle-high, nothing clocks
+ * until DAT is written); bit14 clear = RX (the mode2 receiver free-runs
+ * from that moment until the direction leaves RX, so the RX DMA must be
+ * armed before the clear). */
+static void n32_spi_mode2_3w_set_dir(struct n32_spi *spi_drv, uint16_t dir)
+{
+ if (dir == SPI_DIR_SINGLELINE_TX)
+ {
+ spi_drv->config->SPIx->CTRL1 |= SPI_BIDIRECTION_TX;
+ }
+ else
+ {
+ spi_drv->config->SPIx->CTRL1 &= SPI_BIDIRECTION_RX;
+ }
+ spi_drv->SPI_InitStructure.DataDirection = dir;
+}
+
+/* Error/abort path for the always-on mode2 3-wire master: a failed or
+ * aborted receive must not leave the RX engine free-running (it clocks
+ * SCK continuously until the direction leaves RX), so flip back to the
+ * TX-idle rest posture and clear the stale byte. No-op for every other
+ * role/direction. */
+static void n32_spi_mode2_3w_rx_abort(struct n32_spi *spi_drv)
+{
+ if (n32_spi_mode2_3w_master(spi_drv))
+ {
+ n32_spi_mode2_3w_set_dir(spi_drv, SPI_DIR_SINGLELINE_TX);
+ SPI_I2S_ReceiveData(spi_drv->config->SPIx);
+ SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG);
+ }
+}
+
+/* Switch the 3-wire single-line data direction. A mode2 3-wire master keeps
+ * its engine on, so its flip must not drop SPIEN (that would pull SCK low
+ * and re-introduce the spurious-edge shift on the enabled slave): its warm
+ * flip is a direct BIDIOE toggle (n32_spi_mode2_3w_set_dir - SPI_Init
+ * cannot clear BIDIOE warm, see above). Everyone else keeps the legacy cold
+ * cycle (disable + peripheral DeInit + Init), whose reset also re-zeros the
+ * slave bit counter. */
+static void n32_spi_singleline_dir(struct n32_spi *spi_drv, uint16_t dir)
+{
+ if (n32_spi_mode2_3w_master(spi_drv))
+ {
+ n32_spi_mode2_3w_set_dir(spi_drv, dir);
+ }
+ else
+ {
+ /* Disable the sFLASH_SPI */
+ SPI_Enable(spi_drv->config->SPIx, DISABLE);
+ /* DeInitializes the sFLASH_SPI */
+ SPI_I2S_DeInit(spi_drv->config->SPIx);
+ spi_drv->SPI_InitStructure.DataDirection = dir;
+ SPI_Init(spi_drv->config->SPIx, &spi_drv->SPI_InitStructure);
+ }
+}
+
static rt_err_t SPI_DMA_TransmitReceive(struct n32_spi *spi_drv, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
{
RT_ASSERT(spi_drv != RT_NULL);
@@ -95,32 +385,119 @@ static rt_err_t SPI_DMA_TransmitReceive(struct n32_spi *spi_drv, uint8_t *pTxDat
return -RT_ERROR;
}
+ /* Clear any stale RX residue BEFORE arming RX/TX DMA: once RDMAEN is set
+ * the first DMA transfer would swallow a leftover byte in DAT as rx[0]
+ * (slave-side 1-byte right-shift + trailing RNE=1 symptom). For a slave
+ * the master has not started clocking yet, so no real first byte can be
+ * lost here. */
+ SPI_I2S_ReceiveData(spi_drv->config->SPIx);
+ SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG);
+
+ /* FD engine cold-start scheme (non-mode2 path): each transfer disables
+ * first, then arms, and enables at the end. While SPIEN=0 the TE=0 keeps
+ * the TX DMA request away; TE becomes 1 only after the SPIEN 0->1, so the
+ * request looks like a "TE 0->1 edge trigger" (warm-engine probes proved
+ * the request is actually level-triggered; see the mode2 notes below).
+ * The 3-wire path uses the same scheme in SPI_DMA_Transmit (verified).
+ *
+ * But SPIEN 1->0 pulls the SCK pad low on CPOL=1 (idle-high) configs: the
+ * slave bit counter counts falling edges, so a stray edge shifts the
+ * whole round's frame grid by k bits; and SPIEN 0->1 does not clear the
+ * slave bit counter (measured: mode3 rounds>=1 shift the whole frame by k
+ * bits - slave receives (prev.byte bit0<<7)|(this.byte>>1), master
+ * receives (this.byte<<1)|(next.byte>>7); byte-level deterministic.
+ * Modes 0/1 with CPOL=0 idle-low have no transition and are immune).
+ * Mitigation (see the marked places below):
+ * a) Slave: run a peripheral DeInit+Init here (the same one configure
+ * uses) - only a peripheral reset clears the bit counter, so the
+ * slave phase is zeroed before frame 0 of every round;
+ * b) Master: never drop the line at the top of an arm - the disable
+ * always happens at the message tail (the spixfer bus-release point),
+ * making the disable here a no-op for master and slave; the tail drop
+ * falls into the slave's own finish period of this round and is
+ * cleared by the slave's next arm reset.
+ *
+ * mode2 (CPOL=1, CPHA=0) extra problem: the scheme above cold-starts the
+ * master SPIEN 0->1 after the slave is enabled, and that 0->1 SCK
+ * LOW->HIGH rising edge is counted by a mode2 slave -> whole-frame k-bit
+ * offset from the first frame (pad-bit fingerprints b2 67 9d 52...,
+ * matched byte-for-byte on a full 4096B frame). A mode2 FD master
+ * therefore never cold-starts: the engine is pre-enabled at configure and
+ * kept across messages (not disabled at the spixfer message tail), and no
+ * disable/enable cycle happens here. On a warm engine the TX DMA request
+ * is level-triggered: with TE=1 the channel enable alone fires it (after
+ * RX/TX arm with no CPU write at all, TE goes 1->0, data flows by itself
+ * and the ISR completes normally; during a cold start SPIEN=0 keeps TE=0,
+ * so the request only appears after SPIEN 0->1 and looks edge-triggered).
+ * The original CPU-seed write raced the DMA self-start (the seed written
+ * into a full DAT was swallowed and the first byte shifted) and has been
+ * removed. When the engine is (unexpectedly) off, fall back to the
+ * traditional cold-start cycle as before. */
+ /* Warm re-arm: arming a MASTER whose SPIEN is still set is legitimate
+ * only for (a) the always-on mode2 FD master (see the notes above) and
+ * (b) a non-first chunk of a 4-wire full-duplex message -- spixfer marks
+ * (b) with fd_chunk_cont because it keeps the engine on across chunk
+ * boundaries (only the message tail disables). In both cases SPIEN must
+ * NOT be dropped here: the 1->0 pulls the SCK pad low on CPOL=1
+ * (idle-high) and the 0->1 re-enable raises it again -- both edges land
+ * on the enabled mid-arm slave, whose bit counter counts them and shifts
+ * its TX reply (a chunked 8192-element mode3 message corrupts from byte
+ * 4096 onward). On the warm engine the TX
+ * DMA request is level-triggered (note above): the channel enable alone
+ * fires it, so no SPI enable is needed either. Every other arm -- slave
+ * (phase reset below) or a master whose engine is off -- keeps the
+ * traditional cold-start cycle. */
+ rt_bool_t engine_warm = RT_FALSE;
+ if (spi_drv->fd_chunk_cont &&
+ (spi_drv->SPI_InitStructure.SpiMode != SPI_MODE_SLAVE) &&
+ ((spi_drv->config->SPIx->CTRL2 & SPI_CTRL2_SPIEN) != 0U))
+ {
+ engine_warm = RT_TRUE;
+ }
+ else if (n32_spi_mode2_fd_master(spi_drv) &&
+ (Size > 1U) &&
+ ((spi_drv->config->SPIx->CTRL2 & SPI_CTRL2_SPIEN) != 0U))
+ {
+ engine_warm = RT_TRUE;
+ }
+ else
+ {
+ SPI_Enable(spi_drv->config->SPIx, DISABLE);
+ }
+ if (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE)
+ {
+ SPI_I2S_DeInit(spi_drv->config->SPIx);
+ SPI_Init(spi_drv->config->SPIx, &spi_drv->SPI_InitStructure);
+ }
+
if (spi_drv->dma.DMA_Rx_Init == RT_TRUE)
{
#if defined(SOC_SERIES_N32H7xx)
- /* SPI RX DMA Receive Data */
- DMA_ChannelCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DISABLE);
-
- if (!DMA_ControllerIsEnabled(spi_drv->config->dma_rx->Instance))
+ /* SPI RX DMA receive (single block or seamless LLI chain) */
+ if (n32_spi_dma_arm(spi_drv, RT_TRUE, RT_TRUE, pRxData, Size) != RT_EOK)
{
- DMA_ControllerCmd(spi_drv->config->dma_rx->Instance, ENABLE);
+ SPI_Enable(spi_drv->config->SPIx, ENABLE);
+ return -RT_ERROR;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* SPI RX DMA Receive Data for H49X */
+ DMA_EnableChannel(spi_drv->config->dma_rx->DMAChx, DISABLE);
- spi_drv->dma.RX_DMA_ChInitStr.IntEn = 1U;
- spi_drv->dma.RX_DMA_ChInitStr.DstAddr = (uint32_t)pRxData;
- spi_drv->dma.RX_DMA_ChInitStr.BlkTfrSize = Size;
+ /* Configure DMA request remapping */
+ DMA_RequestRemap(spi_drv->config->dma_rx->request, spi_drv->config->dma_rx->DMAChx, ENABLE);
- DMA_ControllerCmd(spi_drv->config->dma_rx->Instance, ENABLE);
- if (DMA_ChannelInit(spi_drv->config->dma_rx->Instance, &spi_drv->dma.RX_DMA_ChInitStr, spi_drv->config->dma_rx->dma_channel) == 0U)
- {
- /* Enable transaction complete interrupt event */
- DMA_ChannelEventCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, ENABLE);
+ spi_drv->dma.RX_DMA_ChInitStr.MemAddr = (uint32_t)pRxData;
+ spi_drv->dma.RX_DMA_ChInitStr.BufSize = Size;
- /* Enable the specified DMA channel */
- DMA_ChannelCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, ENABLE);
+ DMA_Init(spi_drv->config->dma_rx->DMAChx, &spi_drv->dma.RX_DMA_ChInitStr);
- SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_RX, ENABLE);
- }
+ /* Enable transfer complete interrupt */
+ DMA_ConfigInt(spi_drv->config->dma_rx->DMAChx, DMA_INT_TXC, ENABLE);
+
+ /* Enable the specified DMA channel */
+ DMA_EnableChannel(spi_drv->config->dma_rx->DMAChx, ENABLE);
+
+ SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_RX, ENABLE);
#endif
}
else
@@ -132,50 +509,54 @@ static rt_err_t SPI_DMA_TransmitReceive(struct n32_spi *spi_drv, uint8_t *pTxDat
if (spi_drv->dma.DMA_Tx_Init == RT_TRUE)
{
#if defined(SOC_SERIES_N32H7xx)
- /* SPI TX DMA Send Data */
- DMA_ChannelCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DISABLE);
-
- if (!DMA_ControllerIsEnabled(spi_drv->config->dma_tx->Instance))
+ /* SPI TX DMA send (single block or seamless LLI chain). On a warm
+ * engine (engine_warm) the channel enable level-triggers the transfer
+ * (see the big note above); the first byte goes out from the source
+ * start address, no seed needed. */
+ if (n32_spi_dma_arm(spi_drv, RT_FALSE, RT_TRUE, pTxData, Size) != RT_EOK)
{
- DMA_ControllerCmd(spi_drv->config->dma_tx->Instance, ENABLE);
+ SPI_Enable(spi_drv->config->SPIx, ENABLE);
+ return -RT_ERROR;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* SPI TX DMA Send Data for H49X */
+ DMA_EnableChannel(spi_drv->config->dma_tx->DMAChx, DISABLE);
- spi_drv->dma.TX_DMA_ChInitStr.IntEn = 1U;
- spi_drv->dma.TX_DMA_ChInitStr.SrcAddr = (uint32_t)pTxData;
- spi_drv->dma.TX_DMA_ChInitStr.BlkTfrSize = Size;
+ /* Configure DMA request remapping */
+ DMA_RequestRemap(spi_drv->config->dma_tx->request, spi_drv->config->dma_tx->DMAChx, ENABLE);
- DMA_ControllerCmd(spi_drv->config->dma_tx->Instance, ENABLE);
- if (DMA_ChannelInit(spi_drv->config->dma_tx->Instance, &spi_drv->dma.TX_DMA_ChInitStr, spi_drv->config->dma_tx->dma_channel) == 0U)
- {
- /* Enable transaction complete interrupt event */
- DMA_ChannelEventCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, ENABLE);
+ spi_drv->dma.TX_DMA_ChInitStr.MemAddr = (uint32_t)pTxData;
+ spi_drv->dma.TX_DMA_ChInitStr.BufSize = Size;
- /* Enable the specified DMA channel */
- DMA_ChannelCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, ENABLE);
+ DMA_Init(spi_drv->config->dma_tx->DMAChx, &spi_drv->dma.TX_DMA_ChInitStr);
- SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_TX, ENABLE);
- }
+ /* Enable transfer complete interrupt */
+ DMA_ConfigInt(spi_drv->config->dma_tx->DMAChx, DMA_INT_TXC, ENABLE);
+
+ /* Enable the specified DMA channel */
+ DMA_EnableChannel(spi_drv->config->dma_tx->DMAChx, ENABLE);
+
+ SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_TX, ENABLE);
#endif
}
else
{
LOG_E("In full-duplex mode, TX DMA did not complete initialization.");
+ SPI_Enable(spi_drv->config->SPIx, ENABLE);
return -RT_ERROR;
}
- /* Clear Over Flag */
- SPI_I2S_ReceiveData(spi_drv->config->SPIx);
- SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG);
-
/* Enable Error Interrupt */
SPI_I2S_EnableInt(spi_drv->config->SPIx, SPI_I2S_INT_ERR, ENABLE);
/* Set SPI Direction */
spi_drv->Direct = SPI_Tx_Rx;
- /* Check if the SPI is already enabled */
- if ((spi_drv->config->SPIx->CTRL2 & SPI_CTRL2_SPIEN) != SPI_CTRL2_SPIEN)
+ if (!engine_warm)
{
+ /* Enable 0->1 after arming: the TE rising edge happens only once
+ * RDMAEN/TDMAEN and both DMA channels are ready, so the first-byte TX
+ * request can actually go out (see the note above). */
SPI_Enable(spi_drv->config->SPIx, ENABLE);
}
@@ -189,63 +570,52 @@ static rt_err_t SPI_DMA_Transmit(struct n32_spi *spi_drv, uint8_t *pData, uint16
if (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_RX ||
spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_TX)
{
- /* Disable the sFLASH_SPI */
- SPI_Enable(spi_drv->config->SPIx, DISABLE);
- /* DeInitializes the sFLASH_SPI */
- SPI_I2S_DeInit(spi_drv->config->SPIx);
- /* Set the sFLASH_SPI SendOnly*/
- spi_drv->SPI_InitStructure.DataDirection = SPI_DIR_SINGLELINE_TX;
- SPI_Init(spi_drv->config->SPIx, &spi_drv->SPI_InitStructure);
+ n32_spi_singleline_dir(spi_drv, SPI_DIR_SINGLELINE_TX);
}
if (spi_drv->dma.DMA_Rx_Init == RT_TRUE)
{
#if defined(SOC_SERIES_N32H7xx)
- DMA_ChannelCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DISABLE);
-
- if (!DMA_ControllerIsEnabled(spi_drv->config->dma_rx->Instance))
+ /* Send mode: the RX channel is armed as an empty block (this direction does not take part) */
+ if (n32_spi_dma_arm(spi_drv, RT_TRUE, RT_FALSE, RT_NULL, 0U) != RT_EOK)
{
- DMA_ControllerCmd(spi_drv->config->dma_rx->Instance, ENABLE);
+ return -RT_ERROR;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
- spi_drv->dma.RX_DMA_ChInitStr.IntEn = 0U;
- spi_drv->dma.RX_DMA_ChInitStr.DstAddr = NULL;
- spi_drv->dma.RX_DMA_ChInitStr.BlkTfrSize = 0U;
+ DMA_EnableChannel(spi_drv->config->dma_rx->DMAChx, DISABLE);
+ spi_drv->dma.RX_DMA_ChInitStr.MemAddr = 0;
+ spi_drv->dma.RX_DMA_ChInitStr.BufSize = 0;
- DMA_ControllerCmd(spi_drv->config->dma_rx->Instance, ENABLE);
- if (DMA_ChannelInit(spi_drv->config->dma_rx->Instance, &spi_drv->dma.RX_DMA_ChInitStr, spi_drv->config->dma_rx->dma_channel) != 0U)
- {
- LOG_E("Master DMA Rx channel initialization failed.");
- return -RT_ERROR;
- }
+ DMA_EnableChannel(spi_drv->config->dma_rx->DMAChx, ENABLE);
+ DMA_Init(spi_drv->config->dma_rx->DMAChx, &spi_drv->dma.RX_DMA_ChInitStr);
#endif
}
if (spi_drv->dma.DMA_Tx_Init == RT_TRUE)
{
#if defined(SOC_SERIES_N32H7xx)
- DMA_ChannelCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DISABLE);
+ /* SPI TX DMA send (single block or seamless LLI chain) */
+ n32_spi_dma_arm(spi_drv, RT_FALSE, RT_TRUE, pData, Size);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* SPI TX DMA Send Data for H49X */
+ DMA_EnableChannel(spi_drv->config->dma_tx->DMAChx, DISABLE);
- if (!DMA_ControllerIsEnabled(spi_drv->config->dma_tx->Instance))
- {
- DMA_ControllerCmd(spi_drv->config->dma_tx->Instance, ENABLE);
- }
+ /* Configure DMA request remapping */
+ DMA_RequestRemap(spi_drv->config->dma_tx->request, spi_drv->config->dma_tx->DMAChx, ENABLE);
- spi_drv->dma.TX_DMA_ChInitStr.IntEn = 1U;
- spi_drv->dma.TX_DMA_ChInitStr.SrcAddr = (uint32_t)pData;
- spi_drv->dma.TX_DMA_ChInitStr.BlkTfrSize = Size;
+ spi_drv->dma.TX_DMA_ChInitStr.MemAddr = (uint32_t)pData;
+ spi_drv->dma.TX_DMA_ChInitStr.BufSize = Size;
- DMA_ControllerCmd(spi_drv->config->dma_tx->Instance, ENABLE);
- if (DMA_ChannelInit(spi_drv->config->dma_tx->Instance, &spi_drv->dma.TX_DMA_ChInitStr, spi_drv->config->dma_tx->dma_channel) == 0U)
- {
- /* Enable transaction complete interrupt event */
- DMA_ChannelEventCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, ENABLE);
+ DMA_Init(spi_drv->config->dma_tx->DMAChx, &spi_drv->dma.TX_DMA_ChInitStr);
- /* Enable the specified DMA channel */
- DMA_ChannelCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, ENABLE);
+ /* Enable transfer complete interrupt */
+ DMA_ConfigInt(spi_drv->config->dma_tx->DMAChx, DMA_INT_TXC, ENABLE);
- SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_TX, ENABLE);
- }
+ /* Enable the specified DMA channel */
+ DMA_EnableChannel(spi_drv->config->dma_tx->DMAChx, ENABLE);
+
+ SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_TX, ENABLE);
#endif
}
else
@@ -272,46 +642,81 @@ static rt_err_t SPI_DMA_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_
if (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_FULLDUPLEX && spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER)
{
+#if defined(SOC_SERIES_N32H7xx)
+ /* Master recv-only in 4-wire full-duplex still has to clock the bus,
+ * but must not echo the caller's RX buffer onto MOSI (the old bug:
+ * TX DMA sourced pData itself and pushed the pre-message RX contents
+ * out on MOSI). The TX leg now reads the static 0xFF fill buffer; the
+ * fd_rxonly_dummy_tx flag makes n32_spi_dma_arm re-point every LLI TX
+ * node at the fill base. RX keeps capturing into pData and the arm
+ * order / Direct / ISR / warm-arm (engine_warm) semantics of
+ * SPI_DMA_TransmitReceive are unchanged (it stays textually
+ * untouched; completion still arrives via spi_rx_dma_isr on
+ * Direct == SPI_Tx_Rx). */
+ rt_err_t result;
+
+ spi_drv->fd_rxonly_dummy_tx = RT_TRUE;
+ result = SPI_DMA_TransmitReceive(spi_drv, spi_fd_rxonly_dummy, pData, Size);
+ spi_drv->fd_rxonly_dummy_tx = RT_FALSE;
+ return result;
+#else
return SPI_DMA_TransmitReceive(spi_drv, pData, pData, Size);
+#endif
}
+ rt_bool_t m2warm_rx_defer = RT_FALSE;
+
if (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_RX ||
spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_TX)
{
- /* Disable the sFLASH_SPI */
- SPI_Enable(spi_drv->config->SPIx, DISABLE);
- /* DeInitializes the sFLASH_SPI */
- SPI_I2S_DeInit(spi_drv->config->SPIx);
- /* Set the sFLASH_SPI SendOnly*/
- spi_drv->SPI_InitStructure.DataDirection = SPI_DIR_SINGLELINE_RX;
- SPI_Init(spi_drv->config->SPIx, &spi_drv->SPI_InitStructure);
+ if (n32_spi_mode2_3w_master(spi_drv))
+ {
+ /* Always-on mode2 master: defer the RX flip until both DMA
+ * channels are armed below. The flip itself starts the
+ * free-running receiver, so the residue drain and the arms must
+ * come first or the opening bytes are missed; a cold engine
+ * additionally needs the SPIEN 0->1 enable after the arms,
+ * which the deferred flip then also covers. */
+ m2warm_rx_defer = RT_TRUE;
+ }
+ else
+ {
+ n32_spi_singleline_dir(spi_drv, SPI_DIR_SINGLELINE_RX);
+ }
}
+ /* Clear any stale RX residue BEFORE arming the RX DMA channel: once
+ * RDMAEN is set the first DMA transfer would swallow a leftover byte in
+ * DAT as rx[0] (slave-side 1-byte right-shift + trailing RNE=1 symptom).
+ * For a slave the master has not started clocking yet, so no real first
+ * byte can be lost here. */
+ SPI_I2S_ReceiveData(spi_drv->config->SPIx);
+ SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG);
+
if (spi_drv->dma.DMA_Rx_Init == RT_TRUE)
{
#if defined(SOC_SERIES_N32H7xx)
- DMA_ChannelCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DISABLE);
+ /* SPI RX DMA receive (single block or seamless LLI chain) */
+ n32_spi_dma_arm(spi_drv, RT_TRUE, RT_TRUE, pData, Size);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* SPI RX DMA Receive Data for H49X */
+ DMA_EnableChannel(spi_drv->config->dma_rx->DMAChx, DISABLE);
- if (!DMA_ControllerIsEnabled(spi_drv->config->dma_rx->Instance))
- {
- DMA_ControllerCmd(spi_drv->config->dma_rx->Instance, ENABLE);
- }
+ /* Configure DMA request remapping */
+ DMA_RequestRemap(spi_drv->config->dma_rx->request, spi_drv->config->dma_rx->DMAChx, ENABLE);
- spi_drv->dma.RX_DMA_ChInitStr.IntEn = 1U;
- spi_drv->dma.RX_DMA_ChInitStr.DstAddr = (uint32_t)pData;
- spi_drv->dma.RX_DMA_ChInitStr.BlkTfrSize = Size;
+ spi_drv->dma.RX_DMA_ChInitStr.MemAddr = (uint32_t)pData;
+ spi_drv->dma.RX_DMA_ChInitStr.BufSize = Size;
- DMA_ControllerCmd(spi_drv->config->dma_rx->Instance, ENABLE);
- if (DMA_ChannelInit(spi_drv->config->dma_rx->Instance, &spi_drv->dma.RX_DMA_ChInitStr, spi_drv->config->dma_rx->dma_channel) == 0U)
- {
- /* Enable transaction complete interrupt event */
- DMA_ChannelEventCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, ENABLE);
+ DMA_Init(spi_drv->config->dma_rx->DMAChx, &spi_drv->dma.RX_DMA_ChInitStr);
- /* Enable the specified DMA channel */
- DMA_ChannelCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, ENABLE);
+ /* Enable transfer complete interrupt */
+ DMA_ConfigInt(spi_drv->config->dma_rx->DMAChx, DMA_INT_TXC, ENABLE);
- SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_RX, ENABLE);
- }
+ /* Enable the specified DMA channel */
+ DMA_EnableChannel(spi_drv->config->dma_rx->DMAChx, ENABLE);
+
+ SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_RX, ENABLE);
#endif
}
else
@@ -323,30 +728,24 @@ static rt_err_t SPI_DMA_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_
if (spi_drv->dma.DMA_Tx_Init == RT_TRUE)
{
#if defined(SOC_SERIES_N32H7xx)
- DMA_ChannelCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DISABLE);
-
- if (!DMA_ControllerIsEnabled(spi_drv->config->dma_tx->Instance))
+ /* Receive mode: the TX channel is armed as an empty block (this direction does not take part) */
+ if (n32_spi_dma_arm(spi_drv, RT_FALSE, RT_FALSE, RT_NULL, 0U) != RT_EOK)
{
- DMA_ControllerCmd(spi_drv->config->dma_tx->Instance, ENABLE);
+ return -RT_ERROR;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
- spi_drv->dma.TX_DMA_ChInitStr.IntEn = 0U;
- spi_drv->dma.TX_DMA_ChInitStr.SrcAddr = NULL;
- spi_drv->dma.TX_DMA_ChInitStr.BlkTfrSize = 0U;
+ DMA_EnableChannel(spi_drv->config->dma_tx->DMAChx, DISABLE);
+
+ spi_drv->dma.TX_DMA_ChInitStr.MemAddr = 0;
+ spi_drv->dma.TX_DMA_ChInitStr.BufSize = 0;
+
+ DMA_EnableChannel(spi_drv->config->dma_tx->DMAChx, ENABLE);
+ DMA_Init(spi_drv->config->dma_tx->DMAChx, &spi_drv->dma.TX_DMA_ChInitStr);
- DMA_ControllerCmd(spi_drv->config->dma_tx->Instance, ENABLE);
- if (DMA_ChannelInit(spi_drv->config->dma_tx->Instance, &spi_drv->dma.TX_DMA_ChInitStr, spi_drv->config->dma_tx->dma_channel) != 0U)
- {
- LOG_E("Master DMA Tx channel initialization failed.");
- return -RT_ERROR;
- }
#endif
}
- /* Clear Over Flag */
- SPI_I2S_ReceiveData(spi_drv->config->SPIx);
- SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG);
-
/* Enable Error Interrupt */
SPI_I2S_EnableInt(spi_drv->config->SPIx, SPI_I2S_INT_ERR, ENABLE);
@@ -359,6 +758,15 @@ static rt_err_t SPI_DMA_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_
SPI_Enable(spi_drv->config->SPIx, ENABLE);
}
+ if (m2warm_rx_defer)
+ {
+ /* Start the always-on RX engine (see the note at the flip site):
+ * the live BIDIOE clear makes the mode2 receiver free-run, so the
+ * RX DMA must already be armed (it is - above) to catch every byte
+ * from the very first clock. */
+ n32_spi_mode2_3w_set_dir(spi_drv, SPI_DIR_SINGLELINE_RX);
+ }
+
return RT_EOK;
}
@@ -371,6 +779,14 @@ static rt_err_t SPI_Transmit_Receive(struct n32_spi *spi_drv, uint8_t *pTxData,
RT_ASSERT(spi_drv != RT_NULL);
+ /* Bidirectional PIO is master-only: a slave cannot meet the per-byte
+ * service deadline by CPU polling. The master owns SCLK (slave has no
+ * flow control) and the master/slave threads on one core interleave at
+ * the ms scheduler quantum, far coarser than the byte time - see the
+ * DMA_TRANS_MIN_LEN note in spixfer for the full reasoning. In DMA-on
+ * builds a slave message never reaches this gate (slave is forced
+ * through DMA); in a no-DMA build it does and fails fast with -EIO
+ * instead of silently dropping bytes. */
if (!((spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER) && (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_FULLDUPLEX)))
{
return -RT_EIO;
@@ -550,13 +966,7 @@ static rt_err_t SPI_Transmit(struct n32_spi *spi_drv, uint8_t *pData, uint16_t S
if (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_RX ||
spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_TX)
{
- /* Disable the sFLASH_SPI */
- SPI_Enable(spi_drv->config->SPIx, DISABLE);
- /* DeInitializes the sFLASH_SPI */
- SPI_I2S_DeInit(spi_drv->config->SPIx);
- /* Set the sFLASH_SPI SendOnly*/
- spi_drv->SPI_InitStructure.DataDirection = SPI_DIR_SINGLELINE_TX;
- SPI_Init(spi_drv->config->SPIx, &spi_drv->SPI_InitStructure);
+ n32_spi_singleline_dir(spi_drv, SPI_DIR_SINGLELINE_TX);
}
if ((spi_drv->config->SPIx->CTRL2 & SPI_CTRL2_SPIEN) != SPI_CTRL2_SPIEN)
@@ -603,7 +1013,6 @@ static rt_err_t SPI_Transmit(struct n32_spi *spi_drv, uint8_t *pData, uint16_t S
pData += sizeof(uint8_t);
Transfer_Size--;
}
-
while ((Transfer_Size > 0U))
{
tickstart = rt_tick_get();
@@ -662,6 +1071,191 @@ static rt_err_t SPI_Transmit(struct n32_spi *spi_drv, uint8_t *pData, uint16_t S
return RT_EOK;
}
+/* 4-wire full-duplex MASTER receive-only (PIO): a recv-only master still has
+ * to clock the bus and must put a deterministic 0xFF fill on MOSI (the old
+ * path echoed the caller's RX buffer into the TX slot). This mirrors
+ * SPI_Transmit_Receive's per-frame discipline - per frame: wait TE, write the
+ * fill, wait TE, wait BUSY clear, wait RNE, read the response - with the TX
+ * source replaced by a constant write, so no TX buffer is touched at all
+ * (no RX-buffer echo, no dummy-buffer length bound; any PIO length is safe).
+ * The master-only FD gate mirrors SPI_Transmit_Receive (bidirectional PIO is
+ * master-only; why: see the DMA_TRANS_MIN_LEN note in spixfer). Callers:
+ * SP_Receive's full-duplex master recv-only shortcut.
+ * The pre-drain of RNE/OVER belongs to the caller (SP_Receive does it). */
+static rt_err_t SPI_Transmit_Receive_Fill(struct n32_spi *spi_drv, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint16_t Tx_Size_Const = Size;
+ uint16_t Tx_Size = Size;
+ uint16_t Rx_Size = Size;
+ uint32_t tickstart;
+
+ RT_ASSERT(spi_drv != RT_NULL);
+
+ if (!((spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER) && (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_FULLDUPLEX)))
+ {
+ return -RT_EIO;
+ }
+
+ if ((spi_drv->config->SPIx->CTRL2 & SPI_CTRL2_SPIEN) != SPI_CTRL2_SPIEN)
+ {
+ SPI_Enable(spi_drv->config->SPIx, ENABLE);
+ }
+
+ if (spi_drv->SPI_InitStructure.DataLen == SPI_DATA_SIZE_16BITS)
+ {
+ if (Tx_Size_Const == 1U)
+ {
+ /* Fill word: a recv-only master clocks a deterministic 0xFFFF */
+ spi_drv->config->SPIx->DAT = 0xFFFFU;
+ Tx_Size--;
+ }
+
+ while ((Tx_Size > 0U) || (Rx_Size > 0U))
+ {
+ if (Tx_Size > 0U)
+ {
+ tickstart = rt_tick_get();
+ /* Loop while DAT register in not emplty */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_TE_FLAG) == RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking TE flag timeout befor send data in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /* Fill word: a recv-only master clocks a deterministic 0xFFFF */
+ SPI_I2S_TransmitData(spi_drv->config->SPIx, 0xFFFFU);
+ Tx_Size--;
+ }
+
+ tickstart = rt_tick_get();
+ /* Wait for DATA send has complete */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_TE_FLAG) == RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking TE flag timeout after send data in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ tickstart = rt_tick_get();
+ /* Wait for SPI bus idle */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_BUSY_FLAG) != RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking BUSY flag timeout in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ tickstart = rt_tick_get();
+ /* Wait to receive a byte */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_RNE_FLAG) == RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking RNE flag timeout after send data in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /* Return the byte read from the SPI bus */
+ *((uint16_t *)pData) = (uint16_t)SPI_I2S_ReceiveData(spi_drv->config->SPIx);
+ pData += sizeof(uint16_t);
+
+ Rx_Size--;
+ }
+ }
+ else if (spi_drv->SPI_InitStructure.DataLen == SPI_DATA_SIZE_8BITS)
+ {
+ if (Tx_Size_Const == 1U)
+ {
+ /* Fill byte: a recv-only master clocks a deterministic 0xFF */
+ spi_drv->config->SPIx->DAT = 0xFFU;
+ Tx_Size--;
+ }
+
+ while ((Tx_Size > 0U) || (Rx_Size > 0U))
+ {
+ if (Tx_Size > 0U)
+ {
+ tickstart = rt_tick_get();
+ /* Loop while DAT register in not emplty */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_TE_FLAG) == RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking TE flag timeout befor send data in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /* Fill byte: a recv-only master clocks a deterministic 0xFF */
+ SPI_I2S_TransmitData(spi_drv->config->SPIx, 0xFFU);
+ Tx_Size--;
+ }
+
+ tickstart = rt_tick_get();
+ /* Wait for DATA send has complete */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_TE_FLAG) == RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking TE flag timeout after send data in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ tickstart = rt_tick_get();
+ /* Wait for SPI bus idle */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_BUSY_FLAG) != RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking BUSY flag timeout in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ tickstart = rt_tick_get();
+ /* Wait to receive a byte */
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_RNE_FLAG) == RESET)
+ {
+ if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ {
+ LOG_E("Checking RNE flag timeout after send data in full-duplex mode.");
+ return -RT_ETIMEOUT;
+ }
+ }
+
+ /*!< Return the byte read from the SPI bus */
+ *((uint8_t *)pData) = (uint8_t)SPI_I2S_ReceiveData(spi_drv->config->SPIx);
+ pData += sizeof(uint8_t);
+
+ Rx_Size--;
+ }
+ }
+ else
+ {
+ return -RT_EINVAL;
+ }
+
+ if (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG) != RESET)
+ {
+ volatile uint32_t reg_tmp;
+ reg_tmp = spi_drv->config->SPIx->DAT;
+ reg_tmp = spi_drv->config->SPIx->STS;
+ (void)reg_tmp;
+ }
+
+ return RT_EOK;
+}
+
static rt_err_t SP_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
@@ -687,19 +1281,13 @@ static rt_err_t SP_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_t Siz
if (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_FULLDUPLEX && spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER)
{
- return SPI_Transmit_Receive(spi_drv, pData, pData, Size, Timeout);
+ return SPI_Transmit_Receive_Fill(spi_drv, pData, Size, Timeout);
}
if (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_RX ||
spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_TX)
{
- /* Disable the sFLASH_SPI */
- SPI_Enable(spi_drv->config->SPIx, DISABLE);
- /* DeInitializes the sFLASH_SPI */
- SPI_I2S_DeInit(spi_drv->config->SPIx);
- /* Set the sFLASH_SPI SendOnly*/
- spi_drv->SPI_InitStructure.DataDirection = SPI_DIR_SINGLELINE_RX;
- SPI_Init(spi_drv->config->SPIx, &spi_drv->SPI_InitStructure);
+ n32_spi_singleline_dir(spi_drv, SPI_DIR_SINGLELINE_RX);
}
if ((spi_drv->config->SPIx->CTRL2 & SPI_CTRL2_SPIEN) != SPI_CTRL2_SPIEN)
@@ -718,6 +1306,7 @@ static rt_err_t SP_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_t Siz
if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
{
LOG_E("During receiving data, check the RNE flags for timeout.");
+ n32_spi_mode2_3w_rx_abort(spi_drv);
return -RT_ETIMEOUT;
}
}
@@ -740,6 +1329,7 @@ static rt_err_t SP_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_t Siz
if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
{
LOG_E("During receiving data, check the RNE flags for timeout.");
+ n32_spi_mode2_3w_rx_abort(spi_drv);
return -RT_ETIMEOUT;
}
}
@@ -759,21 +1349,18 @@ static rt_err_t SP_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_t Siz
spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_RX) &&
spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER)
{
- /* Disable the sFLASH_SPI */
- SPI_Enable(spi_drv->config->SPIx, DISABLE);
- }
-
- tickstart = rt_tick_get();
- /* Wait to receive a byte */
- while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_RNE_FLAG) == RESET)
- {
- volatile rt_uint32_t dummy = spi_drv->config->SPIx->DAT;
- (void)dummy;
-
- if ((((rt_tick_get() - tickstart) >= Timeout) && (Timeout != 0xFFFFFFFFU)) || (Timeout == 0U))
+ if (n32_spi_mode2_3w_master(spi_drv))
{
- LOG_E("After receiving data, check the RNE flags for timeout.");
- return -RT_ETIMEOUT;
+ /* Always-on mode2 3-wire master: dropping the engine would pull
+ * SCK low into the enabled slave (the mode2 edge problem), so
+ * instead leave RX and rest idle in TX - the bit14 set stops the
+ * free-running receiver, which otherwise clocks continuously. */
+ n32_spi_mode2_3w_set_dir(spi_drv, SPI_DIR_SINGLELINE_TX);
+ }
+ else
+ {
+ /* Disable the sFLASH_SPI */
+ SPI_Enable(spi_drv->config->SPIx, DISABLE);
}
}
@@ -805,6 +1392,12 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
RT_ASSERT(spi_drv != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
+ /* Force a clean start: DeInit resets the peripheral (clearing stale
+ * 3WIRE/BIDIR/DMA-enable/OVER state); otherwise leftovers of a previous
+ * configuration (e.g. a half-duplex 3WIRE run), such as BIDIR/TDMAEN,
+ * would pollute this one. */
+ SPI_I2S_DeInit(spi_drv->config->SPIx);
+
SPI_InitStruct(&spi_drv->SPI_InitStructure);
if (cfg->mode & RT_SPI_SLAVE)
@@ -820,6 +1413,25 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
{
/* Switch TX/RX direction dynamically according to the application */
spi_drv->SPI_InitStructure.DataDirection = SPI_DIR_SINGLELINE_RX;
+ /* NOTE: mode2 (CPOL=1, CPHA=0) corrupts data as long as the engine
+ * cold-starts per message: the SPIEN 0->1 pulls SCK low then rises
+ * into the already-enabled mode2 slave, its bit counter gains one
+ * spurious edge and the whole frame grid shifts by one bit
+ * (rx[j] = (b[j-1] & 1) << 7 | b[j] >> 1; a whole 4096B frame
+ * matches this deterministically; m0/1/3 sample after the data
+ * lands, so they are immune). Not a silicon defect: the vendor
+ * full-duplex soft-NSS demo on the same chip passes mode2 with an
+ * always-on engine. Fixed for the 3-wire master exactly like the
+ * 4-wire FD master: the engine is pre-enabled at configure (in the
+ * TX posture) and kept across message tails; the per-message
+ * direction flip toggles CTRL1's BIDIOE bit directly without
+ * dropping SPIEN (re-running SPI_Init cannot switch TX->RX warm: its
+ * CLR_MASK 0xF9F7 preserves bit14, making the flip a silent no-op;
+ * see n32_spi_mode2_3w_set_dir / n32_spi_singleline_dir). The 3-wire
+ * slave keeps its legacy cold cycle per message (its enable now
+ * happens on an SCK line clamped idle-high by the master, so no
+ * spurious edge is possible). FD mode2 uses the same always-on
+ * scheme via n32_spi_mode2_fd_master. */
}
else
{
@@ -883,6 +1495,20 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
{
return -RT_EIO;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+
+ RCC_ClocksType RCC_ClockFreq = { 0 };
+
+ RCC_GetClocksFreqValue(&RCC_ClockFreq);
+
+ if ((spi_drv->config->SPIx == SPI1) || (spi_drv->config->SPIx == SPI4) || (spi_drv->config->SPIx == SPI5) || (spi_drv->config->SPIx == SPI6))
+ {
+ SPI_CLOCK = RCC_ClockFreq.Pclk2Freq;
+ }
+ else if ((spi_drv->config->SPIx == SPI2) || (spi_drv->config->SPIx == SPI3))
+ {
+ SPI_CLOCK = RCC_ClockFreq.Pclk1Freq;
+ }
#endif
if (cfg->max_hz >= SPI_CLOCK / 2)
@@ -931,6 +1557,20 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
/* Initializes the SPIx peripheral */
SPI_Init(spi_drv->config->SPIx, &spi_drv->SPI_InitStructure);
+ /* Disable leftover DMA channels/events: SPI_Init does not clear DMA
+ * enables or TC events, so residue across configurations keeps the
+ * previous channels alive (notably on 3WIRE->FD switches). */
+#if defined(SOC_SERIES_N32H7xx)
+ if (spi_drv->config->dma_rx)
+ {
+ DMA_ChannelCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DISABLE);
+ }
+ if (spi_drv->config->dma_tx)
+ {
+ DMA_ChannelCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DISABLE);
+ }
+#endif
+
/* DMA configuration */
if (spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG)
{
@@ -939,6 +1579,9 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
#if defined(SOC_SERIES_N32H7xx)
spi_drv->dma.RX_DMA_ChInitStr.SrcTfrWidth = DMA_CH_TRANSFER_WIDTH_8;
spi_drv->dma.RX_DMA_ChInitStr.DstTfrWidth = DMA_CH_TRANSFER_WIDTH_8;
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ spi_drv->dma.RX_DMA_ChInitStr.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
+ spi_drv->dma.RX_DMA_ChInitStr.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
#endif
}
else if (cfg->data_width == 16)
@@ -946,6 +1589,9 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
#if defined(SOC_SERIES_N32H7xx)
spi_drv->dma.RX_DMA_ChInitStr.SrcTfrWidth = DMA_CH_TRANSFER_WIDTH_16;
spi_drv->dma.RX_DMA_ChInitStr.DstTfrWidth = DMA_CH_TRANSFER_WIDTH_16;
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ spi_drv->dma.RX_DMA_ChInitStr.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_HALFWORD;
+ spi_drv->dma.RX_DMA_ChInitStr.MemDataSize = DMA_MEM_DATA_WIDTH_HALFWORD;
#endif
}
@@ -961,6 +1607,9 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
#if defined(SOC_SERIES_N32H7xx)
spi_drv->dma.TX_DMA_ChInitStr.SrcTfrWidth = DMA_CH_TRANSFER_WIDTH_8;
spi_drv->dma.TX_DMA_ChInitStr.DstTfrWidth = DMA_CH_TRANSFER_WIDTH_8;
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ spi_drv->dma.TX_DMA_ChInitStr.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
+ spi_drv->dma.TX_DMA_ChInitStr.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
#endif
}
else if (cfg->data_width == 16)
@@ -968,6 +1617,9 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
#if defined(SOC_SERIES_N32H7xx)
spi_drv->dma.TX_DMA_ChInitStr.SrcTfrWidth = DMA_CH_TRANSFER_WIDTH_16;
spi_drv->dma.TX_DMA_ChInitStr.DstTfrWidth = DMA_CH_TRANSFER_WIDTH_16;
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ spi_drv->dma.TX_DMA_ChInitStr.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_HALFWORD;
+ spi_drv->dma.TX_DMA_ChInitStr.MemDataSize = DMA_MEM_DATA_WIDTH_HALFWORD;
#endif
}
@@ -983,6 +1635,28 @@ static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuratio
NVIC_EnableIRQ(spi_drv->config->irq_type);
}
+ /* Pre-enable the engine of a mode2 master (FD or 3-wire single-line,
+ * see the big note in SPI_DMA_TransmitReceive): configuration itself
+ * does the 0->1 start and clamps SCK idle-high -- the peer slave engine
+ * is off at that moment (its message tail disabled it), so the rising
+ * edge on a dead slave is harmless. Every later slave arm then happens
+ * on an idle-high SCK and the message self-starts via the warm-engine
+ * DMA level trigger (no more SPIEN 0->1). Non-mode2 configurations keep
+ * the engine off (SPI_I2S_DeInit+Init already reset it) and keep the
+ * legacy cold-start semantics per message. */
+ if (n32_spi_mode2_fd_master(spi_drv) || n32_spi_mode2_3w_master(spi_drv))
+ {
+ if (n32_spi_mode2_3w_master(spi_drv))
+ {
+ /* Pre-enable in the TX posture (bit14 set): a single-line RX
+ * engine free-runs SCK as soon as SPIEN=1 (measured: OVER=1
+ * garbage polluting the first message after the mode boundary),
+ * while TX idles quietly until DAT is written. */
+ n32_spi_mode2_3w_set_dir(spi_drv, SPI_DIR_SINGLELINE_TX);
+ }
+ SPI_Enable(spi_drv->config->SPIx, ENABLE);
+ }
+
LOG_D("%s init done", spi_drv->config->bus_name);
return RT_EOK;
}
@@ -1003,7 +1677,40 @@ static rt_err_t spi_configure(struct rt_spi_device *device,
static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
-#define DMA_TRANS_MIN_LEN 10 /* only buffer length >= DMA_TRANS_MIN_LEN will use DMA mode */
+#define DMA_TRANS_MIN_LEN 10 /* Slave messages never use CPU-polled (PIO)
+ transfer, and the PIO helpers are
+ master-only. Why:
+
+ An SPI slave has no flow control: the
+ master owns SCLK, so the slave must service
+ every byte within one byte time (at 1 MHz
+ that is 8 us - drain RNE / refill DAT before
+ the next shift) or the frame is lost.
+ Under RT-Thread the master and slave SPIs
+ are driven by two threads on one core, so
+ they can never be serviced at the same
+ time; the interleave granularity is the
+ scheduler quantum (ms), about three orders
+ of magnitude coarser than the per-byte
+ deadline -> thread polling drops bytes the
+ moment a message outlives one quantum. Only
+ DMA (hardware moves each byte the instant
+ the SPI requests it) or a per-byte
+ RNE/TE interrupt could meet the deadline;
+ this driver implements DMA and polling but
+ no per-byte IRQ path, so DMA is the only
+ viable slave path. Hence every slave
+ message (>= 1B) is forced through DMA
+ (SpiMode == SPI_MODE_SLAVE overrides this
+ length limit at every dispatch), and the
+ PIO helpers reject SLAVE with -RT_EIO. A
+ no-DMA build therefore has no working slave
+ path at all - expected by design (no partial
+ frames are produced either). Master
+ messages below this length (and any master
+ message in a no-DMA build) are CPU-polled,
+ which a master can afford because it owns
+ the clock and paces itself. */
rt_err_t state = RT_EOK;
uint32_t tickstart;
@@ -1039,10 +1746,77 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
message_length = message->length;
recv_buf = message->recv_buf;
send_buf = message->send_buf;
+ /* Whether this message is 4-wire full-duplex (send and recv both set).
+ * An FD message must disable SPI at its tail (see the message-tail
+ * note) -- both DMA and PIO ones (PIO = non-mode2 master len<10): if a
+ * PIO FD message leaves the engine ON, the next message's cold-start
+ * disable->enable produces spurious SCK edges on the already-enabled
+ * slave (a short PIO mode3 message corrupts from its first byte). The
+ * mode2 FD master with its always-on engine is the only exception (see
+ * the message-tail note). */
+ rt_bool_t fd_msg = (message->send_buf && message->recv_buf) ? RT_TRUE : RT_FALSE;
while (message_length)
{
#if defined(SOC_SERIES_N32H7xx)
+ /* One DMA arm covers up to ARM_MAX elements on the clock-driving
+ * side only; a longer message is split into consecutive arms. The
+ * engine stays on across chunk boundaries (only the message tail
+ * disables -- see the loop bottom) and chunk-2+ master arms re-arm
+ * the live engine warm (fd_chunk_cont, see SPI_DMA_TransmitReceive).
+ * The slave must NOT chunk: its DMA legs are request-driven (they
+ * only advance under the master's clock), so a single
+ * request-driven arm of up to CHAIN_MAX absorbs the master's
+ * inter-arm clock gaps without any re-arm -- a slave chunk boundary
+ * would instead race the master's continuous clock (its thread must
+ * re-arm the RX channel while the master is already clocking the
+ * next chunk; every 8192-element case loses that race at the
+ * boundary). The cap keeps each master arm under the N32H7xx
+ * per-arm transfer ceiling (~4128 items at the 20 MHz top rate, see
+ * SPI_DMA_ARM_MAX) -- a ceiling that applies to a clock-driving arm,
+ * i.e. one that keeps the engine on for its whole length while a
+ * second DMA channel competes for the bus.
+ *
+ * A single-line (3-wire) master message arms exactly one channel
+ * with data (SPI_DMA_Transmit / SPI_DMA_Receive arm the other one as
+ * an empty block), so it never meets that dual-channel arm and it
+ * gets the chain cap like the slave. Chunking a 3-wire master leg is
+ * not merely unnecessary, it CORRUPTS: every chunk-2+ arm takes the
+ * cold path (n32_spi_singleline_dir -> DISABLE + DeInit + Init for
+ * every mode but mode2), so the mid-message peripheral restart puts
+ * a spurious SCK edge onto the peer whose frame grid is already
+ * mid-message, and the 3-wire tail DISABLE block below used to fire
+ * at every chunk tail as well. Every len=8192 case with CPHA=1 then
+ * fails with the first wrong byte at index 4096, in both 3-wire
+ * directions and byte for byte identically at 1 MHz and at 100 kHz
+ * -- which rules out a re-arm timing race and pins it on the
+ * edge/phase corruption of the restart. A 4-wire message keeps the
+ * bounded arm (both channels live: FD, or the recv-only master that
+ * clocks through the 0xFF dummy TX). */
+ rt_uint32_t arm_max;
+ if (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE)
+ {
+ arm_max = SPI_DMA_CHAIN_MAX;
+ }
+ else if ((device->config.mode & RT_SPI_3WIRE) && !fd_msg)
+ {
+ arm_max = SPI_DMA_CHAIN_MAX;
+ }
+ else
+ {
+ arm_max = SPI_DMA_ARM_MAX;
+ }
+ if (message_length > arm_max)
+ {
+ send_length = arm_max;
+ message_length = message_length - arm_max;
+ }
+ else
+ {
+ send_length = message_length;
+ message_length = 0;
+ }
+#else
/* DMA uses a single block, with a maximum of 4095 per block */
if (message_length > 4095)
{
@@ -1058,6 +1832,14 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
/* calculate the start address */
already_send_length = message->length - send_length - message_length;
+ /* Mark a non-first chunk of a 4-wire full-duplex message for the
+ * arm (fd_chunk_cont): chunks keep the engine on, so this chunk's
+ * SPI_DMA_TransmitReceive arm must re-arm the live engine warm
+ * rather than drop SPIEN and re-enable -- that mid-message cycle
+ * puts CPOL=1 SCK edges onto the enabled slave and shifts its frame
+ * grid (see the warm re-arm note). Slaves never chunk below
+ * SPI_DMA_CHAIN_MAX and ignore the flag anyway. */
+ spi_drv->fd_chunk_cont = (fd_msg && (already_send_length != 0U)) ? RT_TRUE : RT_FALSE;
/* avoid null pointer problems */
if (message->send_buf)
{
@@ -1068,39 +1850,120 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
recv_buf = (rt_uint8_t *)message->recv_buf + already_send_length;
}
- rt_uint32_t *dma_aligned_buffer = RT_NULL;
- rt_uint32_t *p_txrx_buffer = RT_NULL;
+ rt_uint32_t *dma_aligned_buffer = RT_NULL; /* TX staging buffer (copy path only) */
+ rt_uint32_t *dma_rx_staging = RT_NULL; /* RX staging buffer (copy path only) */
+ rt_uint32_t *p_tx_buffer = RT_NULL; /* real source that TX DMA reads */
+ rt_uint32_t *p_rx_buffer = RT_NULL; /* real destination RX DMA writes to */
+ /* Which legs of this chunk the DMA serves: the PIO length gate plus
+ * two exceptions - a slave never PIO-polls, and neither does a
+ * 3-wire master receive (see the dispatch note for the measured
+ * reason). The 3-wire exception is receive-only by construction
+ * (send_buf == RT_NULL): a bidirectional 3-wire message below the
+ * gate is served by the PIO helper, which writes the caller's
+ * buffers directly, so staging such a message would only copy an
+ * uninitialized buffer back over the real data.
+ * Every site below that stages, dispatches, synchronizes or tails a
+ * leg reads these - they must all agree. If they disagree - a
+ * 3-wire receive dispatch on the DMA gate whose completion wait and
+ * tail still use the PIO gate - the receive returns before its DMA
+ * has run: zero bytes received, instant return, at every rate. */
+ rt_bool_t tx_leg_dma = ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) != 0U) &&
+ (send_buf != RT_NULL) &&
+ ((send_length >= DMA_TRANS_MIN_LEN) ||
+ (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE));
+ rt_bool_t rx_leg_dma = ((spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) != 0U) &&
+ (recv_buf != RT_NULL) &&
+ ((send_length >= DMA_TRANS_MIN_LEN) ||
+ (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE) ||
+ ((send_buf == RT_NULL) && ((device->config.mode & RT_SPI_3WIRE) != 0)));
+ rt_bool_t msg_dma = tx_leg_dma || rx_leg_dma;
+ /* Loop work vars: declared above the error gotos so a chunk-exit
+ * jump never bypasses an initialization (armcc #546-D) */
+ rt_tick_t busy_to;
+ rt_bool_t busy_to_ok;
+ rt_bool_t dma_leg;
- if ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) && (send_length >= DMA_TRANS_MIN_LEN))
+ /* TX source preparation: allocate/use directly only when data is
+ * actually being sent. The direct path (p_tx_buffer == send_buf) is
+ * kept apart from the copy path so full-duplex DMA never shares one
+ * buffer between TX and RX (an RX echo would overwrite the TX source
+ * and recv_buf would never see data - fixed). */
+ if (tx_leg_dma)
{
#if defined(SOC_SERIES_N32H7xx)
- if (RT_IS_ALIGN((rt_uint32_t)send_buf, 32) && send_buf != RT_NULL) /* aligned with 32 bytes? */
+ /* send_length counts elements: buffer/copy/cache sizes must be
+ * converted to bytes by the data width */
+ rt_uint32_t send_bytes = send_length * (spi_drv->cfg->data_width / 8u);
+ if (RT_IS_ALIGN((rt_uint32_t)send_buf, 32)) /* aligned with 32 bytes? */
{
- p_txrx_buffer = (rt_uint32_t *)send_buf; /* send_buf aligns with 32 bytes, no more operations */
+ p_tx_buffer = (rt_uint32_t *)send_buf; /* send_buf aligns with 32 bytes, DMA reads it directly */
}
else
{
/* send_buf doesn't align with 32 bytes, so creat a cache buffer with 32 bytes aligned */
- dma_aligned_buffer = (rt_uint32_t *)rt_malloc_align(send_length, 32);
- rt_memcpy(dma_aligned_buffer, send_buf, send_length);
- p_txrx_buffer = dma_aligned_buffer;
+ dma_aligned_buffer = (rt_uint32_t *)rt_malloc_align(send_bytes, 32);
+ if (dma_aligned_buffer == RT_NULL)
+ {
+ LOG_E("malloc TX align buf failed, len=%u", send_length);
+ state = -RT_ENOMEM;
+ goto spi_staging_free;
+ }
+ rt_memcpy(dma_aligned_buffer, send_buf, send_bytes);
+ p_tx_buffer = dma_aligned_buffer;
}
if ((SCB->CCR & (uint32_t)SCB_CCR_DC_Msk) != 0U)
{
- rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, dma_aligned_buffer, send_length);
+ /* flush the REAL DMA source: direct path must flush send_buf too */
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, p_tx_buffer, send_bytes);
}
#else
if (RT_IS_ALIGN((rt_uint32_t)send_buf, 4) && send_buf != RT_NULL) /* aligned with 4 bytes? */
{
- p_txrx_buffer = (rt_uint32_t *)send_buf; /* send_buf aligns with 4 bytes, no more operations */
+ p_tx_buffer = (rt_uint32_t *)send_buf; /* send_buf aligns with 4 bytes, no more operations */
}
else
{
/* send_buf doesn't align with 4 bytes, so creat a cache buffer with 4 bytes aligned */
dma_aligned_buffer = (rt_uint32_t *)rt_malloc(send_length); /* aligned with RT_ALIGN_SIZE (8 bytes by default) */
+ if (dma_aligned_buffer == RT_NULL)
+ {
+ LOG_E("SPI DMA TX buffer malloc failed!");
+ state = -RT_ENOMEM;
+ goto spi_staging_free;
+ }
rt_memcpy(dma_aligned_buffer, send_buf, send_length);
- p_txrx_buffer = dma_aligned_buffer;
+ p_tx_buffer = dma_aligned_buffer;
+ }
+#endif
+ }
+
+ /* RX destination preparation: allocate/use directly only when data
+ * is actually being received. The direct path (p_rx_buffer ==
+ * recv_buf) is kept apart from the staging path; staging is always
+ * copied back on completion. */
+ if (rx_leg_dma)
+ {
+#if defined(SOC_SERIES_N32H7xx)
+ /* send_length counts elements: the RX staging buffer is likewise
+ * allocated in bytes (x2 for 16-bit data) */
+ rt_uint32_t recv_bytes = send_length * (spi_drv->cfg->data_width / 8u);
+ if (RT_IS_ALIGN((rt_uint32_t)recv_buf, 32))
+ {
+ p_rx_buffer = (rt_uint32_t *)recv_buf; /* DMA writes straight into caller's buffer */
+ }
+ else
+ {
+ dma_rx_staging = (rt_uint32_t *)rt_malloc_align(recv_bytes, 32);
+ if (dma_rx_staging == RT_NULL)
+ {
+ LOG_E("malloc RX staging buf failed, len=%u", send_length);
+ state = -RT_ENOMEM;
+ goto spi_staging_free;
+ }
+ p_rx_buffer = dma_rx_staging;
}
+#else
+ p_rx_buffer = (rt_uint32_t *)recv_buf;
#endif
}
@@ -1140,19 +2003,28 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
/* start once data exchange in DMA mode */
if (message->send_buf && message->recv_buf)
{
- if ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) && (spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) && (send_length >= DMA_TRANS_MIN_LEN))
+ if ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) && (spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) && ((send_length >= DMA_TRANS_MIN_LEN || spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE)))
{
- state = SPI_DMA_TransmitReceive(spi_drv, (uint8_t *)p_txrx_buffer, (uint8_t *)p_txrx_buffer, send_length);
+ /* TX/RX buffer separation: even when send_buf and recv_buf
+ * differ, DMA TX/RX must never share one source */
+ if ((p_tx_buffer == RT_NULL) || (p_rx_buffer == RT_NULL))
+ {
+ LOG_E("full-duplex DMA: TX %p RX %p buf missing (from %p,%p len=%u)",
+ p_tx_buffer, p_rx_buffer, send_buf, recv_buf, send_length);
+ state = -RT_ERROR;
+ goto spi_staging_free;
+ }
+ state = SPI_DMA_TransmitReceive(spi_drv, (uint8_t *)p_tx_buffer, (uint8_t *)p_rx_buffer, send_length);
}
- else if ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) && (send_length >= DMA_TRANS_MIN_LEN))
+ else if ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) && ((send_length >= DMA_TRANS_MIN_LEN || spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE)))
{
- state = SPI_DMA_Transmit(spi_drv, (uint8_t *)p_txrx_buffer, send_length);
+ state = SPI_DMA_Transmit(spi_drv, (uint8_t *)p_tx_buffer, send_length);
}
- else if ((spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) && (send_length >= DMA_TRANS_MIN_LEN))
+ else if ((spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) && ((send_length >= DMA_TRANS_MIN_LEN || spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE)))
{
state = -RT_ERROR;
LOG_E("It shoule be enabled both BSP_SPIx_TX_USING_DMA and BSP_SPIx_TX_USING_DMA flag, if wants to use SPI DMA Rx singly.");
- break;
+ goto spi_staging_free;
}
else
{
@@ -1161,27 +2033,45 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
}
else if (message->send_buf)
{
- if ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) && (send_length >= DMA_TRANS_MIN_LEN))
+ if ((spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) && ((send_length >= DMA_TRANS_MIN_LEN || spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_SLAVE)))
{
- state = SPI_DMA_Transmit(spi_drv, (uint8_t *)p_txrx_buffer, send_length);
+ if (p_tx_buffer == RT_NULL)
+ {
+ LOG_E("SPI DMA TX: source buf missing");
+ state = -RT_ERROR;
+ goto spi_staging_free;
+ }
+ state = SPI_DMA_Transmit(spi_drv, (uint8_t *)p_tx_buffer, send_length);
}
else
{
state = SPI_Transmit(spi_drv, (uint8_t *)send_buf, send_length, 1000);
}
-
- if (message->cs_release && (device->config.mode & RT_SPI_3WIRE))
- {
- /* release the CS by disable SPI when using 3 wires SPI */
- SPI_Enable(spi_drv->config->SPIx, DISABLE);
- }
}
else if (message->recv_buf)
{
- rt_memset((uint8_t *)recv_buf, 0xff, send_length);
- if ((spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) && (send_length >= DMA_TRANS_MIN_LEN))
+ /* rx_leg_dma: a 3-wire master receive must never be PIO-polled.
+ * The 3-wire master receiver free-runs SCLK the moment the
+ * direction flips to RX, so SP_Receive has no deadline it can
+ * meet by construction - it occasionally reads DAT while a byte
+ * is still shifting in and stores the partial shift register.
+ * The stored value is always the expected byte shifted right by
+ * k bits with the idle-high tail filled (0xc6 read back as
+ * 0x01/0x03/0x07/0x0d/0x19, 0x31 as 0x01) - a deterministic per
+ * (rate, mode, len) beat rather than a rare glitch, so retrying
+ * does not help. The DMA path never showed it at any rate up to
+ * 16384 elements. 4-wire messages (incl. the
+ * recv-only 4-wire master that clocks via SPI_Transmit_Receive_
+ * Fill) keep the PIO gate unchanged. */
+ if (rx_leg_dma)
{
- state = SPI_DMA_Receive(spi_drv, (uint8_t *)p_txrx_buffer, send_length);
+ if (p_rx_buffer == RT_NULL)
+ {
+ LOG_E("SPI DMA RX: dest buf missing");
+ state = -RT_ERROR;
+ goto spi_staging_free;
+ }
+ state = SPI_DMA_Receive(spi_drv, (uint8_t *)p_rx_buffer, send_length);
}
else
{
@@ -1204,7 +2094,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
{
LOG_E("SPI transfer error: %d", state);
message->length = 0;
- break;
+ goto spi_staging_free;
}
else
{
@@ -1214,45 +2104,204 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
/* For simplicity reasons, this example is just waiting till the end of the
transfer, but application may perform other tasks while transfer operation
is ongoing. */
- if ((spi_drv->spi_dma_flag & (SPI_USING_TX_DMA_FLAG | SPI_USING_RX_DMA_FLAG)) && (send_length >= DMA_TRANS_MIN_LEN))
+ if (msg_dma)
{
/* blocking the thread,and the other tasks can run */
if (rt_completion_wait(&spi_drv->cpt, 1000) != RT_EOK)
{
state = -RT_ERROR;
LOG_E("wait for DMA interrupt overtime!");
- break;
+ /* Always-on mode2 3-wire master: a timed-out RX leg would
+ * otherwise keep its free-running engine clocking into the
+ * next message - stop it (no-op for every other role). */
+ n32_spi_mode2_3w_rx_abort(spi_drv);
+ goto spi_staging_free;
+ }
+ }
+
+ /* The DMA leg (the if below) waits for BUSY with "benign timeout"
+ * semantics; the non-DMA (PIO) leg keeps its original 1000-tick
+ * ceiling and still errors on expiry:
+ * a) The DMA-send leg first waits for TE=1: DMA TC fires on the
+ * last DAT write, right after the second-to-last load, when the
+ * last byte is still in DAT waiting for the next frame-boundary
+ * load. If BUSY=0 were waited on directly, polling on a slow
+ * clock (<= 1MHz) can catch the momentary BUSY drop before the
+ * last byte is loaded (BUSY idles between two adjacent bytes)
+ * and move ahead to the 3-wire DISABLE -> the last byte never
+ * shifts out -> the peer receives an empty tail byte (measured:
+ * rx[len-1] always wrong). Follow the manual: wait for TE=1
+ * first (the last byte has left DAT into the shift register).
+ * b) Then wait for BUSY=0, but cap it with a short timeout derived
+ * from the configured bit clock (at 128 bit-times there is >= 8x
+ * headroom over the real clock: prescaler rounding makes the
+ * actual baud rate > max_hz/2). On a single-wire slave transfer
+ * BUSY may never fall after all data has shifted out/in (DMA TC
+ * proves the last byte arrived: CPHA=1 (mode1/3) slave sending,
+ * CPOL=1+CPHA=0 (mode2) slave receiving -- the engine waits for a
+ * frame-boundary clock that never comes; measured: all wire data
+ * correct, peer compare passed). Timeout expiry is treated as
+ * end-of-transfer and the tail finishes as a success -- treating
+ * it as an error would skip the 3-wire DISABLE and leave SPIEN=1
+ * stuck.
+ * In mode0 BUSY falls normally and the flag exits immediately;
+ * this timeout never applies. */
+ busy_to = 1000U;
+ busy_to_ok = RT_FALSE; /* DMA-leg timeout expiry = benign end */
+ dma_leg = msg_dma;
+ if (dma_leg)
+ {
+ busy_to_ok = RT_TRUE;
+ if (message->send_buf && (spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG))
+ {
+ tickstart = rt_tick_get();
+ while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_TE_FLAG) == RESET)
+ {
+ if ((rt_tick_get() - tickstart) > 1000U)
+ {
+ state = -RT_ERROR;
+ LOG_E("Wait SPI TE Flag Timeout!");
+ break;
+ }
+ }
+ }
+ if (state == RT_EOK)
+ {
+ rt_uint32_t hz = spi_drv->cfg->max_hz;
+ if (hz != 0U)
+ {
+ rt_uint32_t ms = (128000U + hz - 1U) / hz; /* 128 bit-times -> ms */
+ busy_to = (rt_tick_t)ms * RT_TICK_PER_SECOND / 1000U;
+ if (busy_to < 1U)
+ {
+ busy_to = 1U;
+ }
+ }
}
}
tickstart = rt_tick_get();
while (SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_BUSY_FLAG) != RESET)
{
- if ((rt_tick_get() - tickstart) > 1000U)
+ if ((rt_tick_get() - tickstart) > busy_to)
{
- state = -RT_ERROR;
- LOG_E("Wait SPI BUSY Flag Timeout!");
+ if (!busy_to_ok)
+ {
+ state = -RT_ERROR;
+ LOG_E("Wait SPI BUSY Flag Timeout!");
+ }
break;
}
}
- if (dma_aligned_buffer != RT_NULL) /* re-aligned, so need to copy the data to recv_buf */
+ /* 3-wire has no CS line: disable SPI once the message (chunk) really
+ * ends to release the bus. DISABLE must come after the DMA completes
+ * and BUSY clears: disabling right after the DMA is armed (as the
+ * old send-only branch did) cuts the clock that drives the slave TX
+ * DMA -> the DMA never completes -> 3-wire leg BA (slave send-only)
+ * wait DMA interrupt overtime. The mode2 3-wire master engine stays
+ * on (pre-enabled at configure, never disabled between messages):
+ * dropping it would pull the idle-high SCK low and the next slave
+ * arm (which precedes the master clock) would land on a low line ->
+ * the mode2 spurious-edge problem returns.
+ *
+ * Message tail only (message_length == 0), exactly like the FD block
+ * below: a 3-wire master message is armed as one single-line leg
+ * (CHAIN_MAX, see the arm_max note) so an intermediate chunk exists
+ * only past 65520 elements, but should it ever happen, disabling
+ * mid-message would put a spurious SCK edge on the peer same as the
+ * FD case. The last chunk still disables -- the 3-wire mode3 skew
+ * fix (single-chunk messages included) depends on that. */
+ if ((device->config.mode & RT_SPI_3WIRE) && message->cs_release && (state == RT_EOK) &&
+ (message_length == 0U))
{
- if (recv_buf != RT_NULL)
+ if (!n32_spi_mode2_3w_master(spi_drv))
{
+ SPI_Enable(spi_drv->config->SPIx, DISABLE);
+ }
+ }
+
+ /* RX data out: the staging path copies back unconditionally; the
+ * direct path (dma_rx_staging == NULL) only needs a cache flush */
+ if ((recv_buf != RT_NULL) && (p_rx_buffer != RT_NULL))
+ {
#if defined(SOC_SERIES_N32H7xx)
- if ((SCB->CCR & (uint32_t)SCB_CCR_DC_Msk) != 0U)
- {
- rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, p_txrx_buffer, send_length);
- }
+ /* RX buffer/cache sizes are in bytes (16-bit elements x2) */
+ rt_uint32_t recv_bytes = send_length * (spi_drv->cfg->data_width / 8u);
+ if ((SCB->CCR & (uint32_t)SCB_CCR_DC_Msk) != 0U)
+ {
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, p_rx_buffer, recv_bytes);
+ }
#endif /* SOC_SERIES_N32H7xx */
- rt_memcpy(recv_buf, p_txrx_buffer, send_length);
+ if (dma_rx_staging != RT_NULL)
+ {
+ rt_memcpy(recv_buf, p_rx_buffer, send_length * (spi_drv->cfg->data_width / 8u));
}
+ }
+
+ /* Release the staging buffers (on success or failure). Chunk-exit
+ * error paths jump here via goto: a failed transfer must never
+ * leak the staging buffers it already allocated. */
+ spi_staging_free:
#if defined(SOC_SERIES_N32H7xx)
+ if (dma_aligned_buffer != RT_NULL)
+ {
rt_free_align(dma_aligned_buffer);
+ }
+ if (dma_rx_staging != RT_NULL)
+ {
+ rt_free_align(dma_rx_staging);
+ }
#else
+ if (dma_aligned_buffer != RT_NULL)
+ {
rt_free(dma_aligned_buffer);
+ }
#endif /* SOC_SERIES_N32H7xx */
+
+ if (state != RT_EOK)
+ {
+ /* Error: leave the chunk loop. Restore the between-message
+ * engine posture (off for every role except the always-on
+ * mode2 FD/3W masters) so the next message cold-starts exactly
+ * as after a clean tail -- a mid-message error can leave the
+ * engine enabled, and the next arm's cold cycle relies on
+ * finding it off. */
+ if (!n32_spi_mode2_fd_master(spi_drv) && !n32_spi_mode2_3w_master(spi_drv))
+ {
+ SPI_Enable(spi_drv->config->SPIx, DISABLE);
+ }
+ break; /* error: leave the chunk loop (tail returns -RT_ERROR) */
+ }
+
+ /* Disable SPI once an FD (4-wire) message really ends (DMA and PIO
+ * alike) -- same semantics as the 3-wire case above (wait for DMA
+ * completion + BUSY clear). A message chunked at SPI_DMA_ARM_MAX
+ * keeps the engine ON across chunk boundaries: only the final chunk
+ * (message_length == 0) disables here, and chunk-2+ arms re-arm the
+ * live engine through the warm path (see SPI_DMA_TransmitReceive /
+ * fd_chunk_cont). Dropping SPIEN at an intermediate chunk tail
+ * would put the CPOL=1 idle-high SCK falling edge onto the slave,
+ * which is mid-arm (single request-driven arm per message): the
+ * slave counts the edge and its TX reply shifts -- measured as
+ * chunk-2 corruption from byte 4096 of an 8192-element mode3
+ * message at 20 MHz (mode0/1 are idle-low and have no edge; the
+ * mode2 master never disables). For a single-chunk message this
+ * block runs where it always did, at the message tail -- the mode3
+ * skew fix depends on disabling SPI at the message tail. */
+ if (fd_msg && message->cs_release && (message_length == 0U))
+ {
+ /* The mode2 FD master engine stays on (pre-enabled at
+ * configure, never disabled between messages): disabling at the
+ * tail would lose the idle-high SCK, and the next message's
+ * slave arm (which precedes the master clock) would land on a
+ * low line -> the mode2 spurious-edge problem returns (see the
+ * SPI_DMA_TransmitReceive note). All other modes keep the
+ * tail-disable semantics. */
+ if (!n32_spi_mode2_fd_master(spi_drv))
+ {
+ SPI_Enable(spi_drv->config->SPIx, DISABLE);
+ }
}
}
@@ -1285,6 +2334,17 @@ static int rt_hw_spi_bus_init(void)
{
rt_err_t result;
+#if defined(SOC_SERIES_N32H7xx)
+ /* Fill the FD master recv-only TX dummy once: it is read-only afterwards
+ * (every LLI node re-reads from its base), so a single init-time fill
+ * and cache flush covers all buses and all subsequent messages. */
+ rt_memset(spi_fd_rxonly_dummy, 0xFF, sizeof(spi_fd_rxonly_dummy));
+ if ((SCB->CCR & SCB_CCR_DC_Msk) != 0U)
+ {
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, spi_fd_rxonly_dummy, sizeof(spi_fd_rxonly_dummy));
+ }
+#endif
+
for (rt_size_t i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
{
spi_bus_obj[i].config = &spi_config[i];
@@ -1342,6 +2402,36 @@ static int rt_hw_spi_bus_init(void)
LOG_E("SPI RX DMA channel initialization failed!");
return -RT_ERROR;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Configure the SPI RX DMA for Transmission process */
+ /* Enable DMA clock */
+ RCC_EnableAHBPeriphClk(spi_bus_obj[i].config->dma_rx->dma_rcc, ENABLE);
+
+ /* Receive DMA Config */
+ DMA_StructInit(&spi_bus_obj[i].dma.RX_DMA_ChInitStr);
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.PeriphAddr = (uint32_t)&spi_bus_obj[i].config->SPIx->DAT;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.MemAddr = 0;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.Direction = DMA_DIR_PERIPH_SRC;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.BufSize = 0;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.PeriphInc = DMA_PERIPH_INC_DISABLE;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.MemoryInc = DMA_MEM_INC_ENABLE;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.CircularMode = DMA_MODE_NORMAL;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.Priority = DMA_PRIORITY_HIGH;
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.Mem2Mem = DMA_M2M_DISABLE;
+#if defined(SOC_SERIES_N32H49x)
+ spi_bus_obj[i].dma.RX_DMA_ChInitStr.BurstCmd = DMA_BURST_DISABLE;
+#endif
+ /* Initialize the specified DMA channel and Whether the specified channel was successfully initialized */
+ DMA_Init(spi_bus_obj[i].config->dma_rx->DMAChx, &spi_bus_obj[i].dma.RX_DMA_ChInitStr);
+
+ /* Enable transfer complete interrupt */
+ DMA_ConfigInt(spi_bus_obj[i].config->dma_rx->DMAChx, DMA_INT_TXC, ENABLE);
+
+ spi_bus_obj[i].dma.DMA_Rx_Init = RT_TRUE;
+
+
#endif
}
@@ -1396,6 +2486,36 @@ static int rt_hw_spi_bus_init(void)
LOG_E("SPI TX DMA channel initialization failed!");
return -RT_ERROR;
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Configure the SPI TX DMA for Transmission process */
+ /* Enable DMA clock */
+ RCC_EnableAHBPeriphClk(spi_bus_obj[i].config->dma_tx->dma_rcc, ENABLE);
+
+ /* SPI_MASTER_Tx_DMA_Channel DMA1 Channel1 configuration ---------------------------------------------*/
+ DMA_StructInit(&spi_bus_obj[i].dma.TX_DMA_ChInitStr);
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.PeriphAddr = (uint32_t)&spi_bus_obj[i].config->SPIx->DAT;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.MemAddr = 0;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.Direction = DMA_DIR_PERIPH_DST;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.BufSize = 0;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.PeriphInc = DMA_PERIPH_INC_DISABLE;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.MemoryInc = DMA_MEM_INC_ENABLE;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.CircularMode = DMA_MODE_NORMAL;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.Priority = DMA_PRIORITY_HIGH;
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.Mem2Mem = DMA_M2M_DISABLE;
+#if defined(SOC_SERIES_N32H49x)
+ spi_bus_obj[i].dma.TX_DMA_ChInitStr.BurstCmd = DMA_BURST_DISABLE;
+#endif
+ /* Initialize the specified DMA channel and Whether the specified channel was successfully initialized */
+ DMA_Init(spi_bus_obj[i].config->dma_tx->DMAChx, &spi_bus_obj[i].dma.TX_DMA_ChInitStr);
+
+ /* Enable transfer complete interrupt */
+ DMA_ConfigInt(spi_bus_obj[i].config->dma_tx->DMAChx, DMA_INT_TXC, ENABLE);
+
+ spi_bus_obj[i].dma.DMA_Tx_Init = RT_TRUE;
+
+
#endif
}
@@ -1459,6 +2579,8 @@ static void spi_isr(struct n32_spi *spi_drv)
{
#if defined(SOC_SERIES_N32H7xx)
DMA_ChannelEventCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, DISABLE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ DMA_ConfigInt(spi_drv->config->dma_tx->DMAChx, DMA_INT_TXC, DISABLE);
#endif
}
@@ -1466,6 +2588,8 @@ static void spi_isr(struct n32_spi *spi_drv)
{
#if defined(SOC_SERIES_N32H7xx)
DMA_ChannelEventCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, DISABLE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ DMA_ConfigInt(spi_drv->config->dma_rx->DMAChx, DMA_INT_TXC, DISABLE);
#endif
}
@@ -1490,6 +2614,78 @@ static void spi_rx_dma_isr(struct n32_spi *spi_drv)
{
if (DMA_GetChannelIntTfrStatus(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel) == SET)
{
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ DMA_Module *dma_module = (DMA_Module *)((uint32_t)spi_drv->config->dma_rx->DMAChx < DMA2_BASE ? DMA1 : DMA2);
+ uint32_t dma_int_tc = 0;
+
+ /* Obtain the corresponding interrupt flag macro based on the channel */
+ if (spi_drv->config->dma_rx->DMAChx == DMA1_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA1_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA1_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA1_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA1_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA1_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA1_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA1_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (spi_drv->config->dma_rx->DMAChx == DMA2_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+
+ if (dma_int_tc != 0 && DMA_GetIntStatus(dma_int_tc, dma_module) == SET)
+ {
#endif
if (spi_drv->Direct == SPI_Tx_Rx)
{
@@ -1498,10 +2694,22 @@ static void spi_rx_dma_isr(struct n32_spi *spi_drv)
#if defined(SOC_SERIES_N32H7xx)
DMA_ChannelEventCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, DISABLE);
DMA_ChannelEventCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, DISABLE);
+ /* Disable the RX/TX DMA channels: avoid leftover moves that
+ * RDMAEN would re-trigger after the slave completes */
+ DMA_ChannelCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DISABLE);
+ DMA_ChannelCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DISABLE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ DMA_ConfigInt(spi_drv->config->dma_rx->DMAChx, DMA_INT_TXC, DISABLE);
+ DMA_ConfigInt(spi_drv->config->dma_tx->DMAChx, DMA_INT_TXC, DISABLE);
#endif
- if (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER && spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_FULLDUPLEX)
+ if (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_FULLDUPLEX)
{
+ /* After a full-duplex DMA completes, both master and
+ * slave must clear the SPI DMA enables: if RDMAEN/TDMAEN
+ * linger on the slave, a live DMA request would move the
+ * stale DAT byte of the next case -> the slave's first
+ * byte misaligns (rx[0] old value + right shift). */
SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_TX | SPI_I2S_DMA_RX, DISABLE);
}
@@ -1516,7 +2724,20 @@ static void spi_rx_dma_isr(struct n32_spi *spi_drv)
if (spi_drv->SPI_InitStructure.SpiMode == SPI_MODE_MASTER && (spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_SINGLELINE_RX ||
spi_drv->SPI_InitStructure.DataDirection == SPI_DIR_DOUBLELINE_RONLY))
{
- SPI_Enable(spi_drv->config->SPIx, DISABLE);
+ if (n32_spi_mode2_3w_master(spi_drv))
+ {
+ /* Always-on mode2 3-wire master: the RX DMA is done,
+ * but the receiver free-runs until the direction
+ * leaves RX - flip back to TX (bit14 set, engine
+ * stays on; dropping SPIEN would pull SCK low into
+ * the enabled slave) so the next message starts from
+ * a quiet idle-high line. */
+ n32_spi_mode2_3w_set_dir(spi_drv, SPI_DIR_SINGLELINE_TX);
+ }
+ else
+ {
+ SPI_Enable(spi_drv->config->SPIx, DISABLE);
+ }
}
SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_RX, DISABLE);
@@ -1525,6 +2746,8 @@ static void spi_rx_dma_isr(struct n32_spi *spi_drv)
#if defined(SOC_SERIES_N32H7xx)
DMA_ChannelEventCmd(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, DISABLE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ DMA_ConfigInt(spi_drv->config->dma_rx->DMAChx, DMA_INT_TXC, DISABLE);
#endif
SPI_I2S_ReceiveData(spi_drv->config->SPIx);
@@ -1537,8 +2760,11 @@ static void spi_rx_dma_isr(struct n32_spi *spi_drv)
#if defined(SOC_SERIES_N32H7xx)
/* Clear interrupt event status */
DMA_ClearChannelEventStatus(spi_drv->config->dma_rx->Instance, spi_drv->config->dma_rx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE);
-#endif
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Clear interrupt event status */
+ DMA_ClrIntPendingBit(dma_int_tc, dma_module);
+#endif
}
}
#endif
@@ -1550,12 +2776,89 @@ static void spi_tx_dma_isr(struct n32_spi *spi_drv)
{
if (DMA_GetChannelIntTfrStatus(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel) == SET)
{
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ DMA_Module *dma_module = (DMA_Module *)((uint32_t)spi_drv->config->dma_tx->DMAChx < DMA2_BASE ? DMA1 : DMA2);
+ uint32_t dma_int_tc = 0;
+
+ if (spi_drv->config->dma_tx->DMAChx == DMA1_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA1_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA1_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA1_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA1_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA1_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA1_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA1_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH1)
+ {
+ dma_int_tc = DMA_INT_TXC1;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH2)
+ {
+ dma_int_tc = DMA_INT_TXC2;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH3)
+ {
+ dma_int_tc = DMA_INT_TXC3;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH4)
+ {
+ dma_int_tc = DMA_INT_TXC4;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH5)
+ {
+ dma_int_tc = DMA_INT_TXC5;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH6)
+ {
+ dma_int_tc = DMA_INT_TXC6;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH7)
+ {
+ dma_int_tc = DMA_INT_TXC7;
+ }
+ else if (spi_drv->config->dma_tx->DMAChx == DMA2_CH8)
+ {
+ dma_int_tc = DMA_INT_TXC8;
+ }
+
+ if (dma_int_tc != 0 && DMA_GetIntStatus(dma_int_tc, dma_module) == SET)
+ {
#endif
if (spi_drv->Direct == SPI_Tx)
{
+#if defined(SOC_SERIES_N32H7xx)
DMA_ChannelEventCmd(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE, DISABLE);
SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_TX, DISABLE);
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ SPI_I2S_EnableInt(spi_drv->config->SPIx, SPI_I2S_INT_ERR, DISABLE);
+
+ SPI_I2S_EnableDma(spi_drv->config->SPIx, SPI_I2S_DMA_TX, DISABLE);
+#endif
SPI_I2S_ReceiveData(spi_drv->config->SPIx);
SPI_I2S_GetStatus(spi_drv->config->SPIx, SPI_I2S_OVER_FLAG);
@@ -1564,10 +2867,16 @@ static void spi_tx_dma_isr(struct n32_spi *spi_drv)
rt_completion_done(&spi_drv->cpt);
}
+#if defined(SOC_SERIES_N32H7xx)
/* Clear interrupt event status */
DMA_ClearChannelEventStatus(spi_drv->config->dma_tx->Instance, spi_drv->config->dma_tx->dma_channel, DMA_CH_EVENT_TRANSFER_COMPLETE);
}
}
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ /* Clear interrupt event status */
+ DMA_ClrIntPendingBit(dma_int_tc, dma_module);
+ }
+#endif
}
#endif
@@ -1610,7 +2919,11 @@ void SPI1_TX_DMA_IRQHandler(void)
#if defined(BSP_SPI2_TX_USING_DMA) || defined(BSP_SPI2_RX_USING_DMA)
+#if defined(SOC_SERIES_N32H7xx)
void SPI2_IRQHandler(void)
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+void SPI2_I2S2_IRQHandler(void)
+#endif
{
/* enter interrupt */
rt_interrupt_enter();
@@ -1648,7 +2961,11 @@ void SPI2_TX_DMA_IRQHandler(void)
#if defined(BSP_SPI3_TX_USING_DMA) || defined(BSP_SPI3_RX_USING_DMA)
+#if defined(SOC_SERIES_N32H7xx)
void SPI3_IRQHandler(void)
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+void SPI3_I2S3_IRQHandler(void)
+#endif
{
/* enter interrupt */
rt_interrupt_enter();
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.h
index 073831568b..c018bc76c0 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_spi.h
@@ -17,6 +17,7 @@
#include <drv_common.h>
#include "drv_dma.h"
#include <ipc/completion.h>
+#include "drv_config.h"
#ifdef __cplusplus
extern "C" {
@@ -47,6 +48,20 @@ struct n32_spi_device
#define SPI_USING_RX_DMA_FLAG (1 << 0)
#define SPI_USING_TX_DMA_FLAG (1 << 1)
+/* Max bytes of a single DMA block (12-bit BlkTfrSize) */
+#define SPI_DMA_BLOCK_MAX (4095U)
+/* Number of LLI chain nodes per DMA leg (sizes lli_tx/lli_rx) */
+#define SPI_DMA_CHAIN_NODES (16U)
+#define SPI_DMA_CHAIN_MAX (SPI_DMA_BLOCK_MAX * SPI_DMA_CHAIN_NODES)
+/* Max elements of a single DMA arm: spixfer chunks every message at this
+ * size. A N32H7xx DMA arm stalls past ~4128 items at the 20MHz top rate
+ * (silicon-level: the LLI chain is verified intact and frozen mid-node;
+ * sharp 4128 PASS / 4136 FAIL boundary, and the ceiling scales with the
+ * bit clock so a 4096-item arm passes at every rate). 4096 items = 2 LLI
+ * nodes (4095+1) -- the same per-arm shape as a standalone 4096-element
+ * message. */
+#define SPI_DMA_ARM_MAX (4096U)
+
typedef enum
{
SPI_Tx_Rx = 0U,
@@ -64,6 +79,7 @@ struct n32_spi
SPI_InitType SPI_InitStructure;
SPI_Work_Direct_t Direct;
+#if defined(SOC_SERIES_N32H7xx)
struct
{
rt_bool_t DMA_Tx_Init;
@@ -71,9 +87,40 @@ struct n32_spi
rt_bool_t DMA_Rx_Init;
DMA_ChInitType RX_DMA_ChInitStr;
+
+ /* LLI node arrays: seamless single-task DMA for > SPI_DMA_BLOCK_MAX */
+ DMA_LinkListItemType lli_rx[SPI_DMA_CHAIN_NODES];
+ DMA_LinkListItemType lli_tx[SPI_DMA_CHAIN_NODES];
} dma;
+#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
+ struct
+ {
+ rt_bool_t DMA_Tx_Init;
+ DMA_InitType TX_DMA_ChInitStr;
+
+ rt_bool_t DMA_Rx_Init;
+ DMA_InitType RX_DMA_ChInitStr;
+ } dma;
+#endif
rt_uint8_t spi_dma_flag;
+ /* TRUE while a 4-wire full-duplex MASTER receive-only message is being
+ * armed: the TX DMA source is then the static 0xFF fill buffer, and
+ * n32_spi_dma_arm re-points every LLI TX node at its base. Read only
+ * inside n32_spi_dma_arm; set/cleared around the SPI_DMA_TransmitReceive
+ * call in SPI_DMA_Receive. Per-bus messages are serialized by the
+ * RT-Thread bus lock and no ISR reads the flag, so a plain rt_bool_t is
+ * race-free. Unused on non-H7 series. */
+ rt_bool_t fd_rxonly_dummy_tx;
+ /* TRUE while a non-first chunk of a 4-wire full-duplex message is being
+ * armed: spixfer keeps the SPI engine on across chunk boundaries (only
+ * the message tail disables), so SPI_DMA_TransmitReceive re-arms the
+ * live engine warm (no SPIEN drop/re-enable) instead of cold-starting
+ * it. Read only inside SPI_DMA_TransmitReceive; set at the top of every
+ * chunk in spixfer. Per-bus messages are serialized by the RT-Thread
+ * bus lock and no ISR reads the flag, so a plain rt_bool_t is
+ * race-free. Unused on non-H7 series. */
+ rt_bool_t fd_chunk_cont;
struct rt_spi_bus spi_bus;
struct rt_completion cpt;
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.c
index 04b74d68f5..99406391d3 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.c
@@ -161,36 +161,66 @@ static void dma_recv_callback(struct rt_serial_device *serial, rt_uint8_t isr_fl
#if defined(SOC_SERIES_N32H7xx)
- rt_size_t read_len;
- read_len = DMA_GetTransferredNumber(uart->config->dma_rx->Instance, uart->config->dma_rx->dma_channel);
-
+ /* BTS (per-block byte count in CHNCTRL) is only valid within the current
+ * LLI block: the hardware loads the next block and wraps BTS the instant a
+ * block completes. Reading BTS inside the TC ISR may therefore see the
+ * already-wrapped value, and diffing it against the last value would
+ * produce a huge underflow count that permanently corrupts the FIFO put
+ * index. Correct scheme:
+ * - TC ISR only accumulates "actual bytes completed" (no BTS read, no RX
+ * report; the DMA IRQ has a higher priority than the UART IRQ, so the
+ * accumulated value is always up to date when the IDLE handler runs);
+ * - BTS is read only at IDLE (end of frame):
+ * cumulative = completed-block bytes + BTS
+ * bytes since last IDLE = cumulative difference.
+ * NOTE: the last LLI item of the ring may be shorter than 4095B
+ * (remain_len), so the TC ISR must add each block's real size by its index,
+ * otherwise the counter drifts per ring turn (16384B buffer -> 4091B). */
switch (isr_flag)
{
case UART_RX_DMA_IT_IDLE_FLAG:
{
- if (uart->dma.rx_dma.block_has_recv_cnt != 0)
+ rt_uint32_t read_len;
+ rt_uint32_t cum;
+ rt_uint32_t delta;
+
+ read_len = DMA_GetTransferredNumber(uart->config->dma_rx->Instance, uart->config->dma_rx->dma_channel);
+ cum = uart->dma.rx_dma.lli_byte_base + read_len;
+ delta = cum - uart->dma.rx_dma.lli_last_cum; /* u32 wrap-safe subtraction */
+ uart->dma.rx_dma.lli_last_cum = cum;
+
+ /* A frame must fit into the FIFO/ring buffer, otherwise the DMA has
+ * already overwritten it: an illegal state, drop the report */
+ if (delta > 0 && delta <= serial->config.bufsz)
{
- recv_len = read_len - uart->dma.rx_dma.block_has_recv_cnt;
+ recv_len = delta;
}
- else
+ else if (delta > 0)
{
- recv_len = read_len;
+ LOG_E("%s RX DMA delta %u > bufsz %u, drop", uart->config->name, delta, serial->config.bufsz);
}
- uart->dma.rx_dma.block_has_recv_cnt = read_len;
-
break;
}
case UART_RX_DMA_IT_BLOCK_TC_FLAG:
{
- if (uart->dma.rx_dma.block_has_recv_cnt != 0)
- {
- recv_len = read_len - uart->dma.rx_dma.block_has_recv_cnt;
- uart->dma.rx_dma.block_has_recv_cnt = 0;
- }
- else
+ /* Add the real size of the block that just completed: the tail item
+ * is remain_len bytes, all other items are DMA_BLOCK_SIZE bytes */
+ rt_uint16_t blk_num = uart->dma.rx_dma.block_num;
+
+ if (blk_num > 0)
{
- recv_len = DMA_BLOCK_SIZE;
+ rt_uint16_t blk_idx = (rt_uint16_t)(uart->dma.rx_dma.lli_blk_cnt % blk_num);
+
+ if ((blk_idx == (rt_uint16_t)(blk_num - 1)) && uart->dma.rx_dma.remain_len != 0)
+ {
+ uart->dma.rx_dma.lli_byte_base += uart->dma.rx_dma.remain_len;
+ }
+ else
+ {
+ uart->dma.rx_dma.lli_byte_base += DMA_BLOCK_SIZE;
+ }
}
+ uart->dma.rx_dma.lli_blk_cnt++;
break;
}
@@ -950,7 +980,9 @@ static rt_err_t n32_configure(struct rt_serial_device *serial, struct serial_con
if (!(serial->parent.open_flag & RT_DEVICE_OFLAG_OPEN))
{
#if defined(SOC_SERIES_N32H7xx)
- uart->dma.rx_dma.block_has_recv_cnt = 0;
+ uart->dma.rx_dma.lli_blk_cnt = 0;
+ uart->dma.rx_dma.lli_byte_base = 0;
+ uart->dma.rx_dma.lli_last_cum = 0;
#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
uart->dma.rx_dma.remaining_cnt = cfg->bufsz;
#endif /* SOC_SERIES_N32H7xx */
@@ -2194,7 +2226,7 @@ int rt_hw_usart_init(void)
uart_obj[i].dma.rx_dma.Read_LinkList[j].pNext = &uart_obj[i].dma.rx_dma.Read_LinkList[j + 1U];
}
- /* The last block and block size ≠ BLOCK_SIZE */
+ /* The last block and block size != BLOCK_SIZE */
if ((j + 1U) == uart_obj[i].dma.rx_dma.block_num && uart_obj[i].dma.rx_dma.remain_len != 0U)
{
uart_obj[i].dma.rx_dma.Read_LinkList[j].BlkTfrSize = uart_obj[i].dma.rx_dma.remain_len;
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.h b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.h
index 8abb2b16e4..45775cd514 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.h
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_usart.h
@@ -73,7 +73,25 @@ struct n32_uart
{
rt_uint16_t block_num;
rt_uint16_t remain_len;
- rt_size_t block_has_recv_cnt;
+ /* LLI ring accounting (maintained in the TC ISR; BTS is never read
+ * here: the hardware wraps BTS the instant a block completes, so
+ * reading BTS at TC and diffing it against the last value would
+ * underflow and permanently corrupt the FIFO put index):
+ * lli_blk_cnt number of completed LLI blocks (also used as
+ * the block index, modulo block_num)
+ * lli_byte_base actual bytes accumulated for completed blocks.
+ * NOTE: the last LLI item may be shorter than
+ * 4095B (remain_len; 4B when bufsz = 16384), so
+ * the TC ISR must add each block's real size.
+ * Otherwise the counter drifts +4095-remain_len
+ * bytes per ring turn (e.g. +4091B per turn for
+ * a 16384B buffer), eventually corrupting the
+ * FIFO read pointer.
+ * lli_last_cum cumulative bytes at the last IDLE report (the
+ * difference between two reports = frame len) */
+ rt_uint32_t lli_blk_cnt;
+ rt_uint32_t lli_byte_base;
+ rt_uint32_t lli_last_cum;
DMA_LinkListItemType *Read_LinkList;
} rx_dma;
diff --git a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_wdt.c b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_wdt.c
index f779883524..b73f599a6b 100644
--- a/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_wdt.c
+++ b/bsp/n32/n32hxxx/libraries/N32_Drivers/drivers/drv_wdt.c
@@ -14,6 +14,14 @@
#ifdef RT_USING_WDT
+#if defined(SOC_SERIES_N32H47x_48x)
+#include "n32h47x_48x_iwdg.h"
+#elif defined(SOC_SERIES_N32H49x)
+#include "n32h49x_iwdg.h"
+#elif defined(SOC_SERIES_N32H7xx)
+#include "n32h7xx_iwdg.h"
+#endif
+
//#define DRV_DEBUG
#define LOG_TAG "drv.wdt"
#include <drv_log.h>
@@ -58,7 +66,9 @@ static rt_uint32_t wdt_get_prescaler_factor(rt_uint16_t prescaler)
static rt_err_t wdt_init(rt_watchdog_t *wdt)
{
+#if defined(SOC_SERIES_N32H7xx)
n32_wdt.IWDGX_ClkCmd(n32_wdt.IWDG_Clk, ENABLE);
+#endif
return RT_EOK;
}
@@ -73,7 +83,11 @@ static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
{
/* feed the watchdog */
case RT_DEVICE_CTRL_WDT_KEEPALIVE:
+#if defined(SOC_SERIES_N32H7xx)
IWDG_ReloadKey(n32_wdt.IWDGx);
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ IWDG_ReloadKey();
+#endif
break;
/* set watchdog timeout */
@@ -86,6 +100,11 @@ static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
}
reload_value = (*(rt_uint32_t *)arg);
+ if (reload_value == 0U)
+ {
+ LOG_W("wdg timeout must be greater than 0 s\n");
+ return -RT_EINVAL;
+ }
prescaler_factor = wdt_get_prescaler_factor(n32_wdt.Prescaler);
if (LSI_VALUE)
@@ -104,6 +123,7 @@ static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
reload_value = (reload_value * (LSI_VALUE / prescaler_factor)) - 1U;
/* Enable write access to IWDG_PR and IWDG_RLR registers */
+#if defined(SOC_SERIES_N32H7xx)
IWDG_WriteConfig(n32_wdt.IWDGx, IWDG_WRITE_ENABLE);
/* Set IWDG PREDIV */
IWDG_SetPrescalerDiv(n32_wdt.IWDGx, n32_wdt.Prescaler);
@@ -114,6 +134,18 @@ static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
/* Disable write access to IWDG_PR and IWDG_RLR registers */
IWDG_WriteConfig(n32_wdt.IWDGx, IWDG_WRITE_DISABLE);
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ IWDG_WriteConfig(IWDG_WRITE_ENABLE);
+ /* Set IWDG PREDIV */
+ IWDG_SetPrescalerDiv(n32_wdt.Prescaler);
+ /* Set Counter Reload Value */
+ IWDG_CntReload((uint16_t)reload_value);
+ /* Reload IWDG counter */
+ IWDG_ReloadKey();
+
+ /* Disable write access to IWDG_PR and IWDG_RLR registers */
+ IWDG_WriteConfig(IWDG_WRITE_DISABLE);
+#endif
}
}
else
@@ -135,7 +167,11 @@ static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
LOG_W("IWDG is already started\n");
return RT_EOK;
}
+#if defined(SOC_SERIES_N32H7xx)
IWDG_Enable(n32_wdt.IWDGx);
+#elif defined(SOC_SERIES_N32H47x_48x) || defined(SOC_SERIES_N32H49x)
+ IWDG_Enable();
+#endif
n32_wdt.is_start = 1;
break;
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/.config b/bsp/n32/n32hxxx/n32h487zgl7-evb/.config
index 4d4870d535..6bb204b3ba 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/.config
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/.config
@@ -158,15 +158,14 @@ CONFIG_RT_USING_MESSAGEQUEUE=y
#
# Memory Management
#
-CONFIG_RT_USING_MEMPOOL=y
-# CONFIG_RT_USING_SMALL_MEM is not set
+# CONFIG_RT_USING_MEMPOOL is not set
+CONFIG_RT_USING_SMALL_MEM=y
# CONFIG_RT_USING_SLAB is not set
CONFIG_RT_USING_MEMHEAP=y
CONFIG_RT_MEMHEAP_FAST_MODE=y
# CONFIG_RT_MEMHEAP_BEST_MODE is not set
-# CONFIG_RT_USING_SMALL_MEM_AS_HEAP is not set
-CONFIG_RT_USING_MEMHEAP_AS_HEAP=y
-CONFIG_RT_USING_MEMHEAP_AUTO_BINDING=y
+CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y
+# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
# CONFIG_RT_USING_SLAB_AS_HEAP is not set
# CONFIG_RT_USING_USERHEAP is not set
# CONFIG_RT_USING_NOHEAP is not set
@@ -183,7 +182,7 @@ CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=512
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y
-CONFIG_RT_VER_NUM=0x50300
+CONFIG_RT_VER_NUM=0x50301
# CONFIG_RT_USING_STDC_ATOMIC is not set
CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
# end of RT-Thread Kernel
@@ -584,6 +583,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
# CONFIG_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_PERSIMMON is not set
# CONFIG_PKG_USING_3GPP_AMRNB is not set
+# CONFIG_PKG_USING_LITETYPE is not set
# end of multimedia packages
#
@@ -1032,6 +1032,7 @@ CONFIG_PKG_N32H47X_48X_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_QMI8658 is not set
# CONFIG_PKG_USING_ICM20948 is not set
# CONFIG_PKG_USING_SCD4X is not set
+# CONFIG_PKG_USING_BMI270 is not set
# end of sensors drivers
#
@@ -1086,6 +1087,7 @@ CONFIG_PKG_N32H47X_48X_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_WK2124 is not set
# CONFIG_PKG_USING_LY68L6400 is not set
# CONFIG_PKG_USING_DM9051 is not set
+# CONFIG_PKG_USING_CH390 is not set
# CONFIG_PKG_USING_SSD1306 is not set
# CONFIG_PKG_USING_QKEY is not set
# CONFIG_PKG_USING_RS485 is not set
@@ -1154,6 +1156,9 @@ CONFIG_PKG_N32H47X_48X_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_NAXOS is not set
# CONFIG_PKG_USING_R_TINYMAIX is not set
# CONFIG_PKG_USING_LLMCHAT is not set
+# CONFIG_PKG_USING_LIME_TM is not set
+# CONFIG_PKG_USING_AIFES is not set
+# CONFIG_PKG_USING_AGENT is not set
# end of AI packages
#
@@ -1488,6 +1493,8 @@ CONFIG_SOC_SERIES_N32H47x_48x=y
#
# Onboard Peripheral Drivers
#
+# CONFIG_BSP_USING_ETH is not set
+# end of Onboard Peripheral Drivers
#
# On-chip Peripheral Drivers
@@ -1499,9 +1506,20 @@ CONFIG_BSP_USING_UART1=y
# CONFIG_BSP_UART1_TX_USING_DMA is not set
# CONFIG_BSP_USING_UART2 is not set
# CONFIG_BSP_USING_UART3 is not set
+# CONFIG_BSP_USING_UART4 is not set
+# CONFIG_BSP_USING_UART5 is not set
+# CONFIG_BSP_USING_UART6 is not set
+# CONFIG_BSP_USING_UART7 is not set
+# CONFIG_BSP_USING_UART8 is not set
+# CONFIG_BSP_USING_SPI is not set
# CONFIG_BSP_USING_ON_CHIP_FLASH is not set
+# CONFIG_BSP_USING_QSPI is not set
+# CONFIG_BSP_USING_HARD_I2C is not set
# CONFIG_BSP_USING_ONCHIP_RTC is not set
+# CONFIG_BSP_USING_WDT is not set
# CONFIG_BSP_USING_FDCAN is not set
+# CONFIG_BSP_USING_NAND is not set
+# CONFIG_BSP_USING_SDIO is not set
# end of On-chip Peripheral Drivers
#
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/Cube_Config.ntfx b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/Cube_Config.ntfx
index 468240de0e..73388dca50 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/Cube_Config.ntfx
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/Cube_Config.ntfx
Binary files differ
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/USER/src/n32h47x_48x_cfg.c b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/USER/src/n32h47x_48x_cfg.c
index 607700155c..fb6075f7a7 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/USER/src/n32h47x_48x_cfg.c
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Cube_Config/USER/src/n32h47x_48x_cfg.c
@@ -134,7 +134,12 @@ bool RCC_Configuration(void)
ClockStatus = RCC_WaitHsiStable();
if (ClockStatus != SUCCESS) return false;
- RCC_ConfigPll(RCC_PLL_SRC_HSI,RCC_PLL_PRE_2,RCC_PLL_MUL_60,RCC_PLLOUT_DIV_1);
+ RCC_ConfigHse(RCC_HSE_ENABLE);
+ /* Wait till HSE is ready */
+ ClockStatus = RCC_WaitHseStable();
+ if (ClockStatus != SUCCESS) return false;
+
+ RCC_ConfigPll(RCC_PLL_SRC_HSE,RCC_PLL_PRE_2,RCC_PLL_MUL_60,RCC_PLLOUT_DIV_1);
/* Enable PLL */
RCC_EnablePll(ENABLE);
/* Wait till PLL is ready */
@@ -177,7 +182,7 @@ bool GPIO_Configuration(void)
GPIO_InitStruct(&GPIO_InitStructure);
/* Enable the GPIO clock*/
- RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOH, ENABLE);
+ RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOH | RCC_AHB_PERIPHEN_GPIOC, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO,ENABLE);
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Kconfig b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Kconfig
index c0b5821609..5a884858f3 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Kconfig
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/Kconfig
@@ -2,6 +2,48 @@ menu "Hardware Drivers Config"
menu "Onboard Peripheral Drivers"
+ menuconfig BSP_USING_ETH
+ bool "Enable Ethernet"
+ default n
+ select RT_USING_LWIP
+ if BSP_USING_ETH
+ choice BSP_ETH_INTERFACE_SEL
+ prompt "Select Media Interface"
+ default ETH_INTERFACE_USING_RMII
+
+ config ETH_INTERFACE_USING_MII
+ bool "MII"
+
+ config ETH_INTERFACE_USING_RMII
+ bool "RMII"
+ endchoice
+
+ choice BSP_ETH_PHY_SEL
+ prompt "Select PHY Chip"
+ default PHY_USING_DM9162EP
+
+ config PHY_USING_DM9162EP
+ bool "DM9162EP (10M/100M, MII/RMII)"
+
+ config PHY_USING_LAN8720A
+ bool "LAN8720A (10M/100M, MII/RMII)"
+ endchoice
+
+ config BSP_ETH_USING_HW_CHECKSUM
+ bool "Enable Hardware Checksum"
+ select RT_LWIP_USING_HW_CHECKSUM
+ default n
+
+ config PHY_USING_INTERRUPT_MODE
+ bool "Enable PHY Link Change Interrupt Mode"
+ default n
+ if PHY_USING_INTERRUPT_MODE
+ config PHY_INT_PIN
+ int "PHY Interrupt Pin Number"
+ range 0 255
+ default 0
+ endif
+ endif
endmenu
menu "On-chip Peripheral Drivers"
@@ -58,12 +100,202 @@ menu "On-chip Peripheral Drivers"
depends on BSP_USING_UART3 && RT_SERIAL_USING_DMA
default n
+ config BSP_USING_UART4
+ bool "Enable UART4"
+ default n
+
+ config BSP_UART4_RX_USING_DMA
+ bool "Enable UART4 RX DMA"
+ depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART4_TX_USING_DMA
+ bool "Enable UART4 TX DMA"
+ depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART5
+ bool "Enable UART5"
+ default n
+
+ config BSP_UART5_RX_USING_DMA
+ bool "Enable UART5 RX DMA"
+ depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART5_TX_USING_DMA
+ bool "Enable UART5 TX DMA"
+ depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART6
+ bool "Enable UART6"
+ default n
+
+ config BSP_UART6_RX_USING_DMA
+ bool "Enable UART6 RX DMA"
+ depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART6_TX_USING_DMA
+ bool "Enable UART6 TX DMA"
+ depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART7
+ bool "Enable UART7"
+ default n
+
+ config BSP_UART7_RX_USING_DMA
+ bool "Enable UART7 RX DMA"
+ depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART7_TX_USING_DMA
+ bool "Enable UART7 TX DMA"
+ depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART8
+ bool "Enable UART8"
+ default n
+
+ config BSP_UART8_RX_USING_DMA
+ bool "Enable UART8 RX DMA"
+ depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART8_TX_USING_DMA
+ bool "Enable UART8 TX DMA"
+ depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA
+ default n
+
+ endif
+
+ menuconfig BSP_USING_SPI
+ bool "Enable SPI BUS"
+ default n
+ select RT_USING_SPI
+ if BSP_USING_SPI
+ config BSP_USING_SPI1
+ bool "Enable SPI1 BUS"
+ default n
+
+ config BSP_SPI1_TX_USING_DMA
+ bool "Enable SPI1 TX DMA"
+ depends on BSP_USING_SPI1
+ default n
+
+ config BSP_SPI1_RX_USING_DMA
+ bool "Enable SPI1 RX DMA"
+ depends on BSP_USING_SPI1
+ select BSP_SPI1_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI2
+ bool "Enable SPI2 BUS"
+ default n
+
+ config BSP_SPI2_TX_USING_DMA
+ bool "Enable SPI2 TX DMA"
+ depends on BSP_USING_SPI2
+ default n
+
+ config BSP_SPI2_RX_USING_DMA
+ bool "Enable SPI2 RX DMA"
+ depends on BSP_USING_SPI2
+ select BSP_SPI2_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI3
+ bool "Enable SPI3 BUS"
+ default n
+
+ config BSP_SPI3_TX_USING_DMA
+ bool "Enable SPI3 TX DMA"
+ depends on BSP_USING_SPI3
+ default n
+
+ config BSP_SPI3_RX_USING_DMA
+ bool "Enable SPI3 RX DMA"
+ depends on BSP_USING_SPI3
+ select BSP_SPI3_TX_USING_DMA
+ default n
+
endif
config BSP_USING_ON_CHIP_FLASH
bool "Enable on-chip FLASH"
default n
+ menuconfig BSP_USING_QSPI
+ bool "Enable QSPI (XSPI) BUS"
+ default n
+ select RT_USING_QSPI
+ select RT_USING_SPI
+
+ menuconfig BSP_USING_HARD_I2C
+ bool "Enable Hard I2C BUS"
+ default n
+ select RT_USING_I2C
+ if BSP_USING_HARD_I2C
+ config BSP_USING_HARD_I2C1
+ bool "Enable I2C1 BUS"
+ default n
+
+ config BSP_I2C1_RX_USING_DMA
+ bool "Enable I2C1 RX DMA"
+ depends on BSP_USING_HARD_I2C1
+ default n
+
+ config BSP_I2C1_TX_USING_DMA
+ bool "Enable i2c1 TX DMA"
+ depends on BSP_USING_HARD_I2C1
+ default n
+
+ config BSP_USING_HARD_I2C2
+ bool "Enable I2C2 BUS"
+ default n
+
+ config BSP_I2C2_RX_USING_DMA
+ bool "Enable I2C2 RX DMA"
+ depends on BSP_USING_HARD_I2C2
+ default n
+
+ config BSP_I2C2_TX_USING_DMA
+ bool "Enable i2c2 TX DMA"
+ depends on BSP_USING_HARD_I2C2
+ default n
+
+ config BSP_USING_HARD_I2C3
+ bool "Enable I2C3 BUS"
+ default n
+
+ config BSP_I2C3_RX_USING_DMA
+ bool "Enable I2C3 RX DMA"
+ depends on BSP_USING_HARD_I2C3
+ default n
+
+ config BSP_I2C3_TX_USING_DMA
+ bool "Enable i2c3 TX DMA"
+ depends on BSP_USING_HARD_I2C3
+ default n
+
+ config BSP_USING_HARD_I2C4
+ bool "Enable I2C4 BUS"
+ default n
+
+ config BSP_I2C4_RX_USING_DMA
+ bool "Enable I2C4 RX DMA"
+ depends on BSP_USING_HARD_I2C4
+ default n
+
+ config BSP_I2C4_TX_USING_DMA
+ bool "Enable i2c4 TX DMA"
+ depends on BSP_USING_HARD_I2C4
+ default n
+ endif
+
menuconfig BSP_USING_ONCHIP_RTC
bool "Enable RTC"
select RT_USING_RTC
@@ -81,6 +313,33 @@ menu "On-chip Peripheral Drivers"
endchoice
endif
+ menuconfig BSP_USING_ADC
+ bool "Enable ADC"
+ default n
+ select RT_USING_ADC
+ if BSP_USING_ADC
+ config BSP_USING_ADC1
+ bool "Enable ADC1"
+ default n
+
+ config BSP_USING_ADC2
+ bool "Enable ADC2"
+ default n
+
+ config BSP_USING_ADC3
+ bool "Enable ADC3"
+ default n
+
+ config BSP_USING_ADC4
+ bool "Enable ADC4"
+ default n
+ endif
+
+ config BSP_USING_WDT
+ bool "Enable Watchdog Timer"
+ select RT_USING_WDT
+ default n
+
menuconfig BSP_USING_FDCAN
bool "Enable FDCAN (CAN FD)"
default n
@@ -383,6 +642,106 @@ menu "On-chip Peripheral Drivers"
endif
endif
+ menuconfig BSP_USING_DAC
+ bool "Enable DAC"
+ default n
+ select RT_USING_DAC
+ if BSP_USING_DAC
+ config BSP_USING_DAC1
+ bool "Enable DAC1"
+ default n
+
+ config BSP_USING_DAC2
+ bool "Enable DAC2"
+ default n
+
+ config BSP_USING_DAC3
+ bool "Enable DAC3"
+ default n
+
+ config BSP_USING_DAC4
+ bool "Enable DAC4"
+ default n
+
+ config BSP_USING_DAC5
+ bool "Enable DAC5"
+ default n
+
+ config BSP_USING_DAC6
+ bool "Enable DAC6"
+ default n
+
+ config BSP_USING_DAC7
+ bool "Enable DAC7"
+ default n
+
+ config BSP_USING_DAC8
+ bool "Enable DAC8"
+ default n
+ endif
+
+ menuconfig BSP_USING_NAND
+ bool "Enable Nand"
+ default n
+ select RT_USING_MTD_NAND
+ if BSP_USING_NAND
+ choice BSP_NAND_BANK_SEL
+ prompt "Select Bank"
+ default BSP_USING_NAND_BANK3
+
+ config BSP_USING_NAND_BANK2
+ bool "USING FEMC NAND BANK2"
+
+ config BSP_USING_NAND_BANK3
+ bool "USING FEMC NAND BANK3"
+ endchoice
+
+ choice BSP_NAND_BUS_WIDTH_SEL
+ prompt "Select Nand Bus Width"
+ default BSP_USING_NAND_BUS_WIDTH_8B
+
+ config BSP_USING_NAND_BUS_WIDTH_8B
+ bool "USING FEMC NAND BUS WIDTH 8BIT"
+
+ config BSP_USING_NAND_BUS_WIDTH_16B
+ bool "USING FEMC NAND BUS WIDTH 16BIT"
+ endchoice
+
+ config BSP_NAND_PAGE_SIZE
+ int "Page Size (bytes)"
+ default 2048
+ help
+ NAND flash page size in bytes, typically 2048 or 4096.
+
+ config BSP_NAND_OOB_SIZE
+ int "OOB (Spare Area) Size (bytes)"
+ default 64
+ help
+ NAND flash spare area size per page, typically 64 or 128.
+
+ config BSP_NAND_PAGES_PER_BLOCK
+ int "Pages Per Block"
+ default 64
+ help
+ Number of pages per erase block, typically 64 or 128.
+
+ config BSP_NAND_BLOCK_COUNT
+ int "Total Block Count"
+ default 1024
+ help
+ Total number of blocks in the NAND flash chip.
+
+ config BSP_NAND_PLANE_NUM
+ int "Plane Number"
+ default 1
+ help
+ Number of planes in the NAND flash chip, typically 1 or 2.
+ endif
+
+ config BSP_USING_SDIO
+ bool "Enable SDIO"
+ default n
+
source "$BSP_DIR/../libraries/N32_Drivers/drivers/Kconfig"
endmenu
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/SConscript b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/SConscript
index fa12bc4751..56260ee6bf 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/SConscript
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/SConscript
@@ -11,6 +11,7 @@ Cube_Config/USER/src/n32h47x_48x_cfg.c
path = [cwd]
path += [os.path.join(cwd, 'Cube_Config', 'USER', 'inc')]
+path += [os.path.join(cwd, 'ports')]
CPPDEFINES = ['N32H488', 'CORE_CM4']
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/SConscript b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/SConscript
index 1948a8d10a..6b1d350978 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/SConscript
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/SConscript
@@ -7,7 +7,11 @@ cwd = GetCurrentDir()
# add general drivers
src = []
path = [cwd]
-
+if GetDepend(['BSP_USING_NAND']):
+ src += Glob('femc_timing.c')
+
+if GetDepend(['BSP_USING_ETH']):
+ src += Glob('phy_reset.c')
CPPDEFINES = ['']
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.c b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.c
new file mode 100644
index 0000000000..77526c0a0a
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-25 ox-horse first version
+ */
+
+#include "femc_timing.h"
+
+#ifdef BSP_USING_NAND
+
+/*
+ * FEMC NAND timing configuration (N32H47x/48x).
+ *
+ * Timing values are in HCLK cycles, taken from the Nations FEMC Nand_Flash
+ * demo (FEMC_Nand_Init): SET=4, WAIT=6, HOLD=5, HIZ=5,
+ * TCLR/TAR = CLE/ALE delay of 1 HCLK.
+ *
+ * Actual time (ns) = value * HCLK_period (ns). When porting to a different
+ * system clock, recalculate HCLK period from RCC_Configuration() and adjust
+ * all values below to satisfy the NAND datasheet timing.
+ *
+ * Registers written by FEMC_InitNand():
+ * FEMC_NCTRLx <- WaitFeatureEnable | MemDataWidth | EccEnable |
+ * EccPageSize | TCLRSetTime | TARSetTime
+ * FEMC_NCMEMTMx <- CommSpaceTimingStruct (timing)
+ * FEMC_NATTMEMTMx <- AttrSpaceTimingStruct (timing)
+ */
+void FEMC_Nand_Timing_Config(FEMC_NandInitType *nandInit,
+ FEMC_NandTimingInitType *timing)
+{
+ /* Address setup time: 4 HCLK */
+ timing->SetTime = FEMC_NAND_SETUP_TIME(0x4);
+ /* Command assert width: 6 HCLK */
+ timing->WaitSetTime = FEMC_NAND_WAIT_TIME(0x6);
+ /* Address/data hold time: 5 HCLK */
+ timing->HoldSetTime = FEMC_NAND_HOLD_TIME(0x5);
+ /* Data bus HiZ time: 5 HCLK */
+ timing->HiZSetTime = FEMC_NAND_HIZ_TIME(0x5);
+
+ nandInit->CommSpaceTimingStruct = timing;
+ nandInit->AttrSpaceTimingStruct = timing;
+
+ /* CLE to RE delay (TCLR): 1 HCLK */
+ nandInit->TCLRSetTime = FEMC_NAND_CLE_DELAY_1HCLK;
+ /* ALE to RE delay (TAR): 1 HCLK */
+ nandInit->TARSetTime = FEMC_NAND_ALE_DELAY_1HCLK;
+}
+
+#endif /* BSP_USING_NAND */
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.h b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.h
new file mode 100644
index 0000000000..a408416c1a
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/femc_timing.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-25 ox-horse first version
+ */
+
+#ifndef __FEMC_TIMING_H__
+#define __FEMC_TIMING_H__
+
+#include "board.h"
+
+/*
+ * Configure FEMC NAND timing parameters (N32H47x/48x).
+ *
+ * This fills the timing-related fields of the NAND init structures:
+ * - timing: SET/WAIT/HOLD/HIZ (then linked to nandInit's
+ * CommSpaceTimingStruct / AttrSpaceTimingStruct)
+ * - nandInit: TCLRSetTime / TARSetTime (CLE/ALE to RE delay)
+ *
+ * @note structures are of type FEMC_NandInitType / FEMC_NandTimingInitType
+ * (N32H47x/48x SDK), which differ from N32H7xx FEMC_TimingInitType.
+ */
+void FEMC_Nand_Timing_Config(FEMC_NandInitType *nandInit,
+ FEMC_NandTimingInitType *timing);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FEMC_TIMING_H__ */
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/phy_reset.c b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/phy_reset.c
new file mode 100644
index 0000000000..3230c65234
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/phy_reset.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-15 ox-horse first version
+ */
+
+#include <board.h>
+#include <drv_gpio.h>
+
+#define RESET_IO GET_PIN(D, 3)
+
+void phy_reset(void)
+{
+ rt_pin_write(RESET_IO, PIN_LOW);
+ rt_thread_mdelay(50);
+ rt_pin_write(RESET_IO, PIN_HIGH);
+}
+
+int phy_init(void)
+{
+ rt_pin_mode(RESET_IO, PIN_MODE_OUTPUT);
+ rt_pin_write(RESET_IO, PIN_HIGH);
+ return RT_EOK;
+}
+INIT_BOARD_EXPORT(phy_init);
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/usb_config.h b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/usb_config.h
new file mode 100644
index 0000000000..cf3dde8044
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/board/ports/usb_config.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-28 ox-horse first version
+ */
+
+#ifndef CHERRYUSB_CONFIG_H
+#define CHERRYUSB_CONFIG_H
+
+/* ================ USB common Configuration ================ */
+
+#ifdef __RTTHREAD__
+#include <rtthread.h>
+
+#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
+#else
+#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
+#endif
+
+#ifndef CONFIG_USB_DBG_LEVEL
+#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
+#endif
+
+/* Enable print with color */
+#define CONFIG_USB_PRINTF_COLOR_ENABLE
+
+/* N32H47x_48x is a Cortex-M4 without cache, so no dcache or dma alignment
+ * is required, and no noncacheable section is needed. */
+#define CONFIG_USB_ALIGN_SIZE 4
+
+#define USB_NOCACHE_RAM_SECTION
+
+/* use usb_memcpy default for high performance but cost more flash memory.
+ * And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
+*/
+// #define CONFIG_USB_MEMCPY_DISABLE
+
+/* ================= USB Device Stack Configuration ================ */
+
+/* Ep0 in and out transfer buffer */
+#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
+#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
+#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512
+#endif
+
+#ifndef CONFIG_USBDEV_MAX_BUS
+#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
+#endif
+
+#ifndef CONFIG_USBDEV_EP_NUM
+#define CONFIG_USBDEV_EP_NUM 8
+#endif
+
+/* ================ USB Device Port Configuration ================*/
+
+/* FSDEV port (Synopsys USBFS) PMA access mode. The N32H4x USBFS
+ * (usb_fsdev_reg.h) re-arranges the register map but keeps the buffer
+ * descriptor table layout that matches the ST macro addressing with
+ * PMA_ACCESS=2, which is what usb_dc_fsdev.c requires. */
+#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2
+
+#endif
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/project.ewp b/bsp/n32/n32hxxx/n32h487zgl7-evb/project.ewp
index 3d2a236c17..f2fbc5276a 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/project.ewp
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/project.ewp
@@ -364,7 +364,6 @@
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\common</state>
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\cortex-m4</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\include</state>
- <state>$PROJ_DIR$\..\..\..\..\components\drivers\phy</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\smp_call</state>
<state>$PROJ_DIR$\board</state>
<state>$PROJ_DIR$\board\Cube_Config\USER\inc</state>
@@ -384,6 +383,7 @@
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\ipc</state>
<state>$PROJ_DIR$\packages\n32h47x_48x_std_driver-latest\n32h47x_48x_std_periph_driver\inc</state>
<state>$PROJ_DIR$\packages\n32h47x_48x_cmsis_driver-latest\device</state>
+ <state>$PROJ_DIR$\applications\test_file</state>
<state>$PROJ_DIR$\..\..\..\..\components\net\utest</state>
</option>
<option>
@@ -1455,7 +1455,6 @@
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\common</state>
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\cortex-m4</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\include</state>
- <state>$PROJ_DIR$\..\..\..\..\components\drivers\phy</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\smp_call</state>
<state>$PROJ_DIR$\board</state>
<state>$PROJ_DIR$\board\Cube_Config\USER\inc</state>
@@ -1475,6 +1474,7 @@
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\ipc</state>
<state>$PROJ_DIR$\packages\n32h47x_48x_std_driver-latest\n32h47x_48x_std_periph_driver\inc</state>
<state>$PROJ_DIR$\packages\n32h47x_48x_cmsis_driver-latest\device</state>
+ <state>$PROJ_DIR$\applications\test_file</state>
<state>$PROJ_DIR$\..\..\..\..\components\net\utest</state>
</option>
<option>
@@ -2308,10 +2308,10 @@
<name>$PROJ_DIR$\..\..\..\..\src\kservice.c</name>
</file>
<file>
- <name>$PROJ_DIR$\..\..\..\..\src\memheap.c</name>
+ <name>$PROJ_DIR$\..\..\..\..\src\mem.c</name>
</file>
<file>
- <name>$PROJ_DIR$\..\..\..\..\src\mempool.c</name>
+ <name>$PROJ_DIR$\..\..\..\..\src\memheap.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\src\object.c</name>
@@ -2432,6 +2432,9 @@
</file>
</group>
<group>
+ <name>test_file</name>
+ </group>
+ <group>
<name>utc_UTest</name>
</group>
<group>
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvoptx b/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvoptx
index f5bcf9e7ee..f7e81a827c 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvoptx
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvoptx
@@ -652,8 +652,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\memheap.c</PathWithFileName>
- <FilenameWithoutPath>memheap.c</FilenameWithoutPath>
+ <PathWithFileName>..\..\..\..\src\mem.c</PathWithFileName>
+ <FilenameWithoutPath>mem.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@@ -664,8 +664,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\mempool.c</PathWithFileName>
- <FilenameWithoutPath>mempool.c</FilenameWithoutPath>
+ <PathWithFileName>..\..\..\..\src\memheap.c</PathWithFileName>
+ <FilenameWithoutPath>memheap.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@@ -897,7 +897,7 @@
<Group>
<GroupName>Libraries</GroupName>
- <tvExp>0</tvExp>
+ <tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@@ -1013,7 +1013,7 @@
<Group>
<GroupName>Libraries-CMSIS</GroupName>
- <tvExp>0</tvExp>
+ <tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvprojx b/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvprojx
index e2aa9ad64c..3e4221f93d 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvprojx
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/project.uvprojx
@@ -337,9 +337,9 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
- <Define>__RTTHREAD__, USE_STDPERIPH_DRIVER, __STDC_LIMIT_MACROS, __CLK_TCK=RT_TICK_PER_SECOND, CORE_CM4, RT_USING_ARMLIBC, N32H488, RT_USING_LIBC</Define>
+ <Define>__STDC_LIMIT_MACROS, USE_STDPERIPH_DRIVER, CORE_CM4, RT_USING_LIBC, __CLK_TCK=RT_TICK_PER_SECOND, N32H488, __RTTHREAD__, RT_USING_ARMLIBC</Define>
<Undefine></Undefine>
- <IncludePath>board;packages\n32h47x_48x_cmsis_driver-latest\device;..\..\..\..\components\libc\posix\io\eventfd;packages\CMSIS-Core-latest\Include;..\..\..\..\libcpu\arm\common;..\..\..\..\components\drivers\include;board\ports;..\..\..\..\components\libc\posix\io\poll;packages\n32h47x_48x_std_driver-latest\n32h47x_48x_std_periph_driver\inc;..\..\..\..\components\finsh;..\..\..\..\components\drivers\include;..\..\..\..\include;..\..\..\..\components\net\utest;..\libraries\N32_Drivers\drivers;..\..\..\..\components\drivers\smp_call;applications;..\..\..\..\components\libc\posix\io\epoll;..\..\..\..\libcpu\arm\cortex-m4;..\..\..\..\components\libc\posix\ipc;board\Cube_Config\USER\inc;..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\include;..\libraries\N32_Drivers\drivers\config;..\libraries\N32_Drivers;.;..\..\..\..\components\libc\compilers\common\extension</IncludePath>
+ <IncludePath>..\..\..\..\components\libc\posix\io\epoll;..\..\..\..\components\finsh;..\..\..\..\libcpu\arm\common;..\..\..\..\include;..\..\..\..\libcpu\arm\cortex-m4;packages\n32h47x_48x_cmsis_driver-latest\device;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\smp_call;..\..\..\..\components\drivers\include;..\libraries\N32_Drivers\drivers;board\ports;packages\n32h47x_48x_std_driver-latest\n32h47x_48x_std_periph_driver\inc;..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;packages\CMSIS-Core-latest\Include;..\libraries\N32_Drivers;..\..\..\..\components\libc\posix\io\eventfd;..\..\..\..\components\net\utest;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\include;..\..\..\..\components\libc\posix\ipc;..\..\..\..\components\libc\compilers\common\extension;..\libraries\N32_Drivers\drivers\config;applications;.;board;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\posix\io\poll;..\..\..\..\components\drivers\include;board\Cube_Config\USER\inc</IncludePath>
</VariousControls>
</Cads>
<Aads>
@@ -1604,9 +1604,9 @@
</FileOption>
</File>
<File>
- <FileName>memheap.c</FileName>
+ <FileName>mem.c</FileName>
<FileType>1</FileType>
- <FilePath>..\..\..\..\src\memheap.c</FilePath>
+ <FilePath>..\..\..\..\src\mem.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
@@ -1660,9 +1660,9 @@
</FileOption>
</File>
<File>
- <FileName>mempool.c</FileName>
+ <FileName>memheap.c</FileName>
<FileType>1</FileType>
- <FilePath>..\..\..\..\src\mempool.c</FilePath>
+ <FilePath>..\..\..\..\src\memheap.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
diff --git a/bsp/n32/n32hxxx/n32h487zgl7-evb/rtconfig.h b/bsp/n32/n32hxxx/n32h487zgl7-evb/rtconfig.h
index 9c6a89b3b7..ac8b21330e 100644
--- a/bsp/n32/n32hxxx/n32h487zgl7-evb/rtconfig.h
+++ b/bsp/n32/n32hxxx/n32h487zgl7-evb/rtconfig.h
@@ -95,11 +95,10 @@
/* Memory Management */
-#define RT_USING_MEMPOOL
+#define RT_USING_SMALL_MEM
#define RT_USING_MEMHEAP
#define RT_MEMHEAP_FAST_MODE
-#define RT_USING_MEMHEAP_AS_HEAP
-#define RT_USING_MEMHEAP_AUTO_BINDING
+#define RT_USING_SMALL_MEM_AS_HEAP
#define RT_USING_HEAP
/* end of Memory Management */
#define RT_USING_DEVICE
@@ -107,7 +106,7 @@
#define RT_CONSOLEBUF_SIZE 512
#define RT_CONSOLE_DEVICE_NAME "uart1"
#define RT_USING_CONSOLE_OUTPUT_CTL
-#define RT_VER_NUM 0x50300
+#define RT_VER_NUM 0x50301
#define RT_BACKTRACE_LEVEL_MAX_NR 32
/* end of RT-Thread Kernel */
#define RT_USING_HW_ATOMIC
@@ -433,6 +432,8 @@
/* Onboard Peripheral Drivers */
+/* end of Onboard Peripheral Drivers */
+
/* On-chip Peripheral Drivers */
#define BSP_USING_GPIO
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/.config b/bsp/n32/n32hxxx/n32h497zgl7-evb/.config
index 2d3a0eda5f..0f1c9e843f 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/.config
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/.config
@@ -159,14 +159,11 @@ CONFIG_RT_USING_MESSAGEQUEUE=y
# Memory Management
#
CONFIG_RT_USING_MEMPOOL=y
-# CONFIG_RT_USING_SMALL_MEM is not set
+CONFIG_RT_USING_SMALL_MEM=y
# CONFIG_RT_USING_SLAB is not set
-CONFIG_RT_USING_MEMHEAP=y
-CONFIG_RT_MEMHEAP_FAST_MODE=y
-# CONFIG_RT_MEMHEAP_BEST_MODE is not set
-# CONFIG_RT_USING_SMALL_MEM_AS_HEAP is not set
-CONFIG_RT_USING_MEMHEAP_AS_HEAP=y
-CONFIG_RT_USING_MEMHEAP_AUTO_BINDING=y
+# CONFIG_RT_USING_MEMHEAP is not set
+CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y
+# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
# CONFIG_RT_USING_SLAB_AS_HEAP is not set
# CONFIG_RT_USING_USERHEAP is not set
# CONFIG_RT_USING_NOHEAP is not set
@@ -183,7 +180,7 @@ CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=512
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y
-CONFIG_RT_VER_NUM=0x50300
+CONFIG_RT_VER_NUM=0x50301
# CONFIG_RT_USING_STDC_ATOMIC is not set
CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
# end of RT-Thread Kernel
@@ -584,6 +581,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
# CONFIG_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_PERSIMMON is not set
# CONFIG_PKG_USING_3GPP_AMRNB is not set
+# CONFIG_PKG_USING_LITETYPE is not set
# end of multimedia packages
#
@@ -1032,6 +1030,7 @@ CONFIG_PKG_N32H49X_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_QMI8658 is not set
# CONFIG_PKG_USING_ICM20948 is not set
# CONFIG_PKG_USING_SCD4X is not set
+# CONFIG_PKG_USING_BMI270 is not set
# end of sensors drivers
#
@@ -1086,6 +1085,7 @@ CONFIG_PKG_N32H49X_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_WK2124 is not set
# CONFIG_PKG_USING_LY68L6400 is not set
# CONFIG_PKG_USING_DM9051 is not set
+# CONFIG_PKG_USING_CH390 is not set
# CONFIG_PKG_USING_SSD1306 is not set
# CONFIG_PKG_USING_QKEY is not set
# CONFIG_PKG_USING_RS485 is not set
@@ -1154,6 +1154,9 @@ CONFIG_PKG_N32H49X_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_NAXOS is not set
# CONFIG_PKG_USING_R_TINYMAIX is not set
# CONFIG_PKG_USING_LLMCHAT is not set
+# CONFIG_PKG_USING_LIME_TM is not set
+# CONFIG_PKG_USING_AIFES is not set
+# CONFIG_PKG_USING_AGENT is not set
# end of AI packages
#
@@ -1488,6 +1491,9 @@ CONFIG_SOC_SERIES_N32H49x=y
#
# Onboard Peripheral Drivers
#
+# CONFIG_BSP_USING_ETH is not set
+# CONFIG_BSP_USING_SDRAM is not set
+# end of Onboard Peripheral Drivers
#
# On-chip Peripheral Drivers
@@ -1499,9 +1505,22 @@ CONFIG_BSP_USING_UART1=y
# CONFIG_BSP_UART1_TX_USING_DMA is not set
# CONFIG_BSP_USING_UART2 is not set
# CONFIG_BSP_USING_UART3 is not set
+# CONFIG_BSP_USING_UART4 is not set
+# CONFIG_BSP_USING_UART5 is not set
+# CONFIG_BSP_USING_UART6 is not set
+# CONFIG_BSP_USING_UART7 is not set
+# CONFIG_BSP_USING_UART8 is not set
+# CONFIG_BSP_USING_UART9 is not set
+# CONFIG_BSP_USING_UART10 is not set
+# CONFIG_BSP_USING_SPI is not set
# CONFIG_BSP_USING_ON_CHIP_FLASH is not set
+# CONFIG_BSP_USING_QSPI is not set
+# CONFIG_BSP_USING_HARD_I2C is not set
# CONFIG_BSP_USING_ONCHIP_RTC is not set
+# CONFIG_BSP_USING_WDT is not set
# CONFIG_BSP_USING_FDCAN is not set
+# CONFIG_BSP_USING_NAND is not set
+# CONFIG_BSP_USING_SDIO is not set
# end of On-chip Peripheral Drivers
#
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/Cube_Config.ntfx b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/Cube_Config.ntfx
index e5a1e567ef..1e41105a95 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/Cube_Config.ntfx
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/Cube_Config.ntfx
Binary files differ
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/USER/src/n32h49x_cfg.c b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/USER/src/n32h49x_cfg.c
index f7d06beb45..87a65cae88 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/USER/src/n32h49x_cfg.c
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Cube_Config/USER/src/n32h49x_cfg.c
@@ -77,7 +77,12 @@ bool RCC_Configuration(void)
ClockStatus = RCC_WaitHsiStable();
if (ClockStatus != SUCCESS) return false;
- RCC_ConfigPll(RCC_PLL_SRC_HSI,RCC_PLL_PRE_2,RCC_PLL_MUL_60,RCC_PLLOUT_DIV_1);
+ RCC_ConfigHse(RCC_HSE_ENABLE);
+ /* Wait till HSE is ready */
+ ClockStatus = RCC_WaitHseStable();
+ if (ClockStatus != SUCCESS) return false;
+
+ RCC_ConfigPll(RCC_PLL_SRC_HSE_DIV2,RCC_PLL_PRE_2,RCC_PLL_MUL_60,RCC_PLLOUT_DIV_1);
/* Enable PLL */
RCC_EnablePll(ENABLE);
/* Wait till PLL is ready */
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Kconfig b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Kconfig
index 5d70700412..aa5e67a533 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Kconfig
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/Kconfig
@@ -2,6 +2,129 @@ menu "Hardware Drivers Config"
menu "Onboard Peripheral Drivers"
+ menuconfig BSP_USING_ETH
+ bool "Enable Ethernet"
+ default n
+ select RT_USING_LWIP
+ if BSP_USING_ETH
+ choice BSP_ETH_INTERFACE_SEL
+ prompt "Select Media Interface"
+ default ETH_INTERFACE_USING_RMII
+
+ config ETH_INTERFACE_USING_MII
+ bool "MII"
+
+ config ETH_INTERFACE_USING_RMII
+ bool "RMII"
+ endchoice
+
+ choice BSP_ETH_PHY_SEL
+ prompt "Select PHY Chip"
+ default PHY_USING_DM9162EP
+
+ config PHY_USING_DM9162EP
+ bool "DM9162EP (10M/100M, MII/RMII)"
+
+ config PHY_USING_LAN8720A
+ bool "LAN8720A (10M/100M, MII/RMII)"
+ endchoice
+
+ config BSP_ETH_USING_HW_CHECKSUM
+ bool "Enable Hardware Checksum"
+ select RT_LWIP_USING_HW_CHECKSUM
+ default n
+
+ config PHY_USING_INTERRUPT_MODE
+ bool "Enable PHY Link Change Interrupt Mode"
+ default n
+ if PHY_USING_INTERRUPT_MODE
+ config PHY_INT_PIN
+ int "PHY Interrupt Pin Number"
+ range 0 255
+ default 0
+ endif
+ endif
+
+ menuconfig BSP_USING_SDRAM
+ bool "Enable SDRAM"
+ default n
+ if BSP_USING_SDRAM
+ choice BSP_SDRAM_BANK_SEL
+ prompt "Select SDRAM Bank"
+ default BSP_SDRAM_BANK1
+
+ config BSP_SDRAM_BANK1
+ bool "Select SDRAM Bank1"
+
+ config BSP_SDRAM_BANK2
+ bool "Select SDRAM Bank2"
+ endchoice
+
+ choice BSP_SDRAM_DATA_WIDTH_SEL
+ prompt "Select SDRAM Data Width"
+ default BSP_SDRAM_DATA_WIDTH_32
+
+ config BSP_SDRAM_DATA_WIDTH_8
+ bool "SDRAM Data Width 8-bits"
+
+ config BSP_SDRAM_DATA_WIDTH_16
+ bool "SDRAM Data Width 16-bits"
+
+ config BSP_SDRAM_DATA_WIDTH_32
+ bool "SDRAM Data Width 32-bits"
+ endchoice
+
+ choice BSP_SDRAM_COLUMN_BITS_SEL
+ prompt "Select SDRAM Column Bits"
+ default BSP_SDRAM_COLUMN_BIT_9
+
+ config BSP_SDRAM_COLUMN_BIT_8
+ bool "SDRAM SDRAM Column Bits 8-bits"
+
+ config BSP_SDRAM_COLUMN_BIT_9
+ bool "SDRAM SDRAM Column Bits 9-bits"
+
+ config BSP_SDRAM_COLUMN_BIT_10
+ bool "SDRAM SDRAM Column Bits 10-bits"
+
+ config BSP_SDRAM_COLUMN_BIT_11
+ bool "SDRAM SDRAM Column Bits 11-bits"
+ endchoice
+
+ choice BSP_SDRAM_ROW_BITS_SEL
+ prompt "Select SDRAM Row Bits"
+ default BSP_SDRAM_ROW_BIT_12
+
+ config BSP_SDRAM_ROW_BIT_11
+ bool "SDRAM SDRAM Row Bits 11-bits"
+
+ config BSP_SDRAM_ROW_BIT_12
+ bool "SDRAM SDRAM Row Bits 12-bits"
+
+ config BSP_SDRAM_ROW_BIT_13
+ bool "SDRAM SDRAM Row Bits 13-bits"
+ endchoice
+
+ choice BSP_SDRAM_CAS_LATENCY_SEL
+ prompt "Select SDRAM CAS Latency"
+ default BSP_SDRAM_CAS_LATENCY_3
+
+ config BSP_SDRAM_CAS_LATENCY_1
+ bool "SDRAM SDRAM CAS Latency 1"
+
+ config BSP_SDRAM_CAS_LATENCY_2
+ bool "SDRAM SDRAM CAS Latency 2"
+
+ config BSP_SDRAM_CAS_LATENCY_3
+ bool "SDRAM SDRAM CAS Latency 3"
+ endchoice
+
+ config BSP_SDRAM_SIZE
+ int "SDRAM Size (MBytes)"
+ range 8 256
+ default 32
+ endif
+
endmenu
menu "On-chip Peripheral Drivers"
@@ -58,12 +181,230 @@ menu "On-chip Peripheral Drivers"
depends on BSP_USING_UART3 && RT_SERIAL_USING_DMA
default n
+ config BSP_USING_UART4
+ bool "Enable UART4"
+ default n
+
+ config BSP_UART4_RX_USING_DMA
+ bool "Enable UART4 RX DMA"
+ depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART4_TX_USING_DMA
+ bool "Enable UART4 TX DMA"
+ depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART5
+ bool "Enable UART5"
+ default n
+
+ config BSP_UART5_RX_USING_DMA
+ bool "Enable UART5 RX DMA"
+ depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART5_TX_USING_DMA
+ bool "Enable UART5 TX DMA"
+ depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART6
+ bool "Enable UART6"
+ default n
+
+ config BSP_UART6_RX_USING_DMA
+ bool "Enable UART6 RX DMA"
+ depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART6_TX_USING_DMA
+ bool "Enable UART6 TX DMA"
+ depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART7
+ bool "Enable UART7"
+ default n
+
+ config BSP_UART7_RX_USING_DMA
+ bool "Enable UART7 RX DMA"
+ depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART7_TX_USING_DMA
+ bool "Enable UART7 TX DMA"
+ depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART8
+ bool "Enable UART8"
+ default n
+
+ config BSP_UART8_RX_USING_DMA
+ bool "Enable UART8 RX DMA"
+ depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART8_TX_USING_DMA
+ bool "Enable UART8 TX DMA"
+ depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART9
+ bool "Enable UART9"
+ default n
+
+ config BSP_UART9_RX_USING_DMA
+ bool "Enable UART9 RX DMA"
+ depends on BSP_USING_UART9 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART9_TX_USING_DMA
+ bool "Enable UART9 TX DMA"
+ depends on BSP_USING_UART9 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART10
+ bool "Enable UART10"
+ default n
+
+ config BSP_UART10_RX_USING_DMA
+ bool "Enable UART10 RX DMA"
+ depends on BSP_USING_UART10 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART10_TX_USING_DMA
+ bool "Enable UART10 TX DMA"
+ depends on BSP_USING_UART10 && RT_SERIAL_USING_DMA
+ default n
+
+ endif
+
+ menuconfig BSP_USING_SPI
+ bool "Enable SPI BUS"
+ default n
+ select RT_USING_SPI
+ if BSP_USING_SPI
+ config BSP_USING_SPI1
+ bool "Enable SPI1 BUS"
+ default n
+
+ config BSP_SPI1_TX_USING_DMA
+ bool "Enable SPI1 TX DMA"
+ depends on BSP_USING_SPI1
+ default n
+
+ config BSP_SPI1_RX_USING_DMA
+ bool "Enable SPI1 RX DMA"
+ depends on BSP_USING_SPI1
+ select BSP_SPI1_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI2
+ bool "Enable SPI2 BUS"
+ default n
+
+ config BSP_SPI2_TX_USING_DMA
+ bool "Enable SPI2 TX DMA"
+ depends on BSP_USING_SPI2
+ default n
+
+ config BSP_SPI2_RX_USING_DMA
+ bool "Enable SPI2 RX DMA"
+ depends on BSP_USING_SPI2
+ select BSP_SPI2_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI3
+ bool "Enable SPI3 BUS"
+ default n
+
+ config BSP_SPI3_TX_USING_DMA
+ bool "Enable SPI3 TX DMA"
+ depends on BSP_USING_SPI3
+ default n
+
+ config BSP_SPI3_RX_USING_DMA
+ bool "Enable SPI3 RX DMA"
+ depends on BSP_USING_SPI3
+ select BSP_SPI3_TX_USING_DMA
+ default n
+
endif
config BSP_USING_ON_CHIP_FLASH
bool "Enable on-chip FLASH"
default n
+ menuconfig BSP_USING_QSPI
+ bool "Enable QSPI (XSPI) BUS"
+ default n
+ select RT_USING_QSPI
+ select RT_USING_SPI
+
+ menuconfig BSP_USING_HARD_I2C
+ bool "Enable Hard I2C BUS"
+ default n
+ select RT_USING_I2C
+ if BSP_USING_HARD_I2C
+ config BSP_USING_HARD_I2C1
+ bool "Enable I2C1 BUS"
+ default n
+
+ config BSP_I2C1_RX_USING_DMA
+ bool "Enable I2C1 RX DMA"
+ depends on BSP_USING_HARD_I2C1
+ default n
+
+ config BSP_I2C1_TX_USING_DMA
+ bool "Enable i2c1 TX DMA"
+ depends on BSP_USING_HARD_I2C1
+ default n
+
+ config BSP_USING_HARD_I2C2
+ bool "Enable I2C2 BUS"
+ default n
+
+ config BSP_I2C2_RX_USING_DMA
+ bool "Enable I2C2 RX DMA"
+ depends on BSP_USING_HARD_I2C2
+ default n
+
+ config BSP_I2C2_TX_USING_DMA
+ bool "Enable i2c2 TX DMA"
+ depends on BSP_USING_HARD_I2C2
+ default n
+
+ config BSP_USING_HARD_I2C3
+ bool "Enable I2C3 BUS"
+ default n
+
+ config BSP_I2C3_RX_USING_DMA
+ bool "Enable I2C3 RX DMA"
+ depends on BSP_USING_HARD_I2C3
+ default n
+
+ config BSP_I2C3_TX_USING_DMA
+ bool "Enable i2c3 TX DMA"
+ depends on BSP_USING_HARD_I2C3
+ default n
+
+ config BSP_USING_HARD_I2C4
+ bool "Enable I2C4 BUS"
+ default n
+
+ config BSP_I2C4_RX_USING_DMA
+ bool "Enable I2C4 RX DMA"
+ depends on BSP_USING_HARD_I2C4
+ default n
+
+ config BSP_I2C4_TX_USING_DMA
+ bool "Enable i2c4 TX DMA"
+ depends on BSP_USING_HARD_I2C4
+ default n
+ endif
+
menuconfig BSP_USING_ONCHIP_RTC
bool "Enable RTC"
select RT_USING_RTC
@@ -81,6 +422,29 @@ menu "On-chip Peripheral Drivers"
endchoice
endif
+ menuconfig BSP_USING_ADC
+ bool "Enable ADC"
+ default n
+ select RT_USING_ADC
+ if BSP_USING_ADC
+ config BSP_USING_ADC1
+ bool "Enable ADC1"
+ default n
+
+ config BSP_USING_ADC2
+ bool "Enable ADC2"
+ default n
+
+ config BSP_USING_ADC3
+ bool "Enable ADC3"
+ default n
+ endif
+
+ config BSP_USING_WDT
+ bool "Enable Watchdog Timer"
+ select RT_USING_WDT
+ default n
+
menuconfig BSP_USING_FDCAN
bool "Enable FDCAN (CAN FD)"
default n
@@ -383,6 +747,82 @@ menu "On-chip Peripheral Drivers"
endif
endif
+ menuconfig BSP_USING_DAC
+ bool "Enable DAC"
+ default n
+ select RT_USING_DAC
+ if BSP_USING_DAC
+ config BSP_USING_DAC1
+ bool "Enable DAC1"
+ default n
+
+ config BSP_USING_DAC2
+ bool "Enable DAC2"
+ default n
+ endif
+
+ menuconfig BSP_USING_NAND
+ bool "Enable Nand"
+ default n
+ select RT_USING_MTD_NAND
+ if BSP_USING_NAND
+ choice BSP_NAND_BANK_SEL
+ prompt "Select Bank"
+ default BSP_USING_NAND_BANK3
+
+ config BSP_USING_NAND_BANK2
+ bool "USING FEMC NAND BANK2"
+
+ config BSP_USING_NAND_BANK3
+ bool "USING FEMC NAND BANK3"
+ endchoice
+
+ choice BSP_NAND_BUS_WIDTH_SEL
+ prompt "Select Nand Bus Width"
+ default BSP_USING_NAND_BUS_WIDTH_8B
+
+ config BSP_USING_NAND_BUS_WIDTH_8B
+ bool "USING FEMC NAND BUS WIDTH 8BIT"
+
+ config BSP_USING_NAND_BUS_WIDTH_16B
+ bool "USING FEMC NAND BUS WIDTH 16BIT"
+ endchoice
+
+ config BSP_NAND_PAGE_SIZE
+ int "Page Size (bytes)"
+ default 2048
+ help
+ NAND flash page size in bytes, typically 2048 or 4096.
+
+ config BSP_NAND_OOB_SIZE
+ int "OOB (Spare Area) Size (bytes)"
+ default 64
+ help
+ NAND flash spare area size per page, typically 64 or 128.
+
+ config BSP_NAND_PAGES_PER_BLOCK
+ int "Pages Per Block"
+ default 64
+ help
+ Number of pages per erase block, typically 64 or 128.
+
+ config BSP_NAND_BLOCK_COUNT
+ int "Total Block Count"
+ default 1024
+ help
+ Total number of blocks in the NAND flash chip.
+
+ config BSP_NAND_PLANE_NUM
+ int "Plane Number"
+ default 1
+ help
+ Number of planes in the NAND flash chip, typically 1 or 2.
+ endif
+
+ config BSP_USING_SDIO
+ bool "Enable SDIO"
+ default n
+
source "$BSP_DIR/../libraries/N32_Drivers/drivers/Kconfig"
endmenu
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/SConscript b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/SConscript
index 39fd3e6cfb..1dbaccf266 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/SConscript
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/SConscript
@@ -11,8 +11,11 @@ Cube_Config/USER/src/n32h49x_cfg.c
path = [cwd]
path += [os.path.join(cwd, 'Cube_Config', 'USER', 'inc')]
+path += [os.path.join(cwd, 'ports')]
-CPPDEFINES = ['N32H49x', 'CORE_CM4']
+# Capital X is intentional: N32H49X is the family marker used by the
+# N32H4x USB fsdev port.
+CPPDEFINES = ['N32H49X', 'CORE_CM4']
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/board.h b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/board.h
index 8ec386dfa5..9053fa7f81 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/board.h
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/board.h
@@ -15,10 +15,12 @@
#include "n32h49x_cfg.h"
#include "n32h49x_exti.h"
#include "misc.h"
+#include "n32h49x_i2c.h"
#include "n32h49x_dma.h"
#include "n32h49x_pwr.h"
#include "n32h49x_dbg.h"
#include "n32h49x_flash.h"
+#include "n32h49x_spi.h"
#include "drv_common.h"
#include "drv_gpio.h"
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/SConscript b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/SConscript
index 1948a8d10a..6b1d350978 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/SConscript
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/SConscript
@@ -7,7 +7,11 @@ cwd = GetCurrentDir()
# add general drivers
src = []
path = [cwd]
-
+if GetDepend(['BSP_USING_NAND']):
+ src += Glob('femc_timing.c')
+
+if GetDepend(['BSP_USING_ETH']):
+ src += Glob('phy_reset.c')
CPPDEFINES = ['']
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.c b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.c
new file mode 100644
index 0000000000..1a616eecb4
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-25 ox-horse first version
+ */
+
+#include "femc_timing.h"
+
+#ifdef BSP_USING_NAND
+
+/*
+ * FEMC NAND timing configuration (N32H49x).
+ *
+ * Timing values are in HCLK cycles, taken from the Nsing FEMC Nand_Flash
+ * demo (FEMC_Nand_Init): SET=4, WAIT=6, HOLD=5, HIZ=5,
+ * TCLR/TAR = CLE/ALE delay of 1 HCLK.
+ *
+ * Actual time (ns) = value * HCLK_period (ns). When porting to a different
+ * system clock, recalculate HCLK period from RCC_Configuration() and adjust
+ * all values below to satisfy the NAND datasheet timing.
+ *
+ * Registers written by FEMC_InitNand():
+ * FEMC_NCTRLx <- WaitFeatureEnable | MemDataWidth | EccEnable |
+ * EccPageSize | TCLRSetTime | TARSetTime
+ * FEMC_NCMEMTMx <- CommSpaceTimingStruct (timing)
+ * FEMC_NATTMEMTMx <- AttrSpaceTimingStruct (timing)
+ */
+void FEMC_Nand_Timing_Config(FEMC_NandInitType *nandInit,
+ FEMC_NandTimingInitType *timing)
+{
+ /* Address setup time: 4 HCLK */
+ timing->SetTime = FEMC_NAND_SETUP_TIME(0x4);
+ /* Command assert width: 6 HCLK */
+ timing->WaitSetTime = FEMC_NAND_WAIT_TIME(0x6);
+ /* Address/data hold time: 5 HCLK */
+ timing->HoldSetTime = FEMC_NAND_HOLD_TIME(0x5);
+ /* Data bus HiZ time: 5 HCLK */
+ timing->HiZSetTime = FEMC_NAND_HIZ_TIME(0x5);
+
+ nandInit->CommSpaceTimingStruct = timing;
+ nandInit->AttrSpaceTimingStruct = timing;
+
+ /* CLE to RE delay (TCLR): 1 HCLK */
+ nandInit->TCLRSetTime = FEMC_NAND_CLE_DELAY_1HCLK;
+ /* ALE to RE delay (TAR): 1 HCLK */
+ nandInit->TARSetTime = FEMC_NAND_ALE_DELAY_1HCLK;
+}
+
+#endif /* BSP_USING_NAND */
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.h b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.h
new file mode 100644
index 0000000000..09e4b6da7a
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/femc_timing.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-25 ox-horse first version
+ */
+
+#ifndef __FEMC_TIMING_H__
+#define __FEMC_TIMING_H__
+
+#include "board.h"
+
+/*
+ * Configure FEMC NAND timing parameters (N32H49x).
+ *
+ * This fills the timing-related fields of the NAND init structures:
+ * - timing: SET/WAIT/HOLD/HIZ (then linked to nandInit's
+ * CommSpaceTimingStruct / AttrSpaceTimingStruct)
+ * - nandInit: TCLRSetTime / TARSetTime (CLE/ALE to RE delay)
+ *
+ * @note structures are of type FEMC_NandInitType / FEMC_NandTimingInitType
+ * (N32H49x SDK), which differ from N32H7xx FEMC_TimingInitType.
+ */
+void FEMC_Nand_Timing_Config(FEMC_NandInitType *nandInit,
+ FEMC_NandTimingInitType *timing);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FEMC_TIMING_H__ */
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/phy_reset.c b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/phy_reset.c
new file mode 100644
index 0000000000..3230c65234
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/phy_reset.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-15 ox-horse first version
+ */
+
+#include <board.h>
+#include <drv_gpio.h>
+
+#define RESET_IO GET_PIN(D, 3)
+
+void phy_reset(void)
+{
+ rt_pin_write(RESET_IO, PIN_LOW);
+ rt_thread_mdelay(50);
+ rt_pin_write(RESET_IO, PIN_HIGH);
+}
+
+int phy_init(void)
+{
+ rt_pin_mode(RESET_IO, PIN_MODE_OUTPUT);
+ rt_pin_write(RESET_IO, PIN_HIGH);
+ return RT_EOK;
+}
+INIT_BOARD_EXPORT(phy_init);
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/usb_config.h b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/usb_config.h
new file mode 100644
index 0000000000..59a58fb3ea
--- /dev/null
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/board/ports/usb_config.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-08-28 ox-horse first version
+ */
+
+#ifndef CHERRYUSB_CONFIG_H
+#define CHERRYUSB_CONFIG_H
+
+/* ================ USB common Configuration ================ */
+
+#ifdef __RTTHREAD__
+#include <rtthread.h>
+
+#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
+#else
+#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
+#endif
+
+#ifndef CONFIG_USB_DBG_LEVEL
+#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
+#endif
+
+/* Enable print with color */
+#define CONFIG_USB_PRINTF_COLOR_ENABLE
+
+/* N32H49x is a Cortex-M4 without cache, so no dcache or dma alignment
+ * is required, and no noncacheable section is needed. */
+#define CONFIG_USB_ALIGN_SIZE 4
+
+#define USB_NOCACHE_RAM_SECTION
+
+/* use usb_memcpy default for high performance but cost more flash memory.
+ * And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
+*/
+// #define CONFIG_USB_MEMCPY_DISABLE
+
+/* ================= USB Device Stack Configuration ================ */
+
+/* Ep0 in and out transfer buffer */
+#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
+#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
+#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512
+#endif
+
+#ifndef CONFIG_USBDEV_MAX_BUS
+#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
+#endif
+
+#ifndef CONFIG_USBDEV_EP_NUM
+#define CONFIG_USBDEV_EP_NUM 8
+#endif
+
+/* ================ USB Device Port Configuration ================*/
+
+/* FSDEV port (Synopsys USBFS) PMA access mode. The N32H4x USBFS
+ * (usb_fsdev_reg.h) re-arranges the register map but keeps the buffer
+ * descriptor table layout that matches the ST macro addressing with
+ * PMA_ACCESS=2, which is what usb_dc_fsdev.c requires. */
+#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2
+
+#endif
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/project.ewp b/bsp/n32/n32hxxx/n32h497zgl7-evb/project.ewp
index e82b6e95c4..a0d60cde22 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/project.ewp
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/project.ewp
@@ -225,6 +225,7 @@
<name>CCDefines</name>
<state />
<state>N32H49x</state>
+ <state>N32H49X</state>
<state>CORE_CM4</state>
<state>USE_STDPERIPH_DRIVER</state>
<state>__RTTHREAD__</state>
@@ -364,7 +365,6 @@
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\common</state>
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\cortex-m4</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\include</state>
- <state>$PROJ_DIR$\..\..\..\..\components\drivers\phy</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\smp_call</state>
<state>$PROJ_DIR$\board</state>
<state>$PROJ_DIR$\board\Cube_Config\USER\inc</state>
@@ -384,6 +384,7 @@
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\ipc</state>
<state>$PROJ_DIR$\packages\n32h49x_std_driver-latest\n32h49x_std_periph_driver\inc</state>
<state>$PROJ_DIR$\packages\n32h49x_cmsis_driver-latest\device</state>
+ <state>$PROJ_DIR$\applications\test_file</state>
<state>$PROJ_DIR$\..\..\..\..\components\net\utest</state>
</option>
<option>
@@ -1316,6 +1317,7 @@
<name>CCDefines</name>
<state />
<state>N32H49x</state>
+ <state>N32H49X</state>
<state>CORE_CM4</state>
<state>USE_STDPERIPH_DRIVER</state>
<state>__RTTHREAD__</state>
@@ -1455,7 +1457,6 @@
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\common</state>
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\cortex-m4</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\include</state>
- <state>$PROJ_DIR$\..\..\..\..\components\drivers\phy</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\smp_call</state>
<state>$PROJ_DIR$\board</state>
<state>$PROJ_DIR$\board\Cube_Config\USER\inc</state>
@@ -1475,6 +1476,7 @@
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\ipc</state>
<state>$PROJ_DIR$\packages\n32h49x_std_driver-latest\n32h49x_std_periph_driver\inc</state>
<state>$PROJ_DIR$\packages\n32h49x_cmsis_driver-latest\device</state>
+ <state>$PROJ_DIR$\applications\test_file</state>
<state>$PROJ_DIR$\..\..\..\..\components\net\utest</state>
</option>
<option>
@@ -2308,7 +2310,7 @@
<name>$PROJ_DIR$\..\..\..\..\src\kservice.c</name>
</file>
<file>
- <name>$PROJ_DIR$\..\..\..\..\src\memheap.c</name>
+ <name>$PROJ_DIR$\..\..\..\..\src\mem.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\src\mempool.c</name>
@@ -2432,6 +2434,9 @@
</file>
</group>
<group>
+ <name>test_file</name>
+ </group>
+ <group>
<name>utc_UTest</name>
</group>
<group>
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvoptx b/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvoptx
index a3c52beefe..201379c6bd 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvoptx
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvoptx
@@ -647,8 +647,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\memheap.c</PathWithFileName>
- <FilenameWithoutPath>memheap.c</FilenameWithoutPath>
+ <PathWithFileName>..\..\..\..\src\mem.c</PathWithFileName>
+ <FilenameWithoutPath>mem.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvprojx b/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvprojx
index 6af6d28bb0..700a12f4fa 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvprojx
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/project.uvprojx
@@ -337,9 +337,9 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
- <Define>N32H49x, __CLK_TCK=RT_TICK_PER_SECOND, RT_USING_LIBC, __STDC_LIMIT_MACROS, CORE_CM4, __RTTHREAD__, RT_USING_ARMLIBC, USE_STDPERIPH_DRIVER</Define>
+ <Define>USE_STDPERIPH_DRIVER, N32H49X, __STDC_LIMIT_MACROS, __CLK_TCK=RT_TICK_PER_SECOND, RT_USING_LIBC, CORE_CM4, RT_USING_ARMLIBC, N32H49x, __RTTHREAD__</Define>
<Undefine></Undefine>
- <IncludePath>..\libraries\N32_Drivers\drivers\config;..\..\..\..\libcpu\arm\cortex-m4;packages\CMSIS-Core-latest\Include;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\smp_call;..\..\..\..\components\finsh;board\Cube_Config\USER\inc;..\..\..\..\components\libc\posix\ipc;..\libraries\N32_Drivers;..\..\..\..\libcpu\arm\common;..\..\..\..\components\net\utest;..\libraries\N32_Drivers\drivers;board\ports;packages\n32h49x_std_driver-latest\n32h49x_std_periph_driver\inc;..\..\..\..\components\drivers\include;.;..\..\..\..\components\libc\posix\io\poll;..\..\..\..\components\drivers\include;board;packages\n32h49x_cmsis_driver-latest\device;..\..\..\..\components\libc\posix\io\epoll;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\..\components\libc\compilers\common\include;..\..\..\..\include;..\..\..\..\components\libc\posix\io\eventfd;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\extension;applications</IncludePath>
+ <IncludePath>..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\include;board\ports;..\..\..\..\components\finsh;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\posix\io\poll;board\Cube_Config\USER\inc;board;..\..\..\..\libcpu\arm\common;..\..\..\..\components\drivers\smp_call;..\..\..\..\components\libc\compilers\common\include;packages\n32h49x_std_driver-latest\n32h49x_std_periph_driver\inc;applications;.;..\..\..\..\components\libc\compilers\common\extension;packages\CMSIS-Core-latest\Include;..\libraries\N32_Drivers\drivers;..\..\..\..\components\net\utest;..\libraries\N32_Drivers;..\..\..\..\components\libc\posix\io\eventfd;packages\n32h49x_cmsis_driver-latest\device;..\..\..\..\components\drivers\include;..\libraries\N32_Drivers\drivers\config;..\..\..\..\include;..\..\..\..\components\libc\posix\io\epoll;..\..\..\..\libcpu\arm\cortex-m4;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\posix\ipc</IncludePath>
</VariousControls>
</Cads>
<Aads>
@@ -1604,9 +1604,9 @@
</FileOption>
</File>
<File>
- <FileName>memheap.c</FileName>
+ <FileName>mem.c</FileName>
<FileType>1</FileType>
- <FilePath>..\..\..\..\src\memheap.c</FilePath>
+ <FilePath>..\..\..\..\src\mem.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
diff --git a/bsp/n32/n32hxxx/n32h497zgl7-evb/rtconfig.h b/bsp/n32/n32hxxx/n32h497zgl7-evb/rtconfig.h
index 4748d2763b..9784995611 100644
--- a/bsp/n32/n32hxxx/n32h497zgl7-evb/rtconfig.h
+++ b/bsp/n32/n32hxxx/n32h497zgl7-evb/rtconfig.h
@@ -96,10 +96,8 @@
/* Memory Management */
#define RT_USING_MEMPOOL
-#define RT_USING_MEMHEAP
-#define RT_MEMHEAP_FAST_MODE
-#define RT_USING_MEMHEAP_AS_HEAP
-#define RT_USING_MEMHEAP_AUTO_BINDING
+#define RT_USING_SMALL_MEM
+#define RT_USING_SMALL_MEM_AS_HEAP
#define RT_USING_HEAP
/* end of Memory Management */
#define RT_USING_DEVICE
@@ -107,7 +105,7 @@
#define RT_CONSOLEBUF_SIZE 512
#define RT_CONSOLE_DEVICE_NAME "uart1"
#define RT_USING_CONSOLE_OUTPUT_CTL
-#define RT_VER_NUM 0x50300
+#define RT_VER_NUM 0x50301
#define RT_BACKTRACE_LEVEL_MAX_NR 32
/* end of RT-Thread Kernel */
#define RT_USING_HW_ATOMIC
@@ -433,6 +431,8 @@
/* Onboard Peripheral Drivers */
+/* end of Onboard Peripheral Drivers */
+
/* On-chip Peripheral Drivers */
#define BSP_USING_GPIO
diff --git a/bsp/n32/n32hxxx/n32h760zil7-stb/.config b/bsp/n32/n32hxxx/n32h760zil7-stb/.config
index d13e20053d..0ea04194a0 100644
--- a/bsp/n32/n32hxxx/n32h760zil7-stb/.config
+++ b/bsp/n32/n32hxxx/n32h760zil7-stb/.config
@@ -180,7 +180,7 @@ CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=512
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y
-CONFIG_RT_VER_NUM=0x50300
+CONFIG_RT_VER_NUM=0x50301
# CONFIG_RT_USING_STDC_ATOMIC is not set
CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
# end of RT-Thread Kernel
@@ -255,7 +255,7 @@ CONFIG_RT_UNAMED_PIPE_NUMBER=64
CONFIG_RT_USING_SERIAL=y
CONFIG_RT_USING_SERIAL_V1=y
# CONFIG_RT_USING_SERIAL_V2 is not set
-CONFIG_RT_SERIAL_USING_DMA=y
+# CONFIG_RT_SERIAL_USING_DMA is not set
CONFIG_RT_SERIAL_RB_BUFSZ=512
# CONFIG_RT_USING_SERIAL_BYPASS is not set
# CONFIG_RT_USING_CAN is not set
@@ -597,6 +597,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
# CONFIG_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_PERSIMMON is not set
# CONFIG_PKG_USING_3GPP_AMRNB is not set
+# CONFIG_PKG_USING_LITETYPE is not set
# end of multimedia packages
#
@@ -1045,6 +1046,7 @@ CONFIG_PKG_N32H7XX_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_QMI8658 is not set
# CONFIG_PKG_USING_ICM20948 is not set
# CONFIG_PKG_USING_SCD4X is not set
+# CONFIG_PKG_USING_BMI270 is not set
# end of sensors drivers
#
@@ -1099,6 +1101,7 @@ CONFIG_PKG_N32H7XX_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_WK2124 is not set
# CONFIG_PKG_USING_LY68L6400 is not set
# CONFIG_PKG_USING_DM9051 is not set
+# CONFIG_PKG_USING_CH390 is not set
# CONFIG_PKG_USING_SSD1306 is not set
# CONFIG_PKG_USING_QKEY is not set
# CONFIG_PKG_USING_RS485 is not set
@@ -1167,6 +1170,9 @@ CONFIG_PKG_N32H7XX_CMSIS_DRIVER_VER="latest"
# CONFIG_PKG_USING_NAXOS is not set
# CONFIG_PKG_USING_R_TINYMAIX is not set
# CONFIG_PKG_USING_LLMCHAT is not set
+# CONFIG_PKG_USING_LIME_TM is not set
+# CONFIG_PKG_USING_AIFES is not set
+# CONFIG_PKG_USING_AGENT is not set
# end of AI packages
#
@@ -1512,10 +1518,20 @@ CONFIG_SOC_SERIES_N32H7xx=y
CONFIG_BSP_USING_GPIO=y
CONFIG_BSP_USING_UART=y
CONFIG_BSP_USING_UART1=y
-# CONFIG_BSP_UART1_RX_USING_DMA is not set
-# CONFIG_BSP_UART1_TX_USING_DMA is not set
# CONFIG_BSP_USING_UART2 is not set
# CONFIG_BSP_USING_UART3 is not set
+# CONFIG_BSP_USING_UART4 is not set
+# CONFIG_BSP_USING_UART5 is not set
+# CONFIG_BSP_USING_UART6 is not set
+# CONFIG_BSP_USING_UART7 is not set
+# CONFIG_BSP_USING_UART8 is not set
+# CONFIG_BSP_USING_UART9 is not set
+# CONFIG_BSP_USING_UART10 is not set
+# CONFIG_BSP_USING_UART11 is not set
+# CONFIG_BSP_USING_UART12 is not set
+# CONFIG_BSP_USING_UART13 is not set
+# CONFIG_BSP_USING_UART14 is not set
+# CONFIG_BSP_USING_UART15 is not set
# CONFIG_BSP_USING_SPI is not set
# CONFIG_BSP_USING_SOFT_I2C is not set
# CONFIG_BSP_USING_HARD_I2C is not set
diff --git a/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/Cube.ntfx b/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/Cube.ntfx
index f79a41c17e..bdc9c46427 100644
--- a/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/Cube.ntfx
+++ b/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/Cube.ntfx
Binary files differ
diff --git a/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/USER/src/n32h7xx_cfg.c b/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/USER/src/n32h7xx_cfg.c
index b248af7d7e..30f9fc2ca5 100644
--- a/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/USER/src/n32h7xx_cfg.c
+++ b/bsp/n32/n32hxxx/n32h760zil7-stb/board/Cube_Config/USER/src/n32h7xx_cfg.c
@@ -183,15 +183,8 @@ bool GPIO_Configuration(void)
/*********Initialize USART1 GPIO function *********/
- /********PA10->USART1.RX********/
/********PA9->USART1.TX********/
- /*Initialize input GPIO */
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
- GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
- GPIO_InitStructure.GPIO_Alternate = GPIO_AF5;
- GPIO_InitStructure.Pin = GPIO_PIN_10;
- GPIO_InitPeripheral(GPIOA,&GPIO_InitStructure);
-
+ /********PA10->USART1.RX********/
/*Initialize AF_PP GPIO */
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
@@ -201,6 +194,13 @@ bool GPIO_Configuration(void)
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitPeripheral(GPIOA,&GPIO_InitStructure);
+ /*Initialize input GPIO */
+ GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
+ GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
+ GPIO_InitStructure.GPIO_Alternate = GPIO_AF5;
+ GPIO_InitStructure.Pin = GPIO_PIN_10;
+ GPIO_InitPeripheral(GPIOA,&GPIO_InitStructure);
+
/* NTFx CODE END */
return true;
diff --git a/bsp/n32/n32hxxx/n32h760zil7-stb/board/Kconfig b/bsp/n32/n32hxxx/n32h760zil7-stb/board/Kconfig
index 9e5790c972..2a76fec34b 100644
--- a/bsp/n32/n32hxxx/n32h760zil7-stb/board/Kconfig
+++ b/bsp/n32/n32hxxx/n32h760zil7-stb/board/Kconfig
@@ -286,6 +286,174 @@ menu "On-chip Peripheral Drivers"
depends on BSP_USING_UART3 && RT_SERIAL_USING_DMA
default n
+ config BSP_USING_UART4
+ bool "Enable UART4"
+ default n
+
+ config BSP_UART4_RX_USING_DMA
+ bool "Enable UART4 RX DMA"
+ depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART4_TX_USING_DMA
+ bool "Enable UART4 TX DMA"
+ depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART5
+ bool "Enable UART5"
+ default n
+
+ config BSP_UART5_RX_USING_DMA
+ bool "Enable UART5 RX DMA"
+ depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART5_TX_USING_DMA
+ bool "Enable UART5 TX DMA"
+ depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART6
+ bool "Enable UART6"
+ default n
+
+ config BSP_UART6_RX_USING_DMA
+ bool "Enable UART6 RX DMA"
+ depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART6_TX_USING_DMA
+ bool "Enable UART6 TX DMA"
+ depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART7
+ bool "Enable UART7"
+ default n
+
+ config BSP_UART7_RX_USING_DMA
+ bool "Enable UART7 RX DMA"
+ depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART7_TX_USING_DMA
+ bool "Enable UART7 TX DMA"
+ depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART8
+ bool "Enable UART8"
+ default n
+
+ config BSP_UART8_RX_USING_DMA
+ bool "Enable UART8 RX DMA"
+ depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART8_TX_USING_DMA
+ bool "Enable UART8 TX DMA"
+ depends on BSP_USING_UART8 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART9
+ bool "Enable UART9"
+ default n
+
+ config BSP_UART9_RX_USING_DMA
+ bool "Enable UART9 RX DMA"
+ depends on BSP_USING_UART9 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART9_TX_USING_DMA
+ bool "Enable UART9 TX DMA"
+ depends on BSP_USING_UART9 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART10
+ bool "Enable UART10"
+ default n
+
+ config BSP_UART10_RX_USING_DMA
+ bool "Enable UART10 RX DMA"
+ depends on BSP_USING_UART10 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART10_TX_USING_DMA
+ bool "Enable UART10 TX DMA"
+ depends on BSP_USING_UART10 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART11
+ bool "Enable UART11"
+ default n
+
+ config BSP_UART11_RX_USING_DMA
+ bool "Enable UART11 RX DMA"
+ depends on BSP_USING_UART11 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART11_TX_USING_DMA
+ bool "Enable UART11 TX DMA"
+ depends on BSP_USING_UART11 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART12
+ bool "Enable UART12"
+ default n
+
+ config BSP_UART12_RX_USING_DMA
+ bool "Enable UART12 RX DMA"
+ depends on BSP_USING_UART12 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART12_TX_USING_DMA
+ bool "Enable UART12 TX DMA"
+ depends on BSP_USING_UART12 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART13
+ bool "Enable UART13"
+ default n
+
+ config BSP_UART13_RX_USING_DMA
+ bool "Enable UART13 RX DMA"
+ depends on BSP_USING_UART13 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART13_TX_USING_DMA
+ bool "Enable UART13 TX DMA"
+ depends on BSP_USING_UART13 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART14
+ bool "Enable UART14"
+ default n
+
+ config BSP_UART14_RX_USING_DMA
+ bool "Enable UART14 RX DMA"
+ depends on BSP_USING_UART14 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART14_TX_USING_DMA
+ bool "Enable UART14 TX DMA"
+ depends on BSP_USING_UART14 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_USING_UART15
+ bool "Enable UART15"
+ default n
+
+ config BSP_UART15_RX_USING_DMA
+ bool "Enable UART15 RX DMA"
+ depends on BSP_USING_UART15 && RT_SERIAL_USING_DMA
+ default n
+
+ config BSP_UART15_TX_USING_DMA
+ bool "Enable UART15 TX DMA"
+ depends on BSP_USING_UART15 && RT_SERIAL_USING_DMA
+ default n
+
endif
menuconfig BSP_USING_SPI
@@ -307,6 +475,96 @@ menu "On-chip Peripheral Drivers"
depends on BSP_USING_SPI1
select BSP_SPI1_TX_USING_DMA
default n
+
+ config BSP_USING_SPI2
+ bool "Enable SPI2 BUS"
+ default n
+
+ config BSP_SPI2_TX_USING_DMA
+ bool "Enable SPI2 TX DMA"
+ depends on BSP_USING_SPI2
+ default n
+
+ config BSP_SPI2_RX_USING_DMA
+ bool "Enable SPI2 RX DMA"
+ depends on BSP_USING_SPI2
+ select BSP_SPI2_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI3
+ bool "Enable SPI3 BUS"
+ default n
+
+ config BSP_SPI3_TX_USING_DMA
+ bool "Enable SPI3 TX DMA"
+ depends on BSP_USING_SPI3
+ default n
+
+ config BSP_SPI3_RX_USING_DMA
+ bool "Enable SPI3 RX DMA"
+ depends on BSP_USING_SPI3
+ select BSP_SPI3_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI4
+ bool "Enable SPI4 BUS"
+ default n
+
+ config BSP_SPI4_TX_USING_DMA
+ bool "Enable SPI4 TX DMA"
+ depends on BSP_USING_SPI4
+ default n
+
+ config BSP_SPI4_RX_USING_DMA
+ bool "Enable SPI4 RX DMA"
+ depends on BSP_USING_SPI4
+ select BSP_SPI4_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI5
+ bool "Enable SPI5 BUS"
+ default n
+
+ config BSP_SPI5_TX_USING_DMA
+ bool "Enable SPI5 TX DMA"
+ depends on BSP_USING_SPI5
+ default n
+
+ config BSP_SPI5_RX_USING_DMA
+ bool "Enable SPI5 RX DMA"
+ depends on BSP_USING_SPI5
+ select BSP_SPI5_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI6
+ bool "Enable SPI6 BUS"
+ default n
+
+ config BSP_SPI6_TX_USING_DMA
+ bool "Enable SPI6 TX DMA"
+ depends on BSP_USING_SPI6
+ default n
+
+ config BSP_SPI6_RX_USING_DMA
+ bool "Enable SPI6 RX DMA"
+ depends on BSP_USING_SPI6
+ select BSP_SPI6_TX_USING_DMA
+ default n
+
+ config BSP_USING_SPI7
+ bool "Enable SPI7 BUS"
+ default n
+
+ config BSP_SPI7_TX_USING_DMA
+ bool "Enable SPI7 TX DMA"
+ depends on BSP_USING_SPI7
+ default n
+
+ config BSP_SPI7_RX_USING_DMA
+ bool "Enable SPI7 RX DMA"
+ depends on BSP_USING_SPI7
+ select BSP_SPI7_TX_USING_DMA
+ default n
endif
menuconfig BSP_USING_SOFT_I2C
diff --git a/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvoptx b/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvoptx
index bb17432120..d4cb02535c 100644
--- a/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvoptx
+++ b/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvoptx
@@ -181,984 +181,4 @@
</TargetOption>
</Target>
- <Group>
- <GroupName>Applications</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>1</GroupNumber>
- <FileNumber>1</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>applications\main.c</PathWithFileName>
- <FilenameWithoutPath>main.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>CPU</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>2</GroupNumber>
- <FileNumber>2</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\libcpu\arm\common\atomic_arm.c</PathWithFileName>
- <FilenameWithoutPath>atomic_arm.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>2</GroupNumber>
- <FileNumber>3</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\libcpu\arm\common\div0.c</PathWithFileName>
- <FilenameWithoutPath>div0.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>2</GroupNumber>
- <FileNumber>4</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\libcpu\arm\common\showmem.c</PathWithFileName>
- <FilenameWithoutPath>showmem.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>2</GroupNumber>
- <FileNumber>5</FileNumber>
- <FileType>2</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\libcpu\arm\cortex-m7\context_rvds.S</PathWithFileName>
- <FilenameWithoutPath>context_rvds.S</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>2</GroupNumber>
- <FileNumber>6</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\libcpu\arm\cortex-m7\cpu_cache.c</PathWithFileName>
- <FilenameWithoutPath>cpu_cache.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>2</GroupNumber>
- <FileNumber>7</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\libcpu\arm\cortex-m7\cpuport.c</PathWithFileName>
- <FilenameWithoutPath>cpuport.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>DeviceDrivers</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>8</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\core\device.c</PathWithFileName>
- <FilenameWithoutPath>device.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>9</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\completion_comm.c</PathWithFileName>
- <FilenameWithoutPath>completion_comm.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>10</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\completion_up.c</PathWithFileName>
- <FilenameWithoutPath>completion_up.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>11</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\condvar.c</PathWithFileName>
- <FilenameWithoutPath>condvar.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>12</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\dataqueue.c</PathWithFileName>
- <FilenameWithoutPath>dataqueue.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>13</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\pipe.c</PathWithFileName>
- <FilenameWithoutPath>pipe.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>14</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\ringblk_buf.c</PathWithFileName>
- <FilenameWithoutPath>ringblk_buf.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>15</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\ringbuffer.c</PathWithFileName>
- <FilenameWithoutPath>ringbuffer.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>16</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\waitqueue.c</PathWithFileName>
- <FilenameWithoutPath>waitqueue.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>17</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\ipc\workqueue.c</PathWithFileName>
- <FilenameWithoutPath>workqueue.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>18</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\pin\dev_pin.c</PathWithFileName>
- <FilenameWithoutPath>dev_pin.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>3</GroupNumber>
- <FileNumber>19</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\drivers\serial\dev_serial.c</PathWithFileName>
- <FilenameWithoutPath>dev_serial.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>Drivers</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>4</GroupNumber>
- <FileNumber>20</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\libraries\N32_Drivers\drivers\drv_gpio.c</PathWithFileName>
- <FilenameWithoutPath>drv_gpio.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>4</GroupNumber>
- <FileNumber>21</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\libraries\N32_Drivers\drivers\drv_usart.c</PathWithFileName>
- <FilenameWithoutPath>drv_usart.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>4</GroupNumber>
- <FileNumber>22</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\libraries\N32_Drivers\drv_common.c</PathWithFileName>
- <FilenameWithoutPath>drv_common.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>4</GroupNumber>
- <FileNumber>23</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>board\Cube_Config\USER\src\n32h7xx_cfg.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_cfg.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>4</GroupNumber>
- <FileNumber>24</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>board\board.c</PathWithFileName>
- <FilenameWithoutPath>board.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>Filesystem</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>5</GroupNumber>
- <FileNumber>25</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\dfs\dfs_v1\filesystems\devfs\devfs.c</PathWithFileName>
- <FilenameWithoutPath>devfs.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>5</GroupNumber>
- <FileNumber>26</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\dfs\dfs_v1\src\dfs.c</PathWithFileName>
- <FilenameWithoutPath>dfs.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>5</GroupNumber>
- <FileNumber>27</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\dfs\dfs_v1\src\dfs_file.c</PathWithFileName>
- <FilenameWithoutPath>dfs_file.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>5</GroupNumber>
- <FileNumber>28</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\dfs\dfs_v1\src\dfs_fs.c</PathWithFileName>
- <FilenameWithoutPath>dfs_fs.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>5</GroupNumber>
- <FileNumber>29</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\dfs\dfs_v1\src\dfs_posix.c</PathWithFileName>
- <FilenameWithoutPath>dfs_posix.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>Finsh</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>6</GroupNumber>
- <FileNumber>30</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\finsh\shell.c</PathWithFileName>
- <FilenameWithoutPath>shell.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>6</GroupNumber>
- <FileNumber>31</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\finsh\msh.c</PathWithFileName>
- <FilenameWithoutPath>msh.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>6</GroupNumber>
- <FileNumber>32</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\finsh\msh_parse.c</PathWithFileName>
- <FilenameWithoutPath>msh_parse.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>6</GroupNumber>
- <FileNumber>33</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\finsh\cmd.c</PathWithFileName>
- <FilenameWithoutPath>cmd.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>6</GroupNumber>
- <FileNumber>34</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\finsh\msh_file.c</PathWithFileName>
- <FilenameWithoutPath>msh_file.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>Kernel</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>35</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\clock.c</PathWithFileName>
- <FilenameWithoutPath>clock.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>36</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\components.c</PathWithFileName>
- <FilenameWithoutPath>components.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>37</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\cpu_up.c</PathWithFileName>
- <FilenameWithoutPath>cpu_up.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>38</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\defunct.c</PathWithFileName>
- <FilenameWithoutPath>defunct.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>39</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\idle.c</PathWithFileName>
- <FilenameWithoutPath>idle.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>40</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\ipc.c</PathWithFileName>
- <FilenameWithoutPath>ipc.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>41</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\irq.c</PathWithFileName>
- <FilenameWithoutPath>irq.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>42</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\kservice.c</PathWithFileName>
- <FilenameWithoutPath>kservice.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>43</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\mem.c</PathWithFileName>
- <FilenameWithoutPath>mem.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>44</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\mempool.c</PathWithFileName>
- <FilenameWithoutPath>mempool.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>45</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\object.c</PathWithFileName>
- <FilenameWithoutPath>object.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>46</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\scheduler_comm.c</PathWithFileName>
- <FilenameWithoutPath>scheduler_comm.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>47</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\scheduler_up.c</PathWithFileName>
- <FilenameWithoutPath>scheduler_up.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>48</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\thread.c</PathWithFileName>
- <FilenameWithoutPath>thread.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>7</GroupNumber>
- <FileNumber>49</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\timer.c</PathWithFileName>
- <FilenameWithoutPath>timer.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>Libc</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>50</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\armlibc\syscall_mem.c</PathWithFileName>
- <FilenameWithoutPath>syscall_mem.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>51</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\armlibc\syscalls.c</PathWithFileName>
- <FilenameWithoutPath>syscalls.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>52</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\common\cctype.c</PathWithFileName>
- <FilenameWithoutPath>cctype.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>53</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\common\cstdlib.c</PathWithFileName>
- <FilenameWithoutPath>cstdlib.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>54</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\common\cstring.c</PathWithFileName>
- <FilenameWithoutPath>cstring.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>55</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\common\ctime.c</PathWithFileName>
- <FilenameWithoutPath>ctime.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>56</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\common\cunistd.c</PathWithFileName>
- <FilenameWithoutPath>cunistd.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>57</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\components\libc\compilers\common\cwchar.c</PathWithFileName>
- <FilenameWithoutPath>cwchar.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>58</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\klibc\kerrno.c</PathWithFileName>
- <FilenameWithoutPath>kerrno.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>59</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\klibc\kstdio.c</PathWithFileName>
- <FilenameWithoutPath>kstdio.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>60</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\klibc\kstring.c</PathWithFileName>
- <FilenameWithoutPath>kstring.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>61</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\klibc\rt_vsnprintf_tiny.c</PathWithFileName>
- <FilenameWithoutPath>rt_vsnprintf_tiny.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>8</GroupNumber>
- <FileNumber>62</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>..\..\..\..\src\klibc\rt_vsscanf.c</PathWithFileName>
- <FilenameWithoutPath>rt_vsscanf.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>Libraries</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>63</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\misc.c</PathWithFileName>
- <FilenameWithoutPath>misc.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>64</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_gpio.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_gpio.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>65</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_mmu.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_mmu.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>66</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_dma.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_dma.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>67</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_dmamux.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_dmamux.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>68</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_pwr.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_pwr.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>69</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_rcc.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_rcc.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>70</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_dbg.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_dbg.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>71</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_exti.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_exti.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>9</GroupNumber>
- <FileNumber>72</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_usart.c</PathWithFileName>
- <FilenameWithoutPath>n32h7xx_usart.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
- <Group>
- <GroupName>Libraries-CMSIS</GroupName>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <cbSel>0</cbSel>
- <RteFlg>0</RteFlg>
- <File>
- <GroupNumber>10</GroupNumber>
- <FileNumber>73</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_cmsis_driver-latest\device\system_n32h7xx.c</PathWithFileName>
- <FilenameWithoutPath>system_n32h7xx.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>10</GroupNumber>
- <FileNumber>74</FileNumber>
- <FileType>2</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_cmsis_driver-latest\device\startup\startup_n32h73x_76x.s</PathWithFileName>
- <FilenameWithoutPath>startup_n32h73x_76x.s</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- <File>
- <GroupNumber>10</GroupNumber>
- <FileNumber>75</FileNumber>
- <FileType>1</FileType>
- <tvExp>0</tvExp>
- <tvExpOptDlg>0</tvExpOptDlg>
- <bDave2>0</bDave2>
- <PathWithFileName>packages\n32h7xx_cmsis_driver-latest\device\soc_mdk.c</PathWithFileName>
- <FilenameWithoutPath>soc_mdk.c</FilenameWithoutPath>
- <RteFlg>0</RteFlg>
- <bShared>0</bShared>
- </File>
- </Group>
-
</ProjectOpt>
diff --git a/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvprojx b/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvprojx
index 91f2256883..cc97c9a67d 100644
--- a/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvprojx
+++ b/bsp/n32/n32hxxx/n32h760zil7-stb/project.uvprojx
@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
-
<SchemaVersion>2.1</SchemaVersion>
-
<Header>### uVision Project, (C) Keil Software</Header>
-
<Targets>
<Target>
<TargetName>rt-thread</TargetName>
@@ -19,28 +16,28 @@
<PackID>Nationstech.N32H7xx_DFP.1.2.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x24000000,0x20000) IROM(0x15000000,0x1E0000) CPUTYPE("Cortex-M7") FPU3(DFPU) CLOCK(12000000) ELITTLE</Cpu>
- <FlashUtilSpec></FlashUtilSpec>
- <StartupFile></StartupFile>
+ <FlashUtilSpec />
+ <StartupFile />
<FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD24000000 -FC8000 -FN1 -FF0N32H76x_2048 -FS015000000 -FL01E0000 -FP0($$Device:N32H760xIx7$Flash\N32H76x_2048.FLM))</FlashDriverDll>
<DeviceId>0</DeviceId>
<RegisterFile>$$Device:N32H760xIx7$firmware\CMSIS\device\N32H76x.h</RegisterFile>
- <MemoryEnv></MemoryEnv>
- <Cmp></Cmp>
- <Asm></Asm>
- <Linker></Linker>
- <OHString></OHString>
- <InfinionOptionDll></InfinionOptionDll>
- <SLE66CMisc></SLE66CMisc>
- <SLE66AMisc></SLE66AMisc>
- <SLE66LinkerMisc></SLE66LinkerMisc>
+ <MemoryEnv />
+ <Cmp />
+ <Asm />
+ <Linker />
+ <OHString />
+ <InfinionOptionDll />
+ <SLE66CMisc />
+ <SLE66AMisc />
+ <SLE66LinkerMisc />
<SFDFile>$$Device:N32H760xIx7$svd\N32H76x.svd</SFDFile>
<bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv>
- <BinPath></BinPath>
- <IncludePath></IncludePath>
- <LibPath></LibPath>
- <RegisterFilePath></RegisterFilePath>
- <DBRegisterFilePath></DBRegisterFilePath>
+ <BinPath />
+ <IncludePath />
+ <LibPath />
+ <RegisterFilePath />
+ <DBRegisterFilePath />
<TargetStatus>
<Error>0</Error>
<ExitCodeStop>0</ExitCodeStop>
@@ -62,8 +59,8 @@
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
- <UserProg1Name></UserProg1Name>
- <UserProg2Name></UserProg2Name>
+ <UserProg1Name />
+ <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
@@ -72,8 +69,8 @@
<BeforeMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
- <UserProg1Name></UserProg1Name>
- <UserProg2Name></UserProg2Name>
+ <UserProg1Name />
+ <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X>
@@ -83,14 +80,14 @@
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>fromelf --bin !L --output rtthread.bin</UserProg1Name>
- <UserProg2Name></UserProg2Name>
+ <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X>
</AfterMake>
<SelectedForBatchBuild>0</SelectedForBatchBuild>
- <SVCSIdString></SVCSIdString>
+ <SVCSIdString />
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
@@ -104,8 +101,8 @@
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
+ <CustomArgument />
+ <IncludeLibraryModules />
<ComprImg>1</ComprImg>
</CommonProperty>
<DllOption>
@@ -138,11 +135,11 @@
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
- <Flash3></Flash3>
- <Flash4></Flash4>
- <pFcarmOut></pFcarmOut>
- <pFcarmGrp></pFcarmGrp>
- <pFcArmRoot></pFcArmRoot>
+ <Flash3 />
+ <Flash4 />
+ <pFcarmOut />
+ <pFcarmGrp />
+ <pFcArmRoot />
<FcArmLst>0</FcArmLst>
</Utilities>
<TargetArmAds>
@@ -175,7 +172,7 @@
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M7"</AdsCpuType>
- <RvctDeviceName></RvctDeviceName>
+ <RvctDeviceName />
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
@@ -309,7 +306,7 @@
<Size>0x0</Size>
</OCR_RVCT10>
</OnChipMemories>
- <RvctStartVector></RvctStartVector>
+ <RvctStartVector />
</ArmAdsMisc>
<Cads>
<interw>1</interw>
@@ -336,10 +333,10 @@
<v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls>
- <MiscControls></MiscControls>
- <Define>N32H76x, __DCACHE_PRESENT=1, USING_TCM, __ICACHE_PRESENT=1, USE_STDPERIPH_DRIVER, __STDC_LIMIT_MACROS, __RTTHREAD__, CORE_CM7, __CLK_TCK=RT_TICK_PER_SECOND, RT_USING_ARMLIBC, RT_USING_LIBC</Define>
- <Undefine></Undefine>
- <IncludePath>..\libraries\N32_Drivers\drivers\config;..\..\..\..\components\libc\compilers\common\extension;packages\n32h7xx_cmsis_driver-latest\device;..\..\..\..\components\drivers\include;.;..\..\..\..\components\dfs\dfs_v1\filesystems\devfs;applications;..\..\..\..\components\libc\posix\io\poll;..\..\..\..\components\drivers\include;..\..\..\..\components\dfs\dfs_v1\include;..\libraries\N32_Drivers;packages\CMSIS-Core-latest\Include;..\..\..\..\libcpu\arm\cortex-m7;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\posix\io\epoll;..\..\..\..\components\libc\posix\io\eventfd;board;board\Cube_Config\USER\inc;..\libraries\N32_Drivers\drivers;..\..\..\..\components\drivers\smp_call;..\..\..\..\components\finsh;..\..\..\..\libcpu\arm\common;..\..\..\..\components\net\utest;..\..\..\..\components\libc\posix\ipc;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\include;..\..\..\..\include;..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;board\ports;packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\inc</IncludePath>
+ <MiscControls />
+ <Define>USE_STDPERIPH_DRIVER, __DCACHE_PRESENT=1, __RTTHREAD__, RT_USING_ARMLIBC, N32H76x, USING_TCM, CORE_CM7, __ICACHE_PRESENT=1, RT_USING_LIBC, __STDC_LIMIT_MACROS, __CLK_TCK=RT_TICK_PER_SECOND</Define>
+ <Undefine />
+ <IncludePath>.;applications;applications\test_file;board;board\Cube_Config\USER\inc;board\ports;packages\CMSIS-Core-latest\Include;packages\n32h7xx_cmsis_driver-latest\device;packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\inc;..\..\..\..\include;..\..\..\..\libcpu\arm\common;..\..\..\..\libcpu\arm\cortex-m7;..\..\..\..\components\dfs\dfs_v1\include;..\..\..\..\components\dfs\dfs_v1\filesystems\devfs;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\smp_call;..\..\..\..\components\finsh;..\..\..\..\components\libc\compilers\common\include;..\..\..\..\components\libc\compilers\common\extension;..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\..\components\libc\posix\io\epoll;..\..\..\..\components\libc\posix\io\eventfd;..\..\..\..\components\libc\posix\io\poll;..\..\..\..\components\libc\posix\ipc;..\..\..\..\components\net\utest;..\libraries\N32_Drivers\drivers;..\libraries\N32_Drivers\drivers\config;..\libraries\N32_Drivers</IncludePath>
</VariousControls>
</Cads>
<Aads>
@@ -354,10 +351,10 @@
<useXO>0</useXO>
<ClangAsOpt>4</ClangAsOpt>
<VariousControls>
- <MiscControls></MiscControls>
- <Define></Define>
- <Undefine></Undefine>
- <IncludePath></IncludePath>
+ <MiscControls />
+ <Define />
+ <Undefine />
+ <IncludePath />
</VariousControls>
</Aads>
<LDads>
@@ -369,13 +366,13 @@
<useFile>0</useFile>
<TextAddressRange>0x08000000</TextAddressRange>
<DataAddressRange>0x20000000</DataAddressRange>
- <pXoBase></pXoBase>
+ <pXoBase />
<ScatterFile>.\board\linker_scripts\link.sct</ScatterFile>
- <IncludeLibs></IncludeLibs>
- <IncludeLibsPath></IncludeLibsPath>
+ <IncludeLibs />
+ <IncludeLibsPath />
<Misc>--entry Reset_Handler</Misc>
- <LinkerInputFile></LinkerInputFile>
- <DisabledWarnings></DisabledWarnings>
+ <LinkerInputFile />
+ <DisabledWarnings />
</LDads>
</TargetArmAds>
</TargetOption>
@@ -398,26 +395,36 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\libcpu\arm\common\atomic_arm.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>div0.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\libcpu\arm\common\div0.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>showmem.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\libcpu\arm\common\showmem.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>context_rvds.S</FileName>
<FileType>2</FileType>
<FilePath>..\..\..\..\libcpu\arm\cortex-m7\context_rvds.S</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cpu_cache.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\libcpu\arm\cortex-m7\cpu_cache.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cpuport.c</FileName>
<FileType>1</FileType>
@@ -433,668 +440,222 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\core\device.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>completion_comm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\completion_comm.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>completion_up.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\completion_up.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>condvar.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\condvar.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>dataqueue.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\dataqueue.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>pipe.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\pipe.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>ringblk_buf.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\ringblk_buf.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>ringbuffer.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\ringbuffer.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>waitqueue.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\waitqueue.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>workqueue.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\ipc\workqueue.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>dev_pin.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\pin\dev_pin.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>dev_serial.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\drivers\serial\dev_serial.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_IPC_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
@@ -1110,21 +671,29 @@
<FileType>1</FileType>
<FilePath>..\libraries\N32_Drivers\drivers\drv_gpio.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>drv_usart.c</FileName>
<FileType>1</FileType>
<FilePath>..\libraries\N32_Drivers\drivers\drv_usart.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>drv_common.c</FileName>
<FileType>1</FileType>
<FilePath>..\libraries\N32_Drivers\drv_common.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_cfg.c</FileName>
<FileType>1</FileType>
<FilePath>board\Cube_Config\USER\src\n32h7xx_cfg.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>board.c</FileName>
<FileType>1</FileType>
@@ -1140,276 +709,89 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\components\dfs\dfs_v1\filesystems\devfs\devfs.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> --c99</MiscControls>
<Define> </Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>dfs.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\dfs\dfs_v1\src\dfs.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> --c99</MiscControls>
<Define> </Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>dfs_file.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\dfs\dfs_v1\src\dfs_file.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> --c99</MiscControls>
<Define> </Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>dfs_fs.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\dfs\dfs_v1\src\dfs_fs.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> --c99</MiscControls>
<Define> </Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>dfs_posix.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\dfs\dfs_v1\src\dfs_posix.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> --c99</MiscControls>
<Define> </Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
@@ -1425,21 +807,29 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\shell.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>msh.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\msh.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>msh_parse.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\msh_parse.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cmd.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\cmd.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>msh_file.c</FileName>
<FileType>1</FileType>
@@ -1455,836 +845,279 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\src\clock.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>components.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\components.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cpu_up.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\cpu_up.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>defunct.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\defunct.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>idle.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\idle.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>ipc.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\ipc.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>irq.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\irq.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>kservice.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\kservice.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>mem.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\mem.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>mempool.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\mempool.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>object.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\object.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>scheduler_comm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\scheduler_comm.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>scheduler_up.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\scheduler_up.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>thread.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\thread.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
+ </Files>
+ <Files>
<File>
<FileName>timer.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\timer.c</FilePath>
<FileOption>
- <CommonProperty>
- <UseCPPCompiler>2</UseCPPCompiler>
- <RVCTCodeConst>0</RVCTCodeConst>
- <RVCTZI>0</RVCTZI>
- <RVCTOtherData>0</RVCTOtherData>
- <ModuleSelection>0</ModuleSelection>
- <IncludeInBuild>1</IncludeInBuild>
- <AlwaysBuild>0</AlwaysBuild>
- <GenerateAssemblyFile>0</GenerateAssemblyFile>
- <AssembleAssemblyFile>0</AssembleAssemblyFile>
- <PublicsOnly>0</PublicsOnly>
- <StopOnExitCode>3</StopOnExitCode>
- <CustomArgument></CustomArgument>
- <IncludeLibraryModules></IncludeLibraryModules>
- <ComprImg>1</ComprImg>
- </CommonProperty>
<FileArmAds>
<Cads>
- <interw>2</interw>
- <Optim>0</Optim>
- <oTime>2</oTime>
- <SplitLS>2</SplitLS>
- <OneElfS>2</OneElfS>
- <Strict>2</Strict>
- <EnumInt>2</EnumInt>
- <PlainCh>2</PlainCh>
- <Ropi>2</Ropi>
- <Rwpi>2</Rwpi>
- <wLevel>0</wLevel>
- <uThumb>2</uThumb>
- <uSurpInc>2</uSurpInc>
- <uC99>2</uC99>
- <uGnu>2</uGnu>
- <useXO>2</useXO>
- <v6Lang>0</v6Lang>
- <v6LangP>0</v6LangP>
- <vShortEn>2</vShortEn>
- <vShortWch>2</vShortWch>
- <v6Lto>2</v6Lto>
- <v6WtE>2</v6WtE>
- <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls> </MiscControls>
<Define>__RT_KERNEL_SOURCE__</Define>
<Undefine> </Undefine>
- <IncludePath></IncludePath>
+ <IncludePath> </IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
@@ -2300,61 +1133,85 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\armlibc\syscall_mem.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>syscalls.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\armlibc\syscalls.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cctype.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\common\cctype.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cstdlib.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\common\cstdlib.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cstring.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\common\cstring.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>ctime.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\common\ctime.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cunistd.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\common\cunistd.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>cwchar.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\libc\compilers\common\cwchar.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>kerrno.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\klibc\kerrno.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>kstdio.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\klibc\kstdio.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>kstring.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\klibc\kstring.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>rt_vsnprintf_tiny.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\klibc\rt_vsnprintf_tiny.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>rt_vsscanf.c</FileName>
<FileType>1</FileType>
@@ -2370,46 +1227,64 @@
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\misc.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_gpio.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_gpio.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_mmu.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_mmu.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_dma.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_dma.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_dmamux.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_dmamux.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_pwr.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_pwr.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_rcc.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_rcc.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_dbg.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_dbg.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_exti.c</FileName>
<FileType>1</FileType>
<FilePath>packages\n32h7xx_std_driver-latest\n32h7xx_std_periph_driver\src\n32h7xx_exti.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>n32h7xx_usart.c</FileName>
<FileType>1</FileType>
@@ -2425,11 +1300,15 @@
<FileType>1</FileType>
<FilePath>packages\n32h7xx_cmsis_driver-latest\device\system_n32h7xx.c</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>startup_n32h73x_76x.s</FileName>
<FileType>2</FileType>
<FilePath>packages\n32h7xx_cmsis_driver-latest\device\startup\startup_n32h73x_76x.s</FilePath>
</File>
+ </Files>
+ <Files>
<File>
<FileName>soc_mdk.c</FileName>
<FileType>1</FileType>
@@ -2437,14 +1316,22 @@
</File>
</Files>
</Group>
+ <Group>
+ <GroupName>test_file</GroupName>
+ <Files>
+ <File>
+ <FileName>uart_test.c</FileName>
+ <FileType>1</FileType>
+ <FilePath>applications\test_file\uart_test.c</FilePath>
+ </File>
+ </Files>
+ </Group>
</Groups>
</Target>
</Targets>
-
<RTE>
- <apis/>
- <components/>
- <files/>
+ <apis />
+ <components />
+ <files />
</RTE>
-
</Project>
diff --git a/bsp/n32/n32hxxx/n32h760zil7-stb/rtconfig.h b/bsp/n32/n32hxxx/n32h760zil7-stb/rtconfig.h
index 69dc683521..8749745f43 100644
--- a/bsp/n32/n32hxxx/n32h760zil7-stb/rtconfig.h
+++ b/bsp/n32/n32hxxx/n32h760zil7-stb/rtconfig.h
@@ -105,7 +105,7 @@
#define RT_CONSOLEBUF_SIZE 512
#define RT_CONSOLE_DEVICE_NAME "uart1"
#define RT_USING_CONSOLE_OUTPUT_CTL
-#define RT_VER_NUM 0x50300
+#define RT_VER_NUM 0x50301
#define RT_BACKTRACE_LEVEL_MAX_NR 32
/* end of RT-Thread Kernel */
#define RT_USING_CACHE
@@ -140,6 +140,14 @@
/* DFS: device virtual file system */
+#define RT_USING_DFS
+#define DFS_USING_POSIX
+#define DFS_USING_WORKDIR
+#define DFS_FD_MAX 16
+#define RT_USING_DFS_V1
+#define DFS_FILESYSTEMS_MAX 4
+#define DFS_FILESYSTEM_TYPES_MAX 4
+#define RT_USING_DFS_DEVFS
/* end of DFS: device virtual file system */
/* Device Drivers */
@@ -148,7 +156,6 @@
#define RT_UNAMED_PIPE_NUMBER 64
#define RT_USING_SERIAL
#define RT_USING_SERIAL_V1
-#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 512
#define RT_USING_PIN
/* end of Device Drivers */
diff --git a/tools/ci/bsp_detail.yml b/tools/ci/bsp_detail.yml
index 38e0a38e98..815f47d87b 100644
--- a/tools/ci/bsp_detail.yml
+++ b/tools/ci/bsp_detail.yml
@@ -1001,7 +1001,7 @@ msp432e401y-LaunchPad:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32g43xcl-stb:
+n32/n32gxx_lxx/n32g43xcl-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1009,7 +1009,7 @@ n32/n32g43xcl-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32g457qel-stb:
+n32/n32gxx_lxx/n32g457qel-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1017,7 +1017,7 @@ n32/n32g457qel-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32g45xcl-stb:
+n32/n32gxx_lxx/n32g45xcl-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1025,7 +1025,7 @@ n32/n32g45xcl-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32g45xml-stb:
+n32/n32gxx_lxx/n32g45xml-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1033,7 +1033,7 @@ n32/n32g45xml-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32g45xrl-stb:
+n32/n32gxx_lxx/n32g45xrl-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1041,7 +1041,7 @@ n32/n32g45xrl-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32g45xvl-stb:
+n32/n32gxx_lxx/n32g45xvl-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1049,7 +1049,7 @@ n32/n32g45xvl-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32g4frml-stb:
+n32/n32gxx_lxx/n32g4frml-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1057,7 +1057,7 @@ n32/n32g4frml-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32l40xcl-stb:
+n32/n32gxx_lxx/n32l40xcl-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1065,7 +1065,7 @@ n32/n32l40xcl-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32l436-evb:
+n32/n32gxx_lxx/n32l436-evb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1073,7 +1073,7 @@ n32/n32l436-evb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32l43xml-stb:
+n32/n32gxx_lxx/n32l43xml-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1081,7 +1081,7 @@ n32/n32l43xml-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32l43xrl-stb:
+n32/n32gxx_lxx/n32l43xrl-stb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1089,7 +1089,7 @@ n32/n32l43xrl-stb:
mdk5: true
menuconfig: true
rtconfig.h: true
-n32/n32wb45xl-evb:
+n32/n32gxx_lxx/n32wb45xl-evb:
.config: true
README.md: true
gcc: arm-none-eabi-gcc
@@ -1097,6 +1097,28 @@ n32/n32wb45xl-evb:
mdk5: true
menuconfig: true
rtconfig.h: true
+n32/n32hxxx/n32h487zgl7-evb:
+ .config: true
+ README.md: true
+ gcc: arm-none-eabi-gcc
+ iar: true
+ mdk5: true
+ menuconfig: true
+ rtconfig.h: true
+n32/n32hxxx/n32h497zgl7-evb:
+ .config: true
+ README.md: true
+ gcc: arm-none-eabi-gcc
+ iar: true
+ mdk5: true
+ menuconfig: true
+ rtconfig.h: true
+n32/n32hxxx/n32h760zil7-stb:
+ .config: true
+ gcc: arm-none-eabi-gcc
+ mdk5: true
+ menuconfig: true
+ rtconfig.h: true
n32g452xx/n32g452xx-mini-system:
.config: true
README.md: true
diff --git a/tools/ci/toolchain_bsp.yml b/tools/ci/toolchain_bsp.yml
index 09ab221458..4b2e1e69be 100644
--- a/tools/ci/toolchain_bsp.yml
+++ b/tools/ci/toolchain_bsp.yml
@@ -126,18 +126,21 @@ arm-none-eabi-gcc:
- mm32l07x
- mm32l3xx
- msp432e401y-LaunchPad
- - n32/n32g43xcl-stb
- - n32/n32g457qel-stb
- - n32/n32g45xcl-stb
- - n32/n32g45xml-stb
- - n32/n32g45xrl-stb
- - n32/n32g45xvl-stb
- - n32/n32g4frml-stb
- - n32/n32l40xcl-stb
- - n32/n32l436-evb
- - n32/n32l43xml-stb
- - n32/n32l43xrl-stb
- - n32/n32wb45xl-evb
+ - n32/n32gxx_lxx/n32g43xcl-stb
+ - n32/n32gxx_lxx/n32g457qel-stb
+ - n32/n32gxx_lxx/n32g45xcl-stb
+ - n32/n32gxx_lxx/n32g45xml-stb
+ - n32/n32gxx_lxx/n32g45xrl-stb
+ - n32/n32gxx_lxx/n32g45xvl-stb
+ - n32/n32gxx_lxx/n32g4frml-stb
+ - n32/n32gxx_lxx/n32l40xcl-stb
+ - n32/n32gxx_lxx/n32l436-evb
+ - n32/n32gxx_lxx/n32l43xml-stb
+ - n32/n32gxx_lxx/n32l43xrl-stb
+ - n32/n32gxx_lxx/n32wb45xl-evb
+ - n32/n32hxxx/n32h487zgl7-evb
+ - n32/n32hxxx/n32h497zgl7-evb
+ - n32/n32hxxx/n32h760zil7-stb
- n32g452xx/n32g452xx-mini-system
- nrf5x/nrf51822
- nrf5x/nrf52832
@@ -323,7 +326,7 @@ arm-none-eabi-gcc:
- yichip/yc3121-pos
- yichip/yc3122-pos
- zynqmp-r5-axu4ev
- count: 298
+ count: 301
download_url: https://github.com/RT-Thread/toolchains-ci/releases/download/v1.3/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
avr32-gcc:
bsp: