Задать вопрос
  • Как запустить программу (XIP) из внешней QSPI FLASH STM32?

    @IvanVamDam Автор вопроса
    Я поэкспериментировал с частотой QSPI (понизил ее до 2.5 МГц) и о чудо, у меня начал исполняться код целевой программы, однако он вылетает на проверке латентности флеш в SystemInit функции:
    if(FLASH_LATENCY_DEFAULT  < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))


    Сама функция:

    void SystemInit (void)
    {
    #if defined (DATA_IN_D2_SRAM)
     __IO uint32_t tmpreg;
    #endif /* DATA_IN_D2_SRAM */
    
      /* FPU settings ------------------------------------------------------------*/
      #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
        SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2)));  /* set CP10 and CP11 Full Access */
      #endif
      /* Reset the RCC clock configuration to the default reset state ------------*/
    
       /* Increasing the CPU frequency */
      if(FLASH_LATENCY_DEFAULT  > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
      {
        /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
        MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
      }
    
      /* Set HSION bit */
      RCC->CR |= RCC_CR_HSION;
    
      /* Reset CFGR register */
      RCC->CFGR = 0x00000000;
    
      /* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
      RCC->CR &= 0xEAF6ED7FU;
    
       /* Decreasing the number of wait states because of lower CPU frequency */
      if(FLASH_LATENCY_DEFAULT  < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
      {
        /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
        MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
      }
    
    #if defined(D3_SRAM_BASE)
      /* Reset D1CFGR register */
      RCC->D1CFGR = 0x00000000;
    
      /* Reset D2CFGR register */
      RCC->D2CFGR = 0x00000000;
    
      /* Reset D3CFGR register */
      RCC->D3CFGR = 0x00000000;
    #else
      /* Reset CDCFGR1 register */
      RCC->CDCFGR1 = 0x00000000;
    
      /* Reset CDCFGR2 register */
      RCC->CDCFGR2 = 0x00000000;
    
      /* Reset SRDCFGR register */
      RCC->SRDCFGR = 0x00000000;
    #endif
      /* Reset PLLCKSELR register */
      RCC->PLLCKSELR = 0x02020200;
    
      /* Reset PLLCFGR register */
      RCC->PLLCFGR = 0x01FF0000;
      /* Reset PLL1DIVR register */
      RCC->PLL1DIVR = 0x01010280;
      /* Reset PLL1FRACR register */
      RCC->PLL1FRACR = 0x00000000;
    
      /* Reset PLL2DIVR register */
      RCC->PLL2DIVR = 0x01010280;
    
      /* Reset PLL2FRACR register */
    
      RCC->PLL2FRACR = 0x00000000;
      /* Reset PLL3DIVR register */
      RCC->PLL3DIVR = 0x01010280;
    
      /* Reset PLL3FRACR register */
      RCC->PLL3FRACR = 0x00000000;
    
      /* Reset HSEBYP bit */
      RCC->CR &= 0xFFFBFFFFU;
    
      /* Disable all interrupts */
      RCC->CIER = 0x00000000;
    
    #if (STM32H7_DEV_ID == 0x450UL)
      /* dual core CM7 or single core line */
      if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
      {
        /* if stm32h7 revY*/
        /* Change  the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
        *((__IO uint32_t*)0x51008108) = 0x000000001U;
      }
    #endif /* STM32H7_DEV_ID */
    
    #if defined(DATA_IN_D2_SRAM)
      /* in case of initialized data in D2 SRAM (AHB SRAM), enable the D2 SRAM clock (AHB SRAM clock) */
    #if defined(RCC_AHB2ENR_D2SRAM3EN)
      RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
    #elif defined(RCC_AHB2ENR_D2SRAM2EN)
      RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN);
    #else
      RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
    #endif /* RCC_AHB2ENR_D2SRAM3EN */
    
      tmpreg = RCC->AHB2ENR;
      (void) tmpreg;
    #endif /* DATA_IN_D2_SRAM */
    
    #if defined(DUAL_CORE) && defined(CORE_CM4)
      /* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
    #if defined(USER_VECT_TAB_ADDRESS)
      SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D2 AXI-RAM or in Internal FLASH */
    #endif /* USER_VECT_TAB_ADDRESS */
    
    #else
      /*
       * Disable the FMC bank1 (enabled after reset).
       * This, prevents CPU speculation access on this bank which blocks the use of FMC during
       * 24us. During this time the others FMC master (such as LTDC) cannot use it!
       */
      FMC_Bank1_R->BTCR[0] = 0x000030D2;
    
      /* Configure the Vector Table location -------------------------------------*/
    #if defined(USER_VECT_TAB_ADDRESS)
      SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */
    #endif /* USER_VECT_TAB_ADDRESS */
    
      RCC->CFGR = 0;
      SCB->VTOR = QSPI_BASE;
    
    #endif /*DUAL_CORE && CORE_CM4*/
    }


    Есть какие-нибудь идеи как бороться с данной проблемой?
    Написано
  • Как запустить программу (XIP) из внешней QSPI FLASH STM32?

    @IvanVamDam Автор вопроса
    Сразу, после заскока в область расположения целевой программы, из скрина вопроса виден обработчик прерывания в пространстве внешней памяти, но дальше программа не идет. По поводу HAL_Init, наверное, Вы правы, но я бы понял если бы программа дошагивала до туда, она же дропается на инициализации указателя стека.
    Написано
  • Как запустить программу (XIP) из внешней QSPI FLASH STM32?

    @IvanVamDam Автор вопроса
    Код целевой программы:

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2025 STMicroelectronics.
      * All rights reserved.
      *
      * This software is licensed under terms that can be found in the LICENSE file
      * in the root directory of this software component.
      * If no LICENSE file comes with this software, it is provided AS-IS.
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MPU_Config(void);
    static void MX_GPIO_Init(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
    
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MPU Configuration--------------------------------------------------------*/
      MPU_Config();
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      /* USER CODE BEGIN 2 */
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
    
    	  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
    	 	  HAL_Delay(1000);
      }
      /* USER CODE END 3 */
    }
    
    /**
      * @brief System Clock Configuration
      * @retval None
      */
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
      /** Supply configuration update enable
      */
      HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
    
      /** Configure the main internal regulator output voltage
      */
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
      while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
    
      /** Initializes the RCC Oscillators according to the specified parameters
      * in the RCC_OscInitTypeDef structure.
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLM = 2;
      RCC_OscInitStruct.PLL.PLLN = 64;
      RCC_OscInitStruct.PLL.PLLP = 2;
      RCC_OscInitStruct.PLL.PLLQ = 2;
      RCC_OscInitStruct.PLL.PLLR = 2;
      RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
      RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
      RCC_OscInitStruct.PLL.PLLFRACN = 0;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
    
      /** Initializes the CPU, AHB and APB buses clocks
      */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                                  |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
      RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /**
      * @brief GPIO Initialization Function
      * @param None
      * @retval None
      */
    static void MX_GPIO_Init(void)
    {
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      /* USER CODE BEGIN MX_GPIO_Init_1 */
    
      /* USER CODE END MX_GPIO_Init_1 */
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOH_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    
      /*Configure GPIO pin : PA1 */
      GPIO_InitStruct.Pin = GPIO_PIN_1;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*AnalogSwitch Config */
      HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PA1, SYSCFG_SWITCH_PA1_CLOSE);
    
      /* USER CODE BEGIN MX_GPIO_Init_2 */
    
      /* USER CODE END MX_GPIO_Init_2 */
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
     /* MPU Configuration */
    
    void MPU_Config(void)
    {
      MPU_Region_InitTypeDef MPU_InitStruct = {0};
    
      /* Disables the MPU */
      HAL_MPU_Disable();
    
      /** Initializes and configures the Region and the memory to be protected
      */
      MPU_InitStruct.Enable = MPU_REGION_ENABLE;
      MPU_InitStruct.Number = MPU_REGION_NUMBER0;
      MPU_InitStruct.BaseAddress = 0x0;
      MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
      MPU_InitStruct.SubRegionDisable = 0x87;
      MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
      MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
      MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
      MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
      MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
      MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    
      HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
      /** Initializes and configures the Region and the memory to be protected
      */
      MPU_InitStruct.Number = MPU_REGION_NUMBER1;
      MPU_InitStruct.BaseAddress = 0x90000000;
      MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
      MPU_InitStruct.SubRegionDisable = 0x0;
      MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
      MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
    
      HAL_MPU_ConfigRegion(&MPU_InitStruct);
      /* Enables the MPU */
      HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    
    }
    
    /**
      * @brief  This function is executed in case of error occurrence.
      * @retval None
      */
    void Error_Handler(void)
    {
      /* USER CODE BEGIN Error_Handler_Debug */
      /* User can add his own implementation to report the HAL error return state */
      __disable_irq();
      while (1)
      {
      }
      /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef  USE_FULL_ASSERT
    /**
      * @brief  Reports the name of the source file and the source line number
      *         where the assert_param error has occurred.
      * @param  file: pointer to the source file name
      * @param  line: assert_param error line source number
      * @retval None
      */
    void assert_failed(uint8_t *file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
         ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    Написано
  • Как запустить программу (XIP) из внешней QSPI FLASH STM32?

    @IvanVamDam Автор вопроса
    Код загрузчика:
    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2025 STMicroelectronics.
      * All rights reserved.
      *
      * This software is licensed under terms that can be found in the LICENSE file
      * in the root directory of this software component.
      * If no LICENSE file comes with this software, it is provided AS-IS.
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "quadspi.h"
    #include "gpio.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MPU_Config(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    typedef  void (*pFunction)(void);
    pFunction JumpToApplication;
    
    #define APPLICATION_ADDRESS 0x90000000U
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
    
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MPU Configuration--------------------------------------------------------*/
      MPU_Config();
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_QUADSPI_Init();
      /* USER CODE BEGIN 2 */
    
      CSP_QUADSPI_Init();
      CSP_QSPI_EnableMemoryMappedMode();
    
      // Disable the cache
      SCB_DisableDCache();
      SCB_DisableICache();
    
      // Disable the systick interrupt
      SysTick->CTRL = 0;
    
      /* Initialize user application's Stack Pointer & Jump to user application */
      JumpToApplication = (pFunction) (*(__IO uint32_t*) (APPLICATION_ADDRESS + 4));  // Reset Handler
      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);   // stack pointer
      JumpToApplication();	  // make the jump
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    
    /**
      * @brief System Clock Configuration
      * @retval None
      */
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
      /** Supply configuration update enable
      */
      HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
    
      /** Configure the main internal regulator output voltage
      */
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
      while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
    
      /** Initializes the RCC Oscillators according to the specified parameters
      * in the RCC_OscInitTypeDef structure.
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLM = 2;
      RCC_OscInitStruct.PLL.PLLN = 64;
      RCC_OscInitStruct.PLL.PLLP = 2;
      RCC_OscInitStruct.PLL.PLLQ = 80;
      RCC_OscInitStruct.PLL.PLLR = 2;
      RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
      RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
      RCC_OscInitStruct.PLL.PLLFRACN = 0;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
    
      /** Initializes the CPU, AHB and APB buses clocks
      */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                                  |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
      RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
     /* MPU Configuration */
    
    void MPU_Config(void)
    {
      MPU_Region_InitTypeDef MPU_InitStruct = {0};
    
      /* Disables the MPU */
      HAL_MPU_Disable();
    
      /** Initializes and configures the Region and the memory to be protected
      */
      MPU_InitStruct.Enable = MPU_REGION_ENABLE;
      MPU_InitStruct.Number = MPU_REGION_NUMBER0;
      MPU_InitStruct.BaseAddress = 0x00000000;
      MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
      MPU_InitStruct.SubRegionDisable = 0x87;
      MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
      MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
      MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
      MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
      MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
      MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
    
      HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
      /** Initializes and configures the Region and the memory to be protected
      */
      MPU_InitStruct.Number = MPU_REGION_NUMBER1;
      MPU_InitStruct.BaseAddress = 0x90000000;
      MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
      MPU_InitStruct.SubRegionDisable = 0x0;
      MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
      MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
      MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
      MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    
      HAL_MPU_ConfigRegion(&MPU_InitStruct);
      /* Enables the MPU */
      HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    
    }
    
    /**
      * @brief  This function is executed in case of error occurrence.
      * @retval None
      */
    void Error_Handler(void)
    {
      /* USER CODE BEGIN Error_Handler_Debug */
      /* User can add his own implementation to report the HAL error return state */
      __disable_irq();
      while (1)
      {
      }
      /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef  USE_FULL_ASSERT
    /**
      * @brief  Reports the name of the source file and the source line number
      *         where the assert_param error has occurred.
      * @param  file: pointer to the source file name
      * @param  line: assert_param error line source number
      * @retval None
      */
    void assert_failed(uint8_t *file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
         ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    Написано
  • Как запустить программу (XIP) из внешней QSPI FLASH STM32?

    @IvanVamDam Автор вопроса
    Ну я говорю, что даже до перемещения таблицы векторов прерывания во внешнюю память программа не доходит. Я ознакомился с примером, которым вы поделились. Реализовал у себя подобное:
    uint8_t a = 0;
    
    __attribute__((section(".extflash"))) void function_in_ext_flash(void)
    {
    
    	a += 1;
    }
    int main(void)
    {
     ...
     Конфигурирую периферию 
     ... 
    function_in_ext_flash();
    }

    Ну и да, функция во внешней флеш и все исполняется корректно:
    68623fce68552322658216.png
    Секцию extflash разметил в файле линковщика
    Написано
  • Как запустить программу (XIP) из внешней QSPI FLASH STM32?

    @IvanVamDam Автор вопроса
    zatim, Application Note на QSPI STM32 говорит, что по его адресному пространству можно исполняться, получается, что не надо копировать. Я лишь настраиваю Memory mapping, перед прыжком в область целевой программы (она же область QSPI), чтобы контроллер видел внешнюю QSPI флеш как внутреннюю. Так что да, я просто передаю управление регистру qspi. В целевой программе, я редактирую линкер скрипт, чтобы вся ее флеш была не внутренняя флеш контроллера ORIGIN = 0x0800 0000, SIZE = 2048, а внешняя ORIGIN = 0x9000 0000, SIZE = 8M, Также перед заходом в main() целевой прошивки переношу таблицу векторов по адресу 0x9000 0000, но это не влияет т.к. программа до этого момента не доходит.
    Написано