diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index af45e66286..80e1540579 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -9,7 +9,9 @@ "limitSymbolsToIncludedHeaders": true, "databaseFilename": "" }, - "intelliSenseMode": "msvc-x64" + "intelliSenseMode": "msvc-x64", + "cStandard": "c11", + "cppStandard": "c++17" } ], "version": 3 diff --git a/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake b/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake index 6caaee5f45..43e877d6fb 100644 --- a/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake +++ b/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake @@ -136,12 +136,16 @@ list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/ list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) # component STM32_RNG list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1) ############################################################################################################################### # Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding # following the template bellow. # # list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1) ############################################################################################################################### @@ -154,6 +158,10 @@ list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/Chib list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) # component STM32_RNG list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c) ########################################################################################################################## # Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework diff --git a/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake b/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake index 5dd5fdee00..4fd7faa05e 100644 --- a/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake +++ b/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake @@ -118,6 +118,8 @@ list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/ list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) # component STM32_RNG list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1) ############################################################################################################################### # Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding @@ -136,6 +138,10 @@ list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/Chib list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) # component STM32_RNG list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c) ########################################################################################################################## # Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework diff --git a/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake b/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake index d66c632bec..67fc755c15 100644 --- a/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake +++ b/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake @@ -114,7 +114,8 @@ list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/ list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) # component STM32_RNG list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1) - +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1) ############################################################################################################################### # Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding # following the template bellow. @@ -132,6 +133,10 @@ list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/Chib list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) # component STM32_RNG list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c) ########################################################################################################################## # Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework diff --git a/CMake/Modules/FindChibiOSnfOverlay.cmake b/CMake/Modules/FindChibiOSnfOverlay.cmake index 748b0ff764..e4da67568b 100644 --- a/CMake/Modules/FindChibiOSnfOverlay.cmake +++ b/CMake/Modules/FindChibiOSnfOverlay.cmake @@ -10,6 +10,8 @@ list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_crc) # component STM32_RNG list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_rng) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc) ################################################################################################################################## # Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding @@ -36,6 +38,8 @@ list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/Chib list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc/hal_stm32_crc.c) # component STM32_RNG list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng/hal_stm32_rng.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c) ######################################################################################################################### # Add above ALL the source code file(s) required for a new nanoFramework overlay component that you are adding diff --git a/src/CLR/Core/Execution.cpp b/src/CLR/Core/Execution.cpp index 86b25527ed..07ef7f7e00 100644 --- a/src/CLR/Core/Execution.cpp +++ b/src/CLR/Core/Execution.cpp @@ -155,6 +155,14 @@ HRESULT CLR_RT_ExecutionEngine::AllocateHeaps() CLR_RT_HeapCluster* hc = (CLR_RT_HeapCluster*) heapFirstFree; CLR_UINT32 size = (heapFree < c_HeapClusterSize) ? heapFree : c_HeapClusterSize; +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink + + CLR_Debug::Printf( "Heap Cluster information\r\n"); + CLR_Debug::Printf( "Start: %08x\r\n", (size_t)heapFirstFree); + CLR_Debug::Printf( "Free: %08x\r\n", (size_t)heapFree); + CLR_Debug::Printf( "Block size: %d\r\n", sizeof(CLR_RT_HeapBlock)); + +#endif /// /// Speed up heap initialization for devices with very large heaps > 1MB /// Exponentially increase the size of a default heap block diff --git a/src/HAL/Include/nanoHAL_v2.h b/src/HAL/Include/nanoHAL_v2.h index 6137b3ba86..3c1c26daa1 100644 --- a/src/HAL/Include/nanoHAL_v2.h +++ b/src/HAL/Include/nanoHAL_v2.h @@ -9,6 +9,7 @@ #include #include +#include typedef enum SYSTEM_STATE { @@ -151,6 +152,10 @@ extern "C" { void nanoHAL_Initialize_C(); void HeapLocation_C(unsigned char** baseAddress, unsigned int* sizeInBytes); +// Call to the external memory configuration and initialization function +// If a target has external memory it has to provide the implementation for it. +void Target_ExternalMemoryInit(); + #ifdef __cplusplus } #endif diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt index e712dd26f4..186d63f9d6 100644 --- a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt @@ -93,6 +93,8 @@ add_executable( ${NANOCLR_PROJECT_NAME}.elf "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + # the next one is required is the target implements and it's using external memory + "${CMAKE_CURRENT_SOURCE_DIR}/target_external_memory.c" ${COMMON_PROJECT_SOURCES} ${NANOCLR_PROJECT_SOURCES} diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld index 8817a7f2cd..bd27c82947 100644 --- a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld @@ -24,6 +24,7 @@ MEMORY ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ ram6 : org = 0x00000000, len = 0 ram7 : org = 0x00000000, len = 0 + ext_ram : org = 0xD0000000, len = 8M /* external SDRAM */ } /* For each data/text section two region are defined, a virtual region @@ -71,6 +72,6 @@ REGION_ALIAS("BSS_RAM", ram0); REGION_ALIAS("HEAP_RAM", ram4); /* RAM region to be used for the nanoFramework CLR managed heap.*/ -REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ext_ram); INCLUDE rules.ld diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h index c710062b71..370ea95871 100644 --- a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h @@ -16,5 +16,9 @@ #define HAL_USE_STM32_FLASH TRUE #endif -#endif // _HALCONF_NF_H_ +// Enables the FSMC subsystem. +#if !defined(HAL_USE_FSMC) +#define HAL_USE_FSMC TRUE +#endif +#endif // _HALCONF_NF_H_ diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c index eda6974960..d8248a3ce5 100644 --- a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c @@ -36,6 +36,10 @@ int main(void) { // main() is executing with absolute priority but interrupts are already enabled. osKernelInitialize(); + // config and init external memory + // this has to be called after osKernelInitialize, otherwise an hard fault will occur + Target_ExternalMemoryInit(); + // Initializes a serial-over-USB CDC driver. sduObjectInit(&SDU1); sduStart(&SDU1, &serusbcfg); diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h index 574b9636f7..b34976b479 100644 --- a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h @@ -6,5 +6,20 @@ #ifndef _MCUCONF_NF_H_ #define _MCUCONF_NF_H_ + +/* + * FSMC driver system settings. + */ +#define STM32_FSMC_USE_FSMC1 TRUE +#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10 +#define STM32_FSMC_DMA_CHN 0x03010201 + +/* + * FSMC SDRAM driver system settings. + */ +#define STM32_USE_FSMC_SDRAM TRUE +#define STM32_SDRAM_USE_FSMC_SDRAM1 FALSE +#define STM32_SDRAM_USE_FSMC_SDRAM2 TRUE + #endif // _MCUCONF_NF_H_ diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in index 101f177226..bdf31944de 100644 --- a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in @@ -18,9 +18,9 @@ // they also must be coherent with what's in the linker file for nanoBooter and nanoCLR // RAM base address -#define RAM1_MEMORY_StartAddress ((uint32_t)0x200000C0) +#define RAM1_MEMORY_StartAddress ((uint32_t)0xD0000000) // RAM size -#define RAM1_MEMORY_Size ((uint32_t)0x00030000) +#define RAM1_MEMORY_Size ((uint32_t)0x00800000) // FLASH base address #define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_external_memory.c b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_external_memory.c new file mode 100644 index 0000000000..61e2bfae73 --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_external_memory.c @@ -0,0 +1,106 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "hal.h" +#include "fsmc_sdram_lld.h" + + +// SDRAM Mode definition register defines +#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_BURST_LENGTH_2 ((uint16_t)0x0001) +#define FMC_SDCMR_MRD_BURST_LENGTH_4 ((uint16_t)0x0002) +#define FMC_SDCMR_MRD_BURST_LENGTH_8 ((uint16_t)0x0004) +#define FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) +#define FMC_SDCMR_MRD_CAS_LATENCY_2 ((uint16_t)0x0020) +#define FMC_SDCMR_MRD_CAS_LATENCY_3 ((uint16_t)0x0030) +#define FMC_SDCMR_MRD_OPERATING_MODE_STANDARD ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +// FMC_ReadPipe_Delay +#define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000) +#define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000) +#define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000) +#define FMC_ReadPipe_Delay_Mask ((uint32_t)0x00006000) + +// FMC_Read_Burst +#define FMC_Read_Burst_Disable ((uint32_t)0x00000000) +#define FMC_Read_Burst_Enable ((uint32_t)0x00001000) +#define FMC_Read_Burst_Mask ((uint32_t)0x00001000) + +// FMC_SDClock_Period +#define FMC_SDClock_Disable ((uint32_t)0x00000000) +#define FMC_SDClock_Period_2 ((uint32_t)0x00000800) +#define FMC_SDClock_Period_3 ((uint32_t)0x00000C00) +#define FMC_SDClock_Period_Mask ((uint32_t)0x00000C00) + +// FMC_ColumnBits_Number +#define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000) +#define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001) +#define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002) +#define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003) + +// FMC_RowBits_Number +#define FMC_RowBits_Number_11b ((uint32_t)0x00000000) +#define FMC_RowBits_Number_12b ((uint32_t)0x00000004) +#define FMC_RowBits_Number_13b ((uint32_t)0x00000008) + +// FMC_SDMemory_Data_Width +#define FMC_SDMemory_Width_8b ((uint32_t)0x00000000) +#define FMC_SDMemory_Width_16b ((uint32_t)0x00000010) +#define FMC_SDMemory_Width_32b ((uint32_t)0x00000020) + +// FMC_InternalBank_Number +#define FMC_InternalBank_Number_2 ((uint32_t)0x00000000) +#define FMC_InternalBank_Number_4 ((uint32_t)0x00000040) + +// FMC_CAS_Latency +#define FMC_CAS_Latency_1 ((uint32_t)0x00000080) +#define FMC_CAS_Latency_2 ((uint32_t)0x00000100) +#define FMC_CAS_Latency_3 ((uint32_t)0x00000180) + +// FMC_Write_Protection +#define FMC_Write_Protection_Disable ((uint32_t)0x00000000) +#define FMC_Write_Protection_Enable ((uint32_t)0x00000200) + +#define SDRAM_SIZE (8 * 1024 * 1024) +#define SDRAM_START ((void *)FSMC_Bank6_MAP_BASE) + + +// SDRAM driver configuration structure. +static const SDRAMConfig sdram_cfg = { + .sdcr = (uint32_t) FMC_ColumnBits_Number_8b | + FMC_RowBits_Number_12b | + FMC_SDMemory_Width_16b | + FMC_InternalBank_Number_4 | + FMC_CAS_Latency_3 | + FMC_Write_Protection_Disable | + FMC_SDClock_Period_2 | + FMC_Read_Burst_Enable | + FMC_ReadPipe_Delay_1, + .sdtr = (uint32_t) (2 - 1) | // FMC_LoadToActiveDelay = 2 (TMRD: 2 Clock cycles) + (7 << 4) | // FMC_ExitSelfRefreshDelay = 7 (TXSR: min=70ns (7x11.11ns)) + (4 << 8) | // FMC_SelfRefreshTime = 4 (TRAS: min=42ns (4x11.11ns) max=120k (ns)) + (7 << 12) | // FMC_RowCycleDelay = 7 (TRC: min=70 (7x11.11ns)) + (3 << 16) | // FMC_WriteRecoveryTime = 2 (TWR: min=1+ 7ns (1+1x11.11ns)) + (2 << 20) | // FMC_RPDelay = 2 (TRP: 20ns => 2x11.11ns) + (2 << 24), // FMC_RCDDelay = 2 (TRCD: 20ns => 2x11.11ns) + // NRFS = 4-1 + .sdcmr = (3 << 5) | (FMC_SDCMR_MRD_BURST_LENGTH_2 | + FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL | + FMC_SDCMR_MRD_CAS_LATENCY_3 | + FMC_SDCMR_MRD_OPERATING_MODE_STANDARD | + FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE) << 9, + + .sdrtr = (uint32_t)(683 << 1), +}; + +void Target_ExternalMemoryInit() +{ + fsmcSdramInit(); + fsmcSdramStart(&SDRAMD, &sdram_cfg); +} diff --git a/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld b/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld index d2515f2da8..fa391da264 100644 --- a/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld +++ b/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld @@ -115,6 +115,12 @@ SECTIONS . = ALIGN(4); __eth_end__ = .; } > ETH_RAM + + /* placing my named section at given address: */ + .myBufBlock 0xC0000000 : + { + KEEP(*(.myBufSection)) /* keep my variable even if not referenced */ + } > sram } /* Code rules inclusion.*/ diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_community.h b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_community.h index b96f007748..1df9242326 100644 --- a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_community.h +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_community.h @@ -9,7 +9,7 @@ // these are for error checks on the configuration header files #if !defined(HAL_USE_STM32_FLASH) -#define HAL_USE_STM32_FLASH FALSE +#define HAL_USE_STM32_FLASH FALSE #endif #if !defined(HAL_USE_STM32_CRC) @@ -22,6 +22,11 @@ #define HAL_USE_STM32_RNG TRUE #endif +#if !defined(HAL_USE_FSMC) +#define HAL_USE_FSMC FALSE +#endif + + // Abstract interfaces // Shared headers @@ -31,6 +36,7 @@ #include "hal_stm32_flash.h" #include "hal_stm32_crc.h" #include "hal_stm32_rng.h" +#include "hal_stm32_fsmc.h" // Complex drivers // #include "hal_nnnn.h" diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc/hal_stm32_fsmc.h b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc/hal_stm32_fsmc.h new file mode 100644 index 0000000000..7388310ab2 --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc/hal_stm32_fsmc.h @@ -0,0 +1,329 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_FSMC_H_ +#define HAL_FSMC_H_ + +#if (HAL_USE_FSMC == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +// (Re)define if needed base address constants supplied in ST's CMSIS +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + #if !defined(FSMC_Bank1_R_BASE) + #define FSMC_Bank1_R_BASE (FMC_R_BASE + 0x0000) + #endif + #if !defined(FSMC_Bank1E_R_BASE) + #define FSMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104) + #endif + #if !defined(FSMC_Bank2_R_BASE) + #define FSMC_Bank2_R_BASE (FMC_R_BASE + 0x0060) + #endif + #if !defined(FSMC_Bank3_R_BASE) + #define FSMC_Bank3_R_BASE (FMC_R_BASE + 0x0080) + #endif + #if !defined(FSMC_Bank4_R_BASE) + #define FSMC_Bank4_R_BASE (FMC_R_BASE + 0x00A0) + #endif + #if !defined(FSMC_Bank5_R_BASE) + #define FSMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140) + #endif +#else + #if !defined(FSMC_Bank1_R_BASE) + #define FSMC_Bank1_R_BASE (FSMC_R_BASE + 0x0000) + #endif + #if !defined(FSMC_Bank1E_R_BASE) + #define FSMC_Bank1E_R_BASE (FSMC_R_BASE + 0x0104) + #endif + #if !defined(FSMC_Bank2_R_BASE) + #define FSMC_Bank2_R_BASE (FSMC_R_BASE + 0x0060) + #endif + #if !defined(FSMC_Bank3_R_BASE) + #define FSMC_Bank3_R_BASE (FSMC_R_BASE + 0x0080) + #endif + #if !defined(FSMC_Bank4_R_BASE) + #define FSMC_Bank4_R_BASE (FSMC_R_BASE + 0x00A0) + #endif +#endif + +/* + * Base bank mappings + */ +#define FSMC_Bank1_MAP_BASE ((uint32_t) 0x60000000) +#define FSMC_Bank2_MAP_BASE ((uint32_t) 0x70000000) +#define FSMC_Bank3_MAP_BASE ((uint32_t) 0x80000000) +#define FSMC_Bank4_MAP_BASE ((uint32_t) 0x90000000) +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) + #define FSMC_Bank5_MAP_BASE ((uint32_t) 0xC0000000) + #define FSMC_Bank6_MAP_BASE ((uint32_t) 0xD0000000) +#endif + +/* + * Subbunks of bank1 + */ +#define FSMC_SUBBUNK_OFFSET (1024 * 1024 * 64) +#define FSMC_Bank1_1_MAP (FSMC_Bank1_MAP_BASE) +#define FSMC_Bank1_2_MAP (FSMC_Bank1_1_MAP + FSMC_SUBBUNK_OFFSET) +#define FSMC_Bank1_3_MAP (FSMC_Bank1_2_MAP + FSMC_SUBBUNK_OFFSET) +#define FSMC_Bank1_4_MAP (FSMC_Bank1_3_MAP + FSMC_SUBBUNK_OFFSET) + +/* + * Bank 2 (NAND) + */ +#define FSMC_Bank2_MAP_COMMON (FSMC_Bank2_MAP_BASE + 0) +#define FSMC_Bank2_MAP_ATTR (FSMC_Bank2_MAP_BASE + 0x8000000) + +#define FSMC_Bank2_MAP_COMMON_DATA (FSMC_Bank2_MAP_COMMON + 0) +#define FSMC_Bank2_MAP_COMMON_CMD (FSMC_Bank2_MAP_COMMON + 0x10000) +#define FSMC_Bank2_MAP_COMMON_ADDR (FSMC_Bank2_MAP_COMMON + 0x20000) + +#define FSMC_Bank2_MAP_ATTR_DATA (FSMC_Bank2_MAP_ATTR + 0) +#define FSMC_Bank2_MAP_ATTR_CMD (FSMC_Bank2_MAP_ATTR + 0x10000) +#define FSMC_Bank2_MAP_ATTR_ADDR (FSMC_Bank2_MAP_ATTR + 0x20000) + +/* + * Bank 3 (NAND) + */ +#define FSMC_Bank3_MAP_COMMON (FSMC_Bank3_MAP_BASE + 0) +#define FSMC_Bank3_MAP_ATTR (FSMC_Bank3_MAP_BASE + 0x8000000) + +#define FSMC_Bank3_MAP_COMMON_DATA (FSMC_Bank3_MAP_COMMON + 0) +#define FSMC_Bank3_MAP_COMMON_CMD (FSMC_Bank3_MAP_COMMON + 0x10000) +#define FSMC_Bank3_MAP_COMMON_ADDR (FSMC_Bank3_MAP_COMMON + 0x20000) + +#define FSMC_Bank3_MAP_ATTR_DATA (FSMC_Bank3_MAP_ATTR + 0) +#define FSMC_Bank3_MAP_ATTR_CMD (FSMC_Bank3_MAP_ATTR + 0x10000) +#define FSMC_Bank3_MAP_ATTR_ADDR (FSMC_Bank3_MAP_ATTR + 0x20000) + +/* + * Bank 4 (PC card) + */ +#define FSMC_Bank4_MAP_COMMON (FSMC_Bank4_MAP_BASE + 0) +#define FSMC_Bank4_MAP_ATTR (FSMC_Bank4_MAP_BASE + 0x8000000) +#define FSMC_Bank4_MAP_IO (FSMC_Bank4_MAP_BASE + 0xC000000) + +/* + * More convenient typedefs than CMSIS has + */ +typedef struct { + __IO uint32_t PCR; /**< NAND Flash control */ + __IO uint32_t SR; /**< NAND Flash FIFO status and interrupt */ + __IO uint32_t PMEM; /**< NAND Flash Common memory space timing */ + __IO uint32_t PATT; /**< NAND Flash Attribute memory space timing */ + uint32_t RESERVED0; /**< Reserved, 0x70 */ + __IO uint32_t ECCR; /**< NAND Flash ECC result registers */ +} FSMC_NAND_TypeDef; + +typedef struct { + __IO uint32_t PCR; /**< PC Card control */ + __IO uint32_t SR; /**< PC Card FIFO status and interrupt */ + __IO uint32_t PMEM; /**< PC Card Common memory space timing */ + __IO uint32_t PATT; /**< PC Card Attribute memory space timing */ + __IO uint32_t PIO; /**< PC Card I/O space timing */ +} FSMC_PCCard_TypeDef; + +typedef struct { + __IO uint32_t BCR; /**< SRAM/NOR chip-select control registers */ + __IO uint32_t BTR; /**< SRAM/NOR chip-select timing registers */ + uint32_t RESERVED[63]; /**< Reserved */ + __IO uint32_t BWTR; /**< SRAM/NOR write timing registers */ +} FSMC_SRAM_NOR_TypeDef; + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) + +typedef struct { + __IO uint32_t SDCR1; /**< SDRAM control register (bank 1) */ + __IO uint32_t SDCR2; /**< SDRAM control register (bank 2) */ + __IO uint32_t SDTR1; /**< SDRAM timing register (bank 1) */ + __IO uint32_t SDTR2; /**< SDRAM timing register (bank 2) */ + __IO uint32_t SDCMR; /**< SDRAM comand mode register */ + __IO uint32_t SDRTR; /**< SDRAM refresh timer register */ + __IO uint32_t SDSR; /**< SDRAM status register */ +} FSMC_SDRAM_TypeDef; + +#endif + +/** + * @brief PCR register + */ +#define FSMC_PCR_PWAITEN ((uint32_t)1 << 1) +#define FSMC_PCR_PBKEN ((uint32_t)1 << 2) +#define FSMC_PCR_PTYP ((uint32_t)1 << 3) +#define FSMC_PCR_PWID_8 ((uint32_t)0 << 4) +#define FSMC_PCR_PWID_16 ((uint32_t)1 << 4) +#define FSMC_PCR_PWID_RESERVED1 ((uint32_t)2 << 4) +#define FSMC_PCR_PWID_RESERVED2 ((uint32_t)3 << 4) +#define FSMC_PCR_PWID_MASK ((uint32_t)3 << 4) +#define FSMC_PCR_ECCEN ((uint32_t)1 << 6) +#define FSMC_PCR_PTYP_PCCARD 0 +#define FSMC_PCR_PTYP_NAND FSMC_PCR_PTYP + +/** + * @brief SR register + */ +#define FSMC_SR_IRS ((uint8_t)0x01) +#define FSMC_SR_ILS ((uint8_t)0x02) +#define FSMC_SR_IFS ((uint8_t)0x04) +#define FSMC_SR_IREN ((uint8_t)0x08) +#define FSMC_SR_ILEN ((uint8_t)0x10) +#define FSMC_SR_IFEN ((uint8_t)0x20) +#define FSMC_SR_FEMPT ((uint8_t)0x40) +#define FSMC_SR_ISR_MASK (FSMC_SR_IRS | FSMC_SR_ILS | FSMC_SR_IFS) + +/** + * @brief BCR register + */ +#define FSMC_BCR_MBKEN ((uint32_t)1 << 0) +#define FSMC_BCR_MUXEN ((uint32_t)1 << 1) +#define FSMC_BCR_MTYP_SRAM ((uint32_t)0 << 2) +#define FSMC_BCR_MTYP_PSRAM ((uint32_t)1 << 2) +#define FSMC_BCR_MTYP_NOR_NAND ((uint32_t)2 << 2) +#define FSMC_BCR_MTYP_RESERVED ((uint32_t)3 << 2) +#define FSMC_BCR_MWID_8 ((uint32_t)0 << 4) +#define FSMC_BCR_MWID_16 ((uint32_t)1 << 4) +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) +#define FSMC_BCR_MWID_32 ((uint32_t)2 << 4) +#else +#define FSMC_BCR_MWID_RESERVED1 ((uint32_t)2 << 4) +#endif +#define FSMC_BCR_MWID_RESERVED2 ((uint32_t)3 << 4) +#define FSMC_BCR_FACCEN ((uint32_t)1 << 6) +#define FSMC_BCR_BURSTEN ((uint32_t)1 << 8) +#define FSMC_BCR_WAITPOL ((uint32_t)1 << 9) +#define FSMC_BCR_WRAPMOD ((uint32_t)1 << 10) +#define FSMC_BCR_WAITCFG ((uint32_t)1 << 11) +#define FSMC_BCR_WREN ((uint32_t)1 << 12) +#define FSMC_BCR_WAITEN ((uint32_t)1 << 13) +#define FSMC_BCR_EXTMOD ((uint32_t)1 << 14) +#define FSMC_BCR_ASYNCWAIT ((uint32_t)1 << 15) +#define FSMC_BCR_CBURSTRW ((uint32_t)1 << 19) +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) +#define FSMC_BCR_CCLKEN ((uint32_t)1 << 20) +#endif +#if (defined(STM32F7)) +#define FSMC_BCR_WFDIS ((uint32_t)1 << 21) +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief FSMC driver enable switch. + * @details If set to @p TRUE the support for FSMC is included. + */ +#if !defined(STM32_FSMC_USE_FSMC1) +#define STM32_FSMC_USE_FSMC1 FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ +#if !STM32_FSMC_USE_FSMC1 +#error "FSMC driver activated but no FSMC peripheral assigned" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an FSMC driver. + */ +typedef struct FSMCDriver FSMCDriver; + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + FSMC_UNINIT = 0, /**< Not initialized. */ + FSMC_STOP = 1, /**< Stopped. */ + FSMC_READY = 2, /**< Ready. */ +} fsmcstate_t; + +/** + * @brief Structure representing an FSMC driver. + */ +struct FSMCDriver { + /** + * @brief Driver state. + */ + fsmcstate_t state; + /* End of the mandatory fields.*/ + +#if STM32_SRAM_USE_FSMC_SRAM1 + FSMC_SRAM_NOR_TypeDef *sram1; +#endif +#if STM32_SRAM_USE_FSMC_SRAM2 + FSMC_SRAM_NOR_TypeDef *sram2; +#endif +#if STM32_SRAM_USE_FSMC_SRAM3 + FSMC_SRAM_NOR_TypeDef *sram3; +#endif +#if STM32_SRAM_USE_FSMC_SRAM4 + FSMC_SRAM_NOR_TypeDef *sram4; +#endif +#if STM32_NAND_USE_FSMC_NAND1 + FSMC_NAND_TypeDef *nand1; +#endif +#if STM32_NAND_USE_FSMC_NAND2 + FSMC_NAND_TypeDef *nand2; +#endif +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F7)) + #if STM32_USE_FSMC_SDRAM + FSMC_SDRAM_TypeDef *sdram; + #endif +#endif +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32_FSMC_USE_FSMC1 && !defined(__DOXYGEN__) +extern FSMCDriver FSMCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void stm32FsmcInit(void); + void fsmc_start(FSMCDriver *fsmcp); + void fsmc_stop(FSMCDriver *fsmcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_FSMC */ + +#endif /* HAL_FSMC_H_ */ diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/README.md b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/README.md new file mode 100644 index 0000000000..2324fcee2e --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/README.md @@ -0,0 +1,4 @@ +# External flexible memory controller (FSMC) driver V1 + +This driver supports F4 and F7 series. +The low level driver code is taken from or heavily inspired in the ChibiOS community contribution repository. diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c new file mode 100644 index 0000000000..8d942279bc --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c @@ -0,0 +1,474 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +#if (HAL_USE_NAND == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// +#define NAND_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_NAND_DMA_STREAM, \ + STM32_FSMC_DMA_CHN) + +// Bus width of NAND IC. +// Must be 8 or 16 +#if ! defined(STM32_NAND_BUS_WIDTH) +#define STM32_NAND_BUS_WIDTH 8 +#endif + +// DMA transaction width on AHB bus in bytes +#define AHB_TRANSACTION_WIDTH 2 + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// + +// NAND1 driver identifier. +#if STM32_NAND_USE_FSMC_NAND1 +NANDDriver NANDD1; +#endif + +// NAND2 driver identifier. +#if STM32_NAND_USE_FSMC_NAND2 +NANDDriver NANDD2; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Helper function. +static void align_check(const void *ptr, uint32_t len) { + osalDbgCheck((((uint32_t)ptr % AHB_TRANSACTION_WIDTH) == 0) && + ((len % AHB_TRANSACTION_WIDTH) == 0) && + (len >= AHB_TRANSACTION_WIDTH)); + (void)ptr; + (void)len; +} + +// Work around errata in STM32's FSMC core. +// Constant output clock (if enabled) disappears when CLKDIV value +// sets to 1 (FMC_CLK period = 2 × HCLK periods) AND 8-bit async +// transaction generated on AHB. This workaround eliminates 8-bit +// transactions on bus when you use 8-bit memory. It suitable only +// for 8-bit memory (i.e. PWID bits in PCR register must be set +// to 8-bit mode). +static void set_16bit_bus(NANDDriver *nandp) { +#if STM32_NAND_BUS_WIDTH + nandp->nand->PCR |= FSMC_PCR_PWID_16; +#else + (void)nandp; +#endif +} + +static void set_8bit_bus(NANDDriver *nandp) { +#if STM32_NAND_BUS_WIDTH + nandp->nand->PCR &= ~FSMC_PCR_PWID_16; +#else + (void)nandp; +#endif +} + +// Wakes up the waiting thread. +// nandp pointer to the @p NANDDriver object +// msg wakeup message +static void wakeup_isr(NANDDriver *nandp) { + + osalDbgCheck(nandp->thread != NULL); + osalThreadResumeI(&nandp->thread, MSG_OK); +} + +// Put calling thread in suspend and switch driver state +// nandp pointer to the @p NANDDriver object +static void nand_lld_suspend_thread(NANDDriver *nandp) { + + osalThreadSuspendS(&nandp->thread); +} + +// Caclulate ECCPS register value +// nandp pointer to the @p NANDDriver object +static uint32_t calc_eccps(NANDDriver *nandp) { + + uint32_t i = 0; + uint32_t eccps = nandp->config->page_data_size; + + eccps = eccps >> 9; + while (eccps > 0){ + i++; + eccps >>= 1; + } + + return i << 17; +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver interrupt handlers. // +/////////////////////////////////////////////////////////////////////////////// + +// Enable interrupts from NAND +// nandp pointer to the @p NANDDriver object +static void nand_ready_isr_enable(NANDDriver *nandp) { + + nandp->nand->SR &= ~(FSMC_SR_IRS | FSMC_SR_ILS | FSMC_SR_IFS | + FSMC_SR_ILEN | FSMC_SR_IFEN); + nandp->nand->SR |= FSMC_SR_IREN; +} + +// Disable interrupts from NAND +// nandp pointer to the @p NANDDriver object +static void nand_ready_isr_disable(NANDDriver *nandp) { + + nandp->nand->SR &= ~FSMC_SR_IREN; +} + +// Ready interrupt handler +// nandp pointer to the @p NANDDriver object +static void nand_isr_handler(NANDDriver *nandp) { + + osalSysLockFromISR(); + + osalDbgCheck(nandp->nand->SR & FSMC_SR_IRS); // spurious interrupt happened + nandp->nand->SR &= ~FSMC_SR_IRS; + + switch (nandp->state){ + case NAND_READ: + nandp->state = NAND_DMA_RX; + dmaStartMemCopy(nandp->dma, nandp->dmamode, nandp->map_data, nandp->rxdata, + nandp->datalen/AHB_TRANSACTION_WIDTH); + // thread will be waked up from DMA ISR + break; + + case NAND_ERASE: // NAND reports about erase finish + case NAND_PROGRAM: // NAND reports about page programming finish + case NAND_RESET: // NAND reports about finished reset recover + nandp->state = NAND_READY; + wakeup_isr(nandp); + break; + + default: + osalSysHalt("Unhandled case"); + break; + } + osalSysUnlockFromISR(); +} + +// DMA RX end IRQ handler. +// nandp pointer to the @p NANDDriver object +// flags pre-shifted content of the ISR register +static void nand_lld_serve_transfer_end_irq(NANDDriver *nandp, uint32_t flags) { + // DMA errors handling. +#if defined(STM32_NAND_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_NAND_DMA_ERROR_HOOK(nandp); + } +#else + (void)flags; +#endif + + osalSysLockFromISR(); + + dmaStreamDisable(nandp->dma); + + switch (nandp->state){ + case NAND_DMA_TX: + nandp->state = NAND_PROGRAM; + nandp->map_cmd[0] = NAND_CMD_PAGEPROG; + // thread will be woken up from ready_isr() + break; + + case NAND_DMA_RX: + nandp->state = NAND_READY; + nandp->rxdata = NULL; + nandp->datalen = 0; + wakeup_isr(nandp); + break; + + default: + osalSysHalt("Unhandled case"); + break; + } + + osalSysUnlockFromISR(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level NAND driver initialization. +void fsmcNandInit(void) { + + stm32FsmcInit(); + +#if STM32_NAND_USE_FSMC_NAND1 + // Driver initialization. + nandObjectInit(&NANDD1); + NANDD1.rxdata = NULL; + NANDD1.datalen = 0; + NANDD1.thread = NULL; + NANDD1.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM); + NANDD1.nand = FSMCD1.nand1; + NANDD1.map_data = (void *)FSMC_Bank2_MAP_COMMON_DATA; + NANDD1.map_cmd = (uint16_t *)FSMC_Bank2_MAP_COMMON_CMD; + NANDD1.map_addr = (uint16_t *)FSMC_Bank2_MAP_COMMON_ADDR; + NANDD1.bb_map = NULL; +#endif // STM32_NAND_USE_FSMC_NAND1 + +#if STM32_NAND_USE_FSMC_NAND2 + // Driver initialization. + nandObjectInit(&NANDD2); + NANDD2.rxdata = NULL; + NANDD2.datalen = 0; + NANDD2.thread = NULL; + NANDD2.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM); + NANDD2.nand = FSMCD1.nand2; + NANDD2.map_data = (void *)FSMC_Bank3_MAP_COMMON_DATA; + NANDD2.map_cmd = (uint16_t *)FSMC_Bank3_MAP_COMMON_CMD; + NANDD2.map_addr = (uint16_t *)FSMC_Bank3_MAP_COMMON_ADDR; + NANDD2.bb_map = NULL; +#endif // STM32_NAND_USE_FSMC_NAND2 +} + +// Configures and activates the NAND peripheral. +// nandp pointer to the @p NANDDriver object +void fsmcNandStart(NANDDriver *nandp) { + + bool b; + uint32_t dmasize; + uint32_t pcr_bus_width; + + if (FSMCD1.state == FSMC_STOP) + fsmc_start(&FSMCD1); + + if (nandp->state == NAND_STOP) { + b = dmaStreamAllocate(nandp->dma, + STM32_EMC_FSMC1_IRQ_PRIORITY, + (stm32_dmaisr_t)nand_lld_serve_transfer_end_irq, + (void *)nandp); + osalDbgAssert(!b, "stream already allocated"); + +#if AHB_TRANSACTION_WIDTH == 4 + dmasize = STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; +#elif AHB_TRANSACTION_WIDTH == 2 + dmasize = STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; +#elif AHB_TRANSACTION_WIDTH == 1 + dmasize = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; +#else +#error "Incorrect AHB_TRANSACTION_WIDTH" +#endif + + nandp->dmamode = STM32_DMA_CR_CHSEL(NAND_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_NAND_NAND1_DMA_PRIORITY) | + dmasize | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | + STM32_DMA_CR_TCIE; + +#if STM32_NAND_BUS_WIDTH == 8 + pcr_bus_width = FSMC_PCR_PWID_8; +#elif STM32_NAND_BUS_WIDTH == 16 + pcr_bus_width = FSMC_PCR_PWID_16; +#else +#error "Bus width must be 8 or 16 bits" +#endif + nandp->nand->PCR = pcr_bus_width | calc_eccps(nandp) | + FSMC_PCR_PTYP_NAND | FSMC_PCR_PBKEN; + nandp->nand->PMEM = nandp->config->pmem; + nandp->nand->PATT = nandp->config->pmem; + nandp->isr_handler = nand_isr_handler; + nand_ready_isr_enable(nandp); + } +} + +// Deactivates the NAND peripheral. +// nandp pointer to the @p NANDDriver object +void fsmcNandStop(NANDDriver *nandp) { + + if (nandp->state == NAND_READY) { + dmaStreamRelease(nandp->dma); + nandp->nand->PCR &= ~FSMC_PCR_PBKEN; + nand_ready_isr_disable(nandp); + nandp->isr_handler = NULL; + } +} + +// Read data from NAND. +// nandp pointer to the @p NANDDriver object +// data pointer to data buffer +// datalen size of data buffer in bytes +// addr pointer to address buffer +// addrlen length of address +// ecc pointer to store computed ECC. Ignored when NULL. +void nand_lld_read_data(NANDDriver *nandp, uint16_t *data, size_t datalen, + uint8_t *addr, size_t addrlen, uint32_t *ecc){ + + align_check(data, datalen); + + nandp->state = NAND_READ; + nandp->rxdata = data; + nandp->datalen = datalen; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_READ0); + nand_lld_write_addr(nandp, addr, addrlen); + osalSysLock(); + nand_lld_write_cmd(nandp, NAND_CMD_READ0_CONFIRM); + set_8bit_bus(nandp); + + // Here NAND asserts busy signal and starts transferring from memory + // array to page buffer. After the end of transmission ready_isr functions + // starts DMA transfer from page buffer to MCU's RAM. + osalDbgAssert((nandp->nand->PCR & FSMC_PCR_ECCEN) == 0, + "State machine broken. ECCEN must be previously disabled."); + + if (NULL != ecc){ + nandp->nand->PCR |= FSMC_PCR_ECCEN; + } + + nand_lld_suspend_thread(nandp); + osalSysUnlock(); + + // thread was woken up from DMA ISR + if (NULL != ecc){ + while (! (nandp->nand->SR & FSMC_SR_FEMPT)) + ; + *ecc = nandp->nand->ECCR; + nandp->nand->PCR &= ~FSMC_PCR_ECCEN; + } +} + +// Write data to NAND. +// nandp pointer to the @p NANDDriver object +// data buffer with data to be written +// datalen size of data buffer in bytes +// addr pointer to address buffer +// addrlen length of address +// ecc pointer to store computed ECC. Ignored when NULL. +// The operation status reported by NAND IC (0x70 command). +uint8_t nand_lld_write_data(NANDDriver *nandp, const uint16_t *data, + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc) { + + align_check(data, datalen); + + nandp->state = NAND_WRITE; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_WRITE); + osalSysLock(); + nand_lld_write_addr(nandp, addr, addrlen); + set_8bit_bus(nandp); + + // Now start DMA transfer to NAND buffer and put thread in sleep state. + // Tread will be woken up from ready ISR. + nandp->state = NAND_DMA_TX; + osalDbgAssert((nandp->nand->PCR & FSMC_PCR_ECCEN) == 0, + "State machine broken. ECCEN must be previously disabled."); + + if (NULL != ecc){ + nandp->nand->PCR |= FSMC_PCR_ECCEN; + } + + dmaStartMemCopy(nandp->dma, nandp->dmamode, data, nandp->map_data, + datalen/AHB_TRANSACTION_WIDTH); + + nand_lld_suspend_thread(nandp); + osalSysUnlock(); + + if (NULL != ecc){ + while (! (nandp->nand->SR & FSMC_SR_FEMPT)) + ; + *ecc = nandp->nand->ECCR; + nandp->nand->PCR &= ~FSMC_PCR_ECCEN; + } + + return nand_lld_read_status(nandp); +} + +// Soft reset NAND device. +// nandp pointer to the @p NANDDriver object +void nand_lld_reset(NANDDriver *nandp) { + + nandp->state = NAND_RESET; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_RESET); + set_8bit_bus(nandp); + + osalSysLock(); + nand_lld_suspend_thread(nandp); + osalSysUnlock(); +} + +// Erase block. +// nandp pointer to the @p NANDDriver object +// addr pointer to address buffer +// addrlen length of address +// return The operation status reported by NAND IC (0x70 command). +uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen) { + + nandp->state = NAND_ERASE; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_ERASE); + nand_lld_write_addr(nandp, addr, addrlen); + osalSysLock(); + nand_lld_write_cmd(nandp, NAND_CMD_ERASE_CONFIRM); + set_8bit_bus(nandp); + + nand_lld_suspend_thread(nandp); + osalSysUnlock(); + + return nand_lld_read_status(nandp); +} + +// Send addres to NAND. +// nandp pointer to the @p NANDDriver object +// len length of address array +// addr pointer to address array +void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len) { + size_t i = 0; + + for (i=0; imap_addr[i] = addr[i]; +} + +// Send command to NAND. +// nandp pointer to the @p NANDDriver object +// cmd command value +void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd) { + nandp->map_cmd[0] = cmd; +} + +// Read status byte from NAND. +// nandp pointer to the @p NANDDriver object +// return Status byte. +uint8_t nand_lld_read_status(NANDDriver *nandp) { + + uint16_t status; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_STATUS); + set_8bit_bus(nandp); + status = nandp->map_data[0]; + + return status & 0xFF; +} + +#endif // HAL_USE_NAND diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h new file mode 100644 index 0000000000..91d4a028c1 --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h @@ -0,0 +1,218 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_NAND_LLD_H_ +#define HAL_NAND_LLD_H_ + +#include "hal_stm32_fsmc" + +#if (HAL_USE_NAND == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// +#define NAND_MIN_PAGE_SIZE 256 +#define NAND_MAX_PAGE_SIZE 8192 + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +// Configuration options + +// FSMC1 interrupt priority level setting. +#if !defined(STM32_EMC_FSMC1_IRQ_PRIORITY) +#define STM32_EMC_FSMC1_IRQ_PRIORITY 10 +#endif + +// NAND driver enable switch. +// If set to @p TRUE the support for NAND1 is included. + +#if !defined(STM32_NAND_USE_NAND1) +#define STM32_NAND_USE_NAND1 FALSE +#endif + +// NAND driver enable switch. +// If set to @p TRUE the support for NAND2 is included. +#if !defined(STM32_NAND_USE_NAND2) +#define STM32_NAND_USE_NAND2 FALSE +#endif + +// NAND DMA error hook. +// The default action for DMA errors is a system halt because DMA +// error can only happen because programming errors. +#if !defined(STM32_NAND_DMA_ERROR_HOOK) +#define STM32_NAND_DMA_ERROR_HOOK(nandp) osalSysHalt("DMA failure") +#endif + +// NAND interrupt enable switch. +// If set to @p TRUE the support for internal FSMC interrupt included. +#if !defined(STM32_NAND_USE_INT) +#define STM32_NAND_USE_INT FALSE +#endif + +// NAND1 DMA priority (0..3|lowest..highest). +#if !defined(STM32_NAND_NAND1_DMA_PRIORITY) +#define STM32_NAND_NAND1_DMA_PRIORITY 0 +#endif + +// NAND2 DMA priority (0..3|lowest..highest). +#if !defined(STM32_NAND_NAND2_DMA_PRIORITY) +#define STM32_NAND_NAND2_DMA_PRIORITY 0 +#endif + +// DMA stream used for NAND operations. +// This option is only available on platforms with enhanced DMA. +#if !defined(STM32_NAND_DMA_STREAM) +#define STM32_NAND_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +#if !STM32_NAND_USE_FSMC_NAND1 && !STM32_NAND_USE_FSMC_NAND2 +#error "NAND driver activated but no NAND peripheral assigned" +#endif + +#if (STM32_NAND_USE_FSMC_NAND2 || STM32_NAND_USE_FSMC_NAND1) && !STM32_HAS_FSMC +#error "FSMC not present in the selected device" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// Type of a structure representing an NAND driver. +typedef struct NANDDriver NANDDriver; + +// Type of interrupt handler function. +typedef void (*nandisrhandler_t)(NANDDriver *nandp); + +// Driver configuration structure. +// It could be empty on some architectures. +typedef struct { + // Number of erase blocks in NAND device. + uint32_t blocks; + + // Number of data bytes in page. + uint32_t page_data_size; + + // Number of spare bytes in page. + uint32_t page_spare_size; + + // Number of pages in block. + uint32_t pages_per_block; + + // Number of write cycles for row addressing. + uint8_t rowcycles; + + // Number of write cycles for column addressing. + uint8_t colcycles; + + // End of the mandatory fields. + // Number of wait cycles. This value will be used both for + // PMEM and PATTR registers + // For proper calculation procedure please look at AN2784 document from STMicroelectronics + uint32_t pmem; + +} NANDConfig; + +// Structure representing an NAND driver. +struct NANDDriver { + // Driver state. + nandstate_t state; + + // Current configuration data. + const NANDConfig *config; + + // Array to store bad block map. +#if NAND_USE_MUTUAL_EXCLUSION +#if CH_CFG_USE_MUTEXES + // Mutex protecting the bus. + mutex_t mutex; +#elif CH_CFG_USE_SEMAPHORES + semaphore_t semaphore; +#endif +#endif // NAND_USE_MUTUAL_EXCLUSION + // End of the mandatory fields. + + // Function enabling interrupts from FSMC. + nandisrhandler_t isr_handler; + + // Pointer to current transaction buffer. + void *rxdata; + + // Current transaction length in bytes. + size_t datalen; + + // DMA mode bit mask. + uint32_t dmamode; + + // DMA channel. + const stm32_dma_stream_t *dma; + + // Thread waiting for I/O completion. + thread_t *thread; + + // Pointer to the FSMC NAND registers block. + FSMC_NAND_TypeDef *nand; + + // Memory mapping for data. + uint16_t *map_data; + + // Memory mapping for commands. + uint16_t *map_cmd; + + // Memory mapping for addresses. + uint16_t *map_addr; + +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32_NAND_USE_FSMC_NAND1 +extern NANDDriver NANDD1; +#endif + +#if STM32_NAND_USE_FSMC_NAND2 +extern NANDDriver NANDD2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + void fsmcNandInit(void); + void fsmcNandStart(NANDDriver *nandp); + void fsmcNandStop(NANDDriver *nandp); + uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen); + void nand_lld_read_data(NANDDriver *nandp, uint16_t *data, + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); + void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len); + void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd); + uint8_t nand_lld_write_data(NANDDriver *nandp, const uint16_t *data, + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); + uint8_t nand_lld_read_status(NANDDriver *nandp); + void nand_lld_reset(NANDDriver *nandp); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_NAND + +#endif // HAL_NAND_LLD_H_ diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c new file mode 100644 index 0000000000..a6b8377649 --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c @@ -0,0 +1,166 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess and Nick Klimov aka progfin +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + +#if (STM32_USE_FSMC_SDRAM == TRUE) + +#include "fsmc_sdram_lld.h" + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +// FMC_Command_Mode +#define FMCCM_NORMAL ((uint32_t)0x00000000) +#define FMCCM_CLK_ENABLED ((uint32_t)0x00000001) +#define FMCCM_PALL ((uint32_t)0x00000002) +#define FMCCM_AUTO_REFRESH ((uint32_t)0x00000003) +#define FMCCM_LOAD_MODE ((uint32_t)0x00000004) +#define FMCCM_SELFREFRESH ((uint32_t)0x00000005) +#define FMCCM_POWER_DOWN ((uint32_t)0x00000006) + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +// SDRAM driver identifier. +SDRAMDriver SDRAMD; + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Wait until the SDRAM controller is ready. +static void _sdram_wait_ready(void) { + // Wait until the SDRAM controller is ready + while (SDRAMD.sdram->SDSR & FMC_SDSR_BUSY); +} + +// Executes the SDRAM memory initialization sequence. +// cfgp pointer to the @p SDRAMConfig object +static void _sdram_init_sequence(const SDRAMConfig *cfgp) { + + uint32_t command_target = 0; + +#if STM32_SDRAM_USE_FSMC_SDRAM1 + command_target |= FMC_SDCMR_CTB1; +#endif +#if STM32_SDRAM_USE_FSMC_SDRAM2 + command_target |= FMC_SDCMR_CTB2; +#endif + + // Step 3: Configure a clock configuration enable command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_CLK_ENABLED | command_target; + + // Step 4: Insert delay (tipically 100uS). + osalThreadSleepMilliseconds(1); + + // Step 5: Configure a PALL (precharge all) command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_PALL | command_target; + + // Step 6.1: Configure a Auto-Refresh command: send the first command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_AUTO_REFRESH | command_target | + (cfgp->sdcmr & FMC_SDCMR_NRFS); + + // Step 6.2: Send the second command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_AUTO_REFRESH | command_target | + (cfgp->sdcmr & FMC_SDCMR_NRFS); + + // Step 7: Program the external memory mode register. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_LOAD_MODE | command_target | + (cfgp->sdcmr & FMC_SDCMR_MRD); + + // Step 8: Set clock. + _sdram_wait_ready(); + SDRAMD.sdram->SDRTR = cfgp->sdrtr & FMC_SDRTR_COUNT; + + _sdram_wait_ready(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver interrupt handlers. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level SDRAM driver initialization. + +void fsmcSdramInit(void) { + + stm32FsmcInit(); + + SDRAMD.sdram = FSMCD1.sdram; + SDRAMD.state = SDRAM_STOP; +} + +// Configures and activates the SDRAM peripheral. +// sdramp pointer to the @p SDRAMDriver object +// cfgp pointer to the @p SDRAMConfig object +void fsmcSdramStart(SDRAMDriver *sdramp, const SDRAMConfig *cfgp) { + + if (FSMCD1.state == FSMC_STOP) + fsmc_start(&FSMCD1); + + osalDbgAssert((sdramp->state == SDRAM_STOP) || (sdramp->state == SDRAM_READY), + "SDRAM. Invalid state."); + + if (sdramp->state == SDRAM_STOP) { + + // Even if you need only bank2 you must properly set up SDCR and SDTR + // regitsters for bank1 too. Both banks will be tuned equally assuming + // connected memory ICs are equal. + sdramp->sdram->SDCR1 = cfgp->sdcr; + sdramp->sdram->SDTR1 = cfgp->sdtr; + sdramp->sdram->SDCR2 = cfgp->sdcr; + sdramp->sdram->SDTR2 = cfgp->sdtr; + + _sdram_init_sequence(cfgp); + + sdramp->state = SDRAM_READY; + } +} + +// Deactivates the SDRAM peripheral. +// sdramp pointer to the @p SDRAMDriver object +void fsmcSdramStop(SDRAMDriver *sdramp) { + + uint32_t command_target = 0; + +#if STM32_SDRAM_USE_FSMC_SDRAM1 + command_target |= FMC_SDCMR_CTB1; +#endif +#if STM32_SDRAM_USE_FSMC_SDRAM2 + command_target |= FMC_SDCMR_CTB2; +#endif + + if (sdramp->state == SDRAM_READY) { + SDRAMD.sdram->SDCMR = FMCCM_POWER_DOWN | command_target; + sdramp->state = SDRAM_STOP; + } +} + +#endif // STM32_USE_FSMC_SDRAM + +#endif //STM32F427xx / STM32F429xx / STM32F437xx / STM32F439xx / STM32F745xx / STM32F746xx + // STM32F756xx / STM32F767xx / STM32F769xx / STM32F777xx / STM32F779xx diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h new file mode 100644 index 0000000000..3a1491b74b --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h @@ -0,0 +1,130 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess and Nick Klimov aka progfin +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_FMC_SDRAM_H_ +#define HAL_FMC_SDRAM_H_ + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + +#include "hal_stm32_fsmc.h" + +#if (STM32_USE_FSMC_SDRAM == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// +// Configuration options + +// SDRAM driver enable switch. +// If set to @p TRUE the support for SDRAM1 is included. +#if !defined(STM32_SDRAM_USE_FSMC_SDRAM1) +#define STM32_SDRAM_USE_FSMC_SDRAM1 FALSE +#else +#define STM32_SDRAM1_MAP_BASE FSMC_Bank5_MAP_BASE +#endif + +// SDRAM driver enable switch. +// If set to @p TRUE the support for SDRAM2 is included. +#if !defined(STM32_SDRAM_USE_FSMC_SDRAM2) +#define STM32_SDRAM_USE_FSMC_SDRAM2 FALSE +#else +#define STM32_SDRAM2_MAP_BASE FSMC_Bank6_MAP_BASE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +#if !STM32_SDRAM_USE_FSMC_SDRAM1 && !STM32_SDRAM_USE_FSMC_SDRAM2 +#error "SDRAM driver activated but no SDRAM peripheral assigned" +#endif + +#if (STM32_SDRAM_USE_FSMC_SDRAM1 || STM32_SDRAM_USE_FSMC_SDRAM2) && !STM32_HAS_FSMC +#error "FMC not present in the selected device" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// Driver state machine possible states. +typedef enum +{ + SDRAM_UNINIT = 0, //*< Not initialized. + SDRAM_STOP = 1, //*< Stopped. + SDRAM_READY = 2, //*< Ready. +} sdramstate_t; + +// Type of a structure representing an SDRAM driver. +typedef struct SDRAMDriver SDRAMDriver; + +// Driver configuration structure. +// It could be empty on some architectures. +typedef struct { + // SDRAM control register. + // Its value will be used for both banks. + uint32_t sdcr; + + // SDRAM timing register. + // Its value will be used for both banks. + uint32_t sdtr; + + // SDRAM command mode register. + // Only its MRD and NRFS bits will be used. + uint32_t sdcmr; + + // SDRAM refresh timer register. + // Only its COUNT bits will be used. + uint32_t sdrtr; + +} SDRAMConfig; + +// Structure representing an SDRAM driver. +struct SDRAMDriver { + // Driver state. + sdramstate_t state; + + // Pointer to the FMC SDRAM registers block. + FSMC_SDRAM_TypeDef *sdram; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +extern SDRAMDriver SDRAMD; + +#ifdef __cplusplus +extern "C" { +#endif + + void fsmcSdramInit(void); + void fsmcSdramStart(SDRAMDriver *sdramp, const SDRAMConfig *cfgp); + void fsmcSdramStop(SDRAMDriver *sdramp); + +#ifdef __cplusplus +} +#endif + +#endif // STM32_USE_FSMC_SDRAM + +#endif //STM32F427xx / STM32F429xx / STM32F437xx / STM32F439xx / STM32F745xx / STM32F746xx + // STM32F756xx / STM32F767xx / STM32F769xx / STM32F777xx / STM32F779xx + +#endif // HAL_FMC_SDRAM_H_ diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c new file mode 100644 index 0000000000..4e2cd5fc4d --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c @@ -0,0 +1,121 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" +#include "fsmc_sram_lld.h" + +#if (STM32_USE_FSMC_SRAM == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +// SRAM1 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM1 +SRAMDriver SRAMD1; +#endif + +// SRAM2 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM2 +SRAMDriver SRAMD2; +#endif + +// SRAM3 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM3 +SRAMDriver SRAMD3; +#endif + +// SRAM4 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM4 +SRAMDriver SRAMD4; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver interrupt handlers. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level SRAM driver initialization. +void fsmcSramInit(void) { + + stm32FsmcInit(); + +#if STM32_SRAM_USE_FSMC_SRAM1 + SRAMD1.sram = FSMCD1.sram1; + SRAMD1.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM1 */ + +#if STM32_SRAM_USE_FSMC_SRAM2 + SRAMD2.sram = FSMCD1.sram2; + SRAMD2.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM2 */ + +#if STM32_SRAM_USE_FSMC_SRAM3 + SRAMD3.sram = FSMCD1.sram3; + SRAMD3.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM3 */ + +#if STM32_SRAM_USE_FSMC_SRAM4 + SRAMD4.sram = FSMCD1.sram4; + SRAMD4.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM4 */ +} + +// Configures and activates the SRAM peripheral. +// sramp pointer to the @p SRAMDriver object +// cfgp pointer to the @p SRAMConfig object +void fsmcSramStart(SRAMDriver *sramp, const SRAMConfig *cfgp) { + + if (FSMCD1.state == FSMC_STOP) + fsmc_start(&FSMCD1); + + osalDbgAssert((sramp->state == SRAM_STOP) || (sramp->state == SRAM_READY), + "invalid state"); + + if (sramp->state == SRAM_STOP) { + sramp->sram->BTR = cfgp->btr; + sramp->sram->BWTR = cfgp->bwtr; + sramp->sram->BCR = cfgp->bcr | FSMC_BCR_MBKEN; + sramp->state = SRAM_READY; + } +} + +// Deactivates the SRAM peripheral. +// sramp pointer to the @p SRAMDriver object +void fsmcSramStop(SRAMDriver *sramp) { + + if (sramp->state == SRAM_READY) { + uint32_t mask = FSMC_BCR_MBKEN; + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + mask |= FSMC_BCR_CCLKEN; +#endif + + sramp->sram->BCR &= ~mask; + sramp->state = SRAM_STOP; + } +} + +#endif // STM32_USE_FSMC_SRAM */ diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h new file mode 100644 index 0000000000..fb2fbd9e38 --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h @@ -0,0 +1,130 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_FSMC_SRAM_H_ +#define HAL_FSMC_SRAM_H_ + +#include "hal_stm32_fsmc.h" + +#if (STM32_USE_FSMC_SRAM == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM1 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM1) +#define STM32_SRAM_USE_FSMC_SRAM1 FALSE +#endif + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM2 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM2) +#define STM32_SRAM_USE_FSMC_SRAM2 FALSE +#endif + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM3 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM3) +#define STM32_SRAM_USE_FSMC_SRAM3 FALSE +#endif + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM4 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM4) +#define STM32_SRAM_USE_FSMC_SRAM4 FALSE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +#if !STM32_SRAM_USE_FSMC_SRAM1 && !STM32_SRAM_USE_FSMC_SRAM2 && \ + !STM32_SRAM_USE_FSMC_SRAM3 && !STM32_SRAM_USE_FSMC_SRAM4 +#error "SRAM driver activated but no SRAM peripheral assigned" +#endif + +#if (STM32_SRAM_USE_FSMC_SRAM1 || STM32_SRAM_USE_FSMC_SRAM2 || \ + STM32_SRAM_USE_FSMC_SRAM3 || STM32_SRAM_USE_FSMC_SRAM4) && !STM32_HAS_FSMC +#error "FSMC not present in the selected device" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// Driver state machine possible states. +typedef enum { + SRAM_UNINIT = 0, // Not initialized + SRAM_STOP = 1, // Stopped + SRAM_READY = 2, // Ready +} sramstate_t; + +// Type of a structure representing an NAND driver. +typedef struct SRAMDriver SRAMDriver; + +// Driver configuration structure. +// It could be empty on some architectures. +// Some bits in BCR register will be forced by driver. +typedef struct { + uint32_t bcr; + uint32_t btr; + uint32_t bwtr; +} SRAMConfig; + +// Structure representing an NAND driver. +struct SRAMDriver { + // Driver state + sramstate_t state; + + // Pointer to the FSMC SRAM registers block. + FSMC_SRAM_NOR_TypeDef *sram; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32_SRAM_USE_FSMC_SRAM1 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD1; +#endif + +#if STM32_SRAM_USE_FSMC_SRAM2 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD2; +#endif + +#if STM32_SRAM_USE_FSMC_SRAM3 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD3; +#endif + +#if STM32_SRAM_USE_FSMC_SRAM4 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD4; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + void fsmcSramInit(void); + void fsmcSramStart(SRAMDriver *sramp, const SRAMConfig *cfgp); + void fsmcSramStop(SRAMDriver *sramp); + +#ifdef __cplusplus +} +#endif + +#endif // STM32_USE_FSMC_SRAM + +#endif // HAL_FSMC_SRAM_H_ diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c index d36408f86f..45626787a7 100644 --- a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c @@ -42,7 +42,10 @@ void halCommunityInit(void) { rngInit(); #endif +#if HAL_USE_FSMC + stm32FsmcInit(); +#endif + } #endif // HAL_USE_COMMUNITY - diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c new file mode 100644 index 0000000000..7e35c365ba --- /dev/null +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c @@ -0,0 +1,147 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" +#include "hal_stm32_fsmc.h" + +#if (HAL_USE_FSMC == TRUE) +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief FSMC1 driver identifier. + */ +#if STM32_FSMC_USE_FSMC1 +FSMCDriver FSMCD1; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level FSMC driver initialization. +void stm32FsmcInit(void) { + + if (FSMCD1.state == FSMC_UNINIT) { + FSMCD1.state = FSMC_STOP; + +#if STM32_SRAM_USE_FSMC_SRAM1 + FSMCD1.sram1 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE); +#endif + +#if STM32_SRAM_USE_FSMC_SRAM2 + FSMCD1.sram2 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE + 8); +#endif + +#if STM32_SRAM_USE_FSMC_SRAM3 + FSMCD1.sram3 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE + 8 * 2); +#endif + +#if STM32_SRAM_USE_FSMC_SRAM4 + FSMCD1.sram4 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE + 8 * 3); +#endif + +#if STM32_NAND_USE_FSMC_NAND1 + FSMCD1.nand1 = (FSMC_NAND_TypeDef *)FSMC_Bank2_R_BASE; +#endif + +#if STM32_NAND_USE_FSMC_NAND2 + FSMCD1.nand2 = (FSMC_NAND_TypeDef *)FSMC_Bank3_R_BASE; +#endif + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + #if STM32_USE_FSMC_SDRAM + FSMCD1.sdram = (FSMC_SDRAM_TypeDef *)FSMC_Bank5_6_R_BASE; + #endif +#endif + } +} + +// Configures and activates the FSMC peripheral. +// fsmcp pointer to the @p FSMCDriver object +void fsmc_start(FSMCDriver *fsmcp) { + + osalDbgAssert((fsmcp->state == FSMC_STOP) || (fsmcp->state == FSMC_READY), + "invalid state"); + + if (fsmcp->state == FSMC_STOP) { + /* Enables the peripheral.*/ +#if STM32_FSMC_USE_FSMC1 + if (&FSMCD1 == fsmcp) { +#ifdef rccResetFSMC + rccResetFSMC(); +#endif + rccEnableFSMC(FALSE); +#if HAL_USE_NAND + nvicEnableVector(STM32_FSMC_NUMBER, STM32_FSMC_FSMC1_IRQ_PRIORITY); +#endif + } +#endif /* STM32_FSMC_USE_FSMC1 */ + + fsmcp->state = FSMC_READY; + } +} + +// Deactivates the FSMC peripheral. +// emcp pointer to the @p FSMCDriver object +void fsmc_stop(FSMCDriver *fsmcp) { + + if (fsmcp->state == FSMC_READY) { + /* Resets the peripheral.*/ +#ifdef rccResetFSMC + rccResetFSMC(); +#endif + + /* Disables the peripheral.*/ +#if STM32_FSMC_USE_FSMC1 + if (&FSMCD1 == fsmcp) { +#if HAL_USE_NAND + nvicDisableVector(STM32_FSMC_NUMBER); +#endif + rccDisableFSMC(); + } +#endif /* STM32_FSMC_USE_FSMC1 */ + + fsmcp->state = FSMC_STOP; + } +} + +// FSMC shared interrupt handler. +CH_IRQ_HANDLER(STM32_FSMC_HANDLER) { + + CH_IRQ_PROLOGUE(); +#if STM32_NAND_USE_FSMC_NAND1 + if (FSMCD1.nand1->SR & FSMC_SR_ISR_MASK) { + NANDD1.isr_handler(&NANDD1); + } +#endif +#if STM32_NAND_USE_FSMC_NAND2 + if (FSMCD1.nand2->SR & FSMC_SR_ISR_MASK) { + NANDD2.isr_handler(&NANDD2); + } +#endif + CH_IRQ_EPILOGUE(); +} + +#endif /* HAL_USE_FSMC */