From 29316de9d8c7df0216f0f4e4381ba865177f6a6a Mon Sep 17 00:00:00 2001 From: Davide Schiavone Date: Thu, 27 Jul 2023 14:11:52 +0200 Subject: [PATCH] [app] fix APPs on flash_exec (#357) * fix race condition on GPIO * fix example_spi_host * fix example_spi_host_dma * fix example_spi_host_dma_power_gate --- .../example_power_gating_core/main.c | 8 +-- sw/applications/example_spi_host/main.c | 39 +++++++++--- sw/applications/example_spi_host_dma/main.c | 60 +++++++++++++------ .../example_spi_host_dma_power_gate/main.c | 39 ++++++++---- 4 files changed, 103 insertions(+), 43 deletions(-) diff --git a/sw/applications/example_power_gating_core/main.c b/sw/applications/example_power_gating_core/main.c index 1c284c51a..63e88d31e 100644 --- a/sw/applications/example_power_gating_core/main.c +++ b/sw/applications/example_power_gating_core/main.c @@ -166,14 +166,14 @@ int main(int argc, char *argv[]) plic_irq_set_priority(GPIO_INTR_31, 1); plic_irq_set_enabled(GPIO_INTR_31, kPlicToggleEnabled); - gpio_cfg_t pin1_cfg = {.pin = GPIO_TB_OUT, .mode = GpioModeOutPushPull}; - gpio_config (pin1_cfg); - gpio_write(GPIO_TB_OUT, true); - gpio_cfg_t pin2_cfg = {.pin = GPIO_TB_IN, .mode = GpioModeIn,.en_input_sampling = true, .en_intr = true, .intr_type = GpioIntrEdgeRising}; gpio_config (pin2_cfg); + gpio_cfg_t pin1_cfg = {.pin = GPIO_TB_OUT, .mode = GpioModeOutPushPull}; + gpio_config (pin1_cfg); + gpio_write(GPIO_TB_OUT, true); + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); if (power_gate_core(&power_manager, kPlic_pm_e, &power_manager_cpu_counters) != kPowerManagerOk_e) { diff --git a/sw/applications/example_spi_host/main.c b/sw/applications/example_spi_host/main.c index 8b7745cee..18f9154c2 100644 --- a/sw/applications/example_spi_host/main.c +++ b/sw/applications/example_spi_host/main.c @@ -24,9 +24,9 @@ #define DEFAULT_PRINTF_BEHAVIOR 1 /* By default, printfs are activated for FPGA and disabled for simulation. */ -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_PYNQ_Z2 #define ENABLE_PRINTF DEFAULT_PRINTF_BEHAVIOR -#else +#else #define ENABLE_PRINTF !DEFAULT_PRINTF_BEHAVIOR #endif @@ -34,14 +34,14 @@ #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) -#endif +#endif // Simple example to check the SPI host peripheral is working. It checks the ram and flash have the same content #define REVERT_24b_ADDR(addr) ((((uint32_t)(addr) & 0xff0000) >> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) #define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) -int8_t spi_intr_flag; +volatile int8_t spi_intr_flag; spi_host_t spi_host; uint32_t flash_data[8]; uint32_t flash_original[8] = {1}; @@ -69,14 +69,30 @@ int main(int argc, char *argv[]) soc_ctrl_t soc_ctrl; soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t read_byte_cmd = ((REVERT_24b_ADDR(flash_original) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order -#ifdef USE_SPI_FLASH if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { +#ifdef USE_SPI_FLASH PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); return EXIT_SUCCESS; - } +#else + /* + if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different + as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH + */ + uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; + for(int i =0; i < 8 ; i++){ + flash_original[i] = ptr_flash[i]; + } + // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS + read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order + #endif + + } + + // spi_host_t spi_host; #ifndef USE_SPI_FLASH spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); @@ -155,7 +171,6 @@ int main(int argc, char *argv[]) volatile uint32_t data_addr = flash_original; - const uint32_t read_byte_cmd = ((REVERT_24b_ADDR(flash_original) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order // Fill TX FIFO with TX data (read command + 3B address) spi_write_word(&spi_host, read_byte_cmd); @@ -210,8 +225,14 @@ int main(int argc, char *argv[]) // spi_wait_for_rx_watermark(&spi_host); // or wait for SPI interrupt PRINTF("Waiting for SPI...\n\r"); - while(spi_intr_flag==0) { - wait_for_interrupt(); + + while( spi_intr_flag == 0 ) { + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + + if( spi_intr_flag == 0 ) + wait_for_interrupt(); + + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); } // Enable event interrupt diff --git a/sw/applications/example_spi_host_dma/main.c b/sw/applications/example_spi_host_dma/main.c index 9d43f42b8..3848f40a6 100644 --- a/sw/applications/example_spi_host_dma/main.c +++ b/sw/applications/example_spi_host_dma/main.c @@ -25,9 +25,9 @@ #define DEFAULT_PRINTF_BEHAVIOR 1 /* By default, printfs are activated for FPGA and disabled for simulation. */ -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_PYNQ_Z2 #define ENABLE_PRINTF DEFAULT_PRINTF_BEHAVIOR -#else +#else #define ENABLE_PRINTF !DEFAULT_PRINTF_BEHAVIOR #endif @@ -35,7 +35,7 @@ #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) -#endif +#endif // Type of data frome the SPI. For types different than words the SPI data is requested in separate transactions // word(0), half-word(1), byte(2,3) @@ -48,7 +48,7 @@ #define REVERT_24b_ADDR(addr) ((((uint32_t)(addr) & 0xff0000) >> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) -int8_t dma_intr_flag; +volatile int8_t dma_intr_flag; spi_host_t spi_host; void dma_intr_handler_trans_done(void) @@ -77,15 +77,26 @@ int main(int argc, char *argv[]) soc_ctrl_t soc_ctrl; soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t read_byte_cmd; -#ifdef USE_SPI_FLASH if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { +#ifdef USE_SPI_FLASH PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); return EXIT_SUCCESS; - } +#else + /* + if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different + as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH + */ + uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; + for(int i =0; i < COPY_DATA_NUM ; i++){ + flash_data[i] = ptr_flash[i]; + } #endif + } + #ifndef USE_SPI_FLASH spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); @@ -125,12 +136,12 @@ int main(int argc, char *argv[]) #endif static dma_target_t tgt_src = { - .inc_du = 0, + .inc_du = 0, .size_du = COPY_DATA_NUM, .type = SPI_DATA_TYPE, }; - tgt_src.ptr = fifo_ptr_rx; // Necessary outside 'cause its not a const. - tgt_src.trig = slot;// Necessary outside 'cause its not a const. + tgt_src.ptr = fifo_ptr_rx; // Necessary outside 'cause its not a const. + tgt_src.trig = slot;// Necessary outside 'cause its not a const. static dma_target_t tgt_dst = { .ptr = copy_data, @@ -150,7 +161,7 @@ int main(int argc, char *argv[]) PRINTF("Result - tgt trans: %u\n\r", res ); res = dma_load_transaction(&trans); PRINTF("Result - tgt load: %u\n\r", res ); - + // Configure SPI clock // SPI clk freq = 1/2 core clk freq when clk_div = 0 // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 @@ -205,13 +216,18 @@ int main(int argc, char *argv[]) .direction = kSpiDirTxOnly }); - uint32_t read_byte_cmd; dma_intr_flag = 0; res = dma_launch(&trans); PRINTF("launched!\n\r"); #if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - read_byte_cmd = ((REVERT_24b_ADDR(flash_data) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order + + if(get_spi_flash_mode(&soc_ctrl) != SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO) + read_byte_cmd = ((REVERT_24b_ADDR(flash_data) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order + else + // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS + read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order + const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Single transaction .len = COPY_DATA_NUM*sizeof(DATA_TYPE) - 1, // In bytes - 1 .csaat = false, @@ -234,11 +250,14 @@ int main(int argc, char *argv[]) DATA_TYPE* flash_ptr = (DATA_TYPE *)flash_data; for (int i = 0; i> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) -int8_t dma_intr_flag; +volatile int8_t dma_intr_flag; int8_t core_sleep_flag; spi_host_t spi_host; @@ -80,14 +80,24 @@ int main(int argc, char *argv[]) soc_ctrl_t soc_ctrl; soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - -#ifdef USE_SPI_FLASH + uint32_t read_byte_cmd; + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { +#ifdef USE_SPI_FLASH PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); return EXIT_SUCCESS; - } +#else + /* + if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different + as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH + */ + uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; + for(int i =0; i < COPY_DATA_NUM ; i++){ + flash_data[i] = ptr_flash[i]; + } #endif + } #ifndef USE_SPI_FLASH spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); @@ -111,7 +121,7 @@ int main(int argc, char *argv[]) // Enable interrupt on processor side // Enable global interrupt for machine-level interrupts CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - + // Set mie.MEIE bit to one to enable machine-level fast dma interrupt const uint32_t mask = 1 << 19; CSR_SET_BITS(CSR_REG_MIE, mask); @@ -225,14 +235,16 @@ int main(int argc, char *argv[]) .direction = kSpiDirTxOnly }); - uint32_t read_byte_cmd; - dma_intr_flag = 0; dma_launch(&trans); PRINTF("Launched\n\r"); #if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - read_byte_cmd = ((REVERT_24b_ADDR(flash_data) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order + if(get_spi_flash_mode(&soc_ctrl) != SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO) + read_byte_cmd = ((REVERT_24b_ADDR(flash_data) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order + else + // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS + read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Single transaction .len = COPY_DATA_NUM*sizeof(DATA_TYPE) - 1, // In bytes - 1 .csaat = false, @@ -255,7 +267,10 @@ int main(int argc, char *argv[]) DATA_TYPE* flash_ptr = (DATA_TYPE *)flash_data; for (int i = 0; i