MDK分散加载:
默认情况下是通过MDK的option选项设置Flash和RAM大小,这种情况下所有的管理工作都是编译来处理的,
MDK自动生成的分散加载文件:H7_ProjectTest.sct
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00020000 { ; load region size_region
ER_IROM1 0x08000000 0x00020000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM2 0x24000000 0x00080000 {
.ANY (+RW +ZI)
}
}
看着这文件前需要先看下各RAM的地址和大小,工程使用的STM32H750VBT6
未全部写出,只写出了主要使用的部分
重新编写的MDK分散加载文件,后面示例使用的也是这个文件:stm32h750vb_user.sct
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; SRAM分散加载文件
; *************************************************************
LR_IROM1 0x08000000 0x00200000 { ; load region size_region;加载域
ER_IROM1 0x08000000 0x00200000 { ; load address = execution address;执行域对应H7的Flash地址和大小
*.o (RESET, +First);将启动文件 startup_stm32h743xx.s 有个段名为 RESET 的代码段(主要存储了中断向量表),将其存放在Flash
*(InRoot$$Sections);将将 MDK 的一些库文件全部放在根域,比如__main.o, _scatter*.o, _dc*.o
.ANY (+RO);将目标文件中所有具有 RO 只读属性的数据放在这里,即 ER_IROM1
}
; RW data - 128KB DTCM
RW_IRAM1 0x20000000 0x00020000 {
.ANY (+RW +ZI);将目标文件中所有具有 RW 和 ZI 数据放在这里
}
; RW data - 512KB AXI SRAM
RW_IRAM2 0x24000000 0x00080000 {
*(.RAM_D1);给这个域专门配了一个名字 .RAM_D1,这样就可以通过__attribute__((section("name")))将其分配到这个RAM域
}
; RW data - 128KB SRAM1(0x30000000) + 128KB SRAM2(0x3002 0000) + 32KB SRAM3(0x30040000)
RW_IRAM3 0x30000000 0x00048000 {
*(.RAM_D2)
}
; RW data - 64KB SRAM4(0x38000000)
RW_IRAM4 0x38000000 0x00010000 {
*(.RAM_D3)
}
}
注意:
__HAL_RCC_D2SRAM1_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
使用分散加载文件:
在定义变量时:
__attribute__((section(".RAM_D1"))) uint32_t AXISRAMBuf[10] = {0,0,0,0,0,0,0,0,0,0};//建议程序初始化后重新对变量进行初始化,否则该值有可能不确定
分散加载示例
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2023 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.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 */
__attribute__((section(".RAM_D1"))) uint32_t AXISRAMBuf[10] = {0,0,0,0,0,0,0,0,0,0};
__attribute__((section(".RAM_D1"))) uint16_t AXISRAMCount = 0;
__attribute__((section(".RAM_D2"))) uint32_t D2SRAMBuf[10] = {0,0,0,0,0,0,0,0,0,0};
__attribute__((section(".RAM_D2"))) uint16_t D2SRAMCount = 0;
__attribute__((section(".RAM_D3"))) uint32_t D3SRAMBuf[10] = {0,0,0,0,0,0,0,0,0,0};
__attribute__((section(".RAM_D3"))) uint16_t D3SRAMCount = 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();
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
__HAL_RCC_D2SRAM1_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
for(uint8_t i = 0;i < 10;i++)
{
AXISRAMBuf[i] = 0;
D2SRAMBuf[i] = 0;
D3SRAMBuf[i] = 0;
}
AXISRAMCount = 0;
D2SRAMCount = 0;
D3SRAMCount = 0;
/* 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_USART1_UART_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 */
printf("system\n");HAL_Delay(2000);
AXISRAMBuf[0]++;AXISRAMBuf[5]++;AXISRAMBuf[9]++;
D2SRAMBuf[0]++;D2SRAMBuf[5]++;D2SRAMBuf[9]++;
D3SRAMBuf[0]++;D3SRAMBuf[5]++;D3SRAMBuf[9]++;
AXISRAMCount += 5;
D2SRAMCount += 2;
D3SRAMCount += 1;
printf("AXISRAMBuf[0]=%d AXISRAMBuf[5]=%d AXISRAMBuf[9]=%d AXISRAMCount=%d\n",\
AXISRAMBuf[0],AXISRAMBuf[5],AXISRAMBuf[9],AXISRAMCount);HAL_Delay(100);
printf("D2SRAMBuf[0]=%d D2SRAMBuf[5]=%d D2SRAMBuf[9]=%d D2SRAMCount=%d\n",\
D2SRAMBuf[0],D2SRAMBuf[5],D2SRAMBuf[9],D2SRAMCount);HAL_Delay(100);
printf("D3SRAMBuf[0]=%d D3SRAMBuf[5]=%d D3SRAMBuf[9]=%d D3SRAMCount=%d\n",\
D3SRAMBuf[0],D3SRAMBuf[5],D3SRAMBuf[9],D3SRAMCount);HAL_Delay(100);
}
/* 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_SCALE0);
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_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 60;
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_4) != 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 = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
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 = 0x60000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256MB;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0x30000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
MPU_InitStruct.IsCacheable = MPU_ACCESS_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_NUMBER3;
MPU_InitStruct.BaseAddress = 0x30020000;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER4;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER5;
MPU_InitStruct.BaseAddress = 0x38000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;
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();
printf("Error_Handler\n");
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 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
注意,一定要在使用前进行单独初始化,否则会出现不定的初始值:
/* USER CODE BEGIN Init */
__HAL_RCC_D2SRAM1_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
// for(uint8_t i = 0;i < 10;i++)//使用前不对其重新初始化
// {
// AXISRAMBuf[i] = 0;
// D2SRAMBuf[i] = 0;
// D3SRAMBuf[i] = 0;
// }
AXISRAMCount = 0;
D2SRAMCount = 0;
D3SRAMCount = 0;
/* USER CODE END Init */
示例中的MPU配置为:
void MPU_Config(void)
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 = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
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 = 0x60000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256MB;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0x30000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
MPU_InitStruct.IsCacheable = MPU_ACCESS_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_NUMBER3;
MPU_InitStruct.BaseAddress = 0x30020000;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER4;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER5;
MPU_InitStruct.BaseAddress = 0x38000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
开启Cache指令
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
对TCM,SRAM进行内存动态分配实现
此处直接引用的安富莱例程:
rtx_lib.h
/*
*********************************************************************************************************
*
* 模块名称 : 动态内存管理
* 文件名称 : rtx_memory.h
* 版 本 : V1.0
* 说 明 : 将RTX5的动态内存管理整理出来, 可以管理多个内存块
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2018-04-09 Eric2013 将RTX5的动态内存管理整理出来
*
* Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
/*
* Copyright (c) 2013-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: RTX Library definitions
*
* -----------------------------------------------------------------------------
*/
#ifndef RTX_LIB_H_
#define RTX_LIB_H_
#include <string.h>
#include <stdint.h>
#include "stm32h7xx.h"
// Memory Pool Header structure
typedef struct {
uint32_t size; // Memory Pool size
uint32_t used; // Used Memory
} mem_head_t;
// Memory Block Header structure
typedef struct mem_block_s {
struct mem_block_s *next; // Next Memory Block in list
uint32_t info; // Block Info or max used Memory (in last block)
} mem_block_t;
// Memory Block Info: Length = <31:2>:'00', Type = <1:0>
#define MB_INFO_LEN_MASK 0xFFFFFFFCU // Length mask
#define MB_INFO_TYPE_MASK 0x00000003U // Type mask
// Memory Head Pointer
__STATIC_INLINE mem_head_t *MemHeadPtr (void *mem) {
//lint -e{9079} -e{9087} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
return ((mem_head_t *)mem);
}
// Memory Block Pointer
__STATIC_INLINE mem_block_t *MemBlockPtr (void *mem, uint32_t offset) {
uint32_t addr;
mem_block_t *ptr;
//lint --e{923} --e{9078} "cast between pointer and unsigned int" [MISRA Note 8]
addr = (uint32_t)mem + offset;
ptr = (mem_block_t *)addr;
return ptr;
}
// ==== Library functions ====
// Memory Heap Library functions
extern uint32_t osRtxMemoryInit (void *mem, uint32_t size);
extern void *osRtxMemoryAlloc(void *mem, uint32_t size, uint32_t type);
extern uint32_t osRtxMemoryFree (void *mem, void *block);
#endif // RTX_LIB_H_
rtx_memory.c
/*
*********************************************************************************************************
*
* 模块名称 : 动态内存管理
* 文件名称 : rtx_memory.c
* 版 本 : V1.0
* 说 明 : 将RTX5的动态内存管理整理出来, 可以管理多个内存块
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2018-04-09 Eric2013 将RTX5的动态内存管理整理出来
*
* Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
/*
* Copyright (c) 2013-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Memory functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Library functions ====
/// Initialize Memory Pool with variable block size.
/// \param[in] mem pointer to memory pool.
/// \param[in] size size of a memory pool in bytes.
/// \return 1 - success, 0 - failure.
__WEAK uint32_t osRtxMemoryInit (void *mem, uint32_t size) {
mem_head_t *head;
mem_block_t *ptr;
// Check parameters
//lint -e{923} "cast from pointer to unsigned int" [MISRA Note 7]
if ((mem == NULL) || (((uint32_t)mem & 7U) != 0U) || ((size & 7U) != 0U) ||
(size < (sizeof(mem_head_t) + (2U*sizeof(mem_block_t))))) {
//EvrRtxMemoryInit(mem, size, 0U);
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
return 0U;
}
// Initialize memory pool header
head = MemHeadPtr(mem);
head->size = size;
head->used = sizeof(mem_head_t) + sizeof(mem_block_t);
// Initialize first and last block header
ptr = MemBlockPtr(mem, sizeof(mem_head_t));
ptr->next = MemBlockPtr(mem, size - sizeof(mem_block_t));
ptr->next->next = NULL;
ptr->next->info = sizeof(mem_head_t) + sizeof(mem_block_t);
ptr->info = 0U;
//EvrRtxMemoryInit(mem, size, 1U);
return 1U;
}
/// Allocate a memory block from a Memory Pool.
/// \param[in] mem pointer to memory pool.
/// \param[in] size size of a memory block in bytes.
/// \param[in] type memory block type: 0 - generic, 1 - control block
/// \return allocated memory block or NULL in case of no memory is available.
__WEAK void *osRtxMemoryAlloc (void *mem, uint32_t size, uint32_t type) {
mem_block_t *ptr;
mem_block_t *p, *p_new;
uint32_t block_size;
uint32_t hole_size;
// Check parameters
if ((mem == NULL) || (size == 0U) || ((type & ~MB_INFO_TYPE_MASK) != 0U)) {
//EvrRtxMemoryAlloc(mem, size, type, NULL);
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
return NULL;
}
// Add block header to size
block_size = size + sizeof(mem_block_t);
// Make sure that block is 8-byte aligned
block_size = (block_size + 7U) & ~((uint32_t)7U);
// Search for hole big enough
p = MemBlockPtr(mem, sizeof(mem_head_t));
for (;;) {
//lint -e{923} -e{9078} "cast from pointer to unsigned int"
hole_size = (uint32_t)p->next - (uint32_t)p;
hole_size -= p->info & MB_INFO_LEN_MASK;
if (hole_size >= block_size) {
// Hole found
break;
}
p = p->next;
if (p->next == NULL) {
// Failed (end of list)
//EvrRtxMemoryAlloc(mem, size, type, NULL);
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
return NULL;
}
}
// Update used memory
(MemHeadPtr(mem))->used += block_size;
// Update max used memory
p_new = MemBlockPtr(mem, (MemHeadPtr(mem))->size - sizeof(mem_block_t));
if (p_new->info < (MemHeadPtr(mem))->used) {
p_new->info = (MemHeadPtr(mem))->used;
}
// Allocate block
if (p->info == 0U) {
// No block allocated, set info of first element
p->info = block_size | type;
ptr = MemBlockPtr(p, sizeof(mem_block_t));
} else {
// Insert new element into the list
p_new = MemBlockPtr(p, p->info & MB_INFO_LEN_MASK);
p_new->next = p->next;
p_new->info = block_size | type;
p->next = p_new;
ptr = MemBlockPtr(p_new, sizeof(mem_block_t));
}
//EvrRtxMemoryAlloc(mem, size, type, ptr);
return ptr;
}
/// Return an allocated memory block back to a Memory Pool.
/// \param[in] mem pointer to memory pool.
/// \param[in] block memory block to be returned to the memory pool.
/// \return 1 - success, 0 - failure.
__WEAK uint32_t osRtxMemoryFree (void *mem, void *block) {
const mem_block_t *ptr;
mem_block_t *p, *p_prev;
// Check parameters
if ((mem == NULL) || (block == NULL)) {
//EvrRtxMemoryFree(mem, block, 0U);
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
return 0U;
}
// Memory block header
ptr = MemBlockPtr(block, 0U);
ptr--;
// Search for block header
p_prev = NULL;
p = MemBlockPtr(mem, sizeof(mem_head_t));
while (p != ptr) {
p_prev = p;
p = p->next;
if (p == NULL) {
// Not found
//EvrRtxMemoryFree(mem, block, 0U);
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
return 0U;
}
}
// Update used memory
(MemHeadPtr(mem))->used -= p->info & MB_INFO_LEN_MASK;
// Free block
if (p_prev == NULL) {
// Release first block, only set info to 0
p->info = 0U;
} else {
// Discard block from chained list
p_prev->next = p->next;
}
//EvrRtxMemoryFree(mem, block, 1U);
return 1U;
}
main.c
/*
*********************************************************************************************************
*
* 模块名称 : 主程序模块
* 文件名称 : main.c
* 版 本 : V1.0
* 说 明 : TCM,SRAM等五块内存的动态内存分配实现。
* 实验目的:
* 1. 学习TCM,SRAM等五块内存的动态内存分配实现。
* 实验内容:
* 1. 启动自动重装软件定时器0,每100ms翻转一次LED2。
* 实验操作:
* 1. K1键按下,从DTCM依次申请280字节,64字节和6111字节。
* 2. K1键松开,释放从DTCM申请的空间。
* 3. K2键按下,从AXI SRAM依次申请160字节,32字节和2333字节。
* 4. K2键松开,释放从AXI SRAM申请的空间。
* 5. K3键按下,从D2域SRAM依次申请200字节,96字节和4111字节。
* 6. K3键松开,释放从D2域SRAM申请的空间。
* 7. 摇杆OK键按下,从D3域SRAM依次申请300字节,128字节和5111字节。
* 8. 摇杆OK键松开,释放从D3域SRAM申请的空间。
* 注意事项:
* 1. 本实验推荐使用串口软件SecureCRT查看打印信息,波特率115200,数据位8,奇偶校验位无,停止位1。
* 2. 务必将编辑器的缩进参数和TAB设置为4来阅读本文件,要不代码显示不整齐。
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2018-12-12 Eric2013 1. CMSIS软包版本 V5.4.0
* 2. HAL库版本 V1.3.0
*
* Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include "bsp.h" /* 底层硬件驱动 */
/* 定义例程名和例程发布日期 */
#define EXAMPLE_NAME "V7-TCM,SRAM等五块内存的动态内存分配实现"
#define EXAMPLE_DATE "2018-12-12"
#define DEMO_VER "1.0"
static void PrintfLogo(void);
static void PrintfHelp(void);
/* DTCM, 64KB */
mem_head_t *DTCMUsed;
uint64_t AppMallocDTCM[64*1024/8];
#if defined ( __ICCARM__ ) /* 使用的IAR */
/* D1域, AXI SRAM, 512KB */
mem_head_t *AXISRAMUsed;
#pragma location = 0x24000000
uint64_t AppMallocAXISRAM[512*1024/8];
/* D2域, 128KB SRAM1(0x30000000) + 128KB SRAM2(0x30020000) + 32KB SRAM3(0x30040000) */
mem_head_t *SRAM1Used;
#pragma location = 0x30000000
uint64_t AppMallocSRAM1[288*1024/8];
/* D3域, SRAM4, 64KB */
mem_head_t *SRAM4Used;
#pragma location = 0x38000000
uint64_t AppMallocSRAM4[64*1024/8];
#elif defined ( __CC_ARM ) /* 使用的MDK */
/* D1域, AXI SRAM, 512KB */
mem_head_t *AXISRAMUsed;
uint64_t AppMallocAXISRAM[512*1024/8]__attribute__((at(0x24000000)));
/* D2域, 128KB SRAM1(0x30000000) + 128KB SRAM2(0x30020000) + 32KB SRAM3(0x30040000) */
mem_head_t *SRAM1Used;
uint64_t AppMallocSRAM1[288*1024/8]__attribute__((at(0x30000000)));
/* D3域, SRAM4, 64KB */
mem_head_t *SRAM4Used;
uint64_t AppMallocSRAM4[64*1024/8]__attribute__((at(0x38000000)));
#endif
/*
*********************************************************************************************************
* 函 数 名: main
* 功能说明: c程序入口
* 形 参: 无
* 返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
uint8_t ucKeyCode; /* 按键代码 */
uint32_t *DTCM_Addres0, *AXISRAM_Addres0, *SRAM1_Addres0, *SRAM4_Addres0;
uint16_t *DTCM_Addres1, *AXISRAM_Addres1, *SRAM1_Addres1, *SRAM4_Addres1;
uint8_t *DTCM_Addres2, *AXISRAM_Addres2, *SRAM1_Addres2, *SRAM4_Addres2;
bsp_Init(); /* 硬件初始化 */
/* 初始化动态内存空间 */
osRtxMemoryInit(AppMallocDTCM, sizeof(AppMallocDTCM));
osRtxMemoryInit(AppMallocAXISRAM, sizeof(AppMallocAXISRAM));
osRtxMemoryInit(AppMallocSRAM1, sizeof(AppMallocSRAM1));
osRtxMemoryInit(AppMallocSRAM4, sizeof(AppMallocSRAM4));
PrintfLogo(); /* 打印例程名称和版本等信息 */
PrintfHelp(); /* 打印操作提示 */
bsp_StartAutoTimer(0, 100); /* 启动1个100ms的自动重装的定时器 */
/* 进入主程序循环体 */
while (1)
{
bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
/* 判断定时器超时时间 */
if (bsp_CheckTimer(0))
{
/* 每隔100ms 进来一次 */
bsp_LedToggle(2);
}
/* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */
ucKeyCode = bsp_GetKey(); /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
if (ucKeyCode != KEY_NONE)
{
switch (ucKeyCode)
{
/* 从DTCM依次申请280字节,64字节和6111字节 */
case KEY_DOWN_K1:
/* 从DTCM申请280字节空间,使用指针变量DTCM_Addres0操作这些空间时不要超过280字节大小 */
printf("=========================================================\r\n");
DTCM_Addres0 = osRtxMemoryAlloc(AppMallocDTCM, 280, 0);
DTCMUsed = MemHeadPtr(AppMallocDTCM);
printf("DTCM总大小 = %d字节,申请大小 = 0280字节,当前共使用大小 = %d字节\r\n",
DTCMUsed->size, DTCMUsed->used);
/* 从DTCM申请64字节空间,使用指针变量DTCM_Addres1操作这些空间时不要超过64字节大小 */
DTCM_Addres1 = osRtxMemoryAlloc(AppMallocDTCM, 64, 0);
DTCMUsed = MemHeadPtr(AppMallocDTCM);
printf("DTCM总大小 = %d字节,申请大小 = 0064字节,当前共使用大小 = %d字节\r\n",
DTCMUsed->size, DTCMUsed->used);
/* 从DTCM申请6111字节空间,使用指针变量DTCM_Addres2操作这些空间时不要超过6111字节大小 */
DTCM_Addres2 = osRtxMemoryAlloc(AppMallocDTCM, 6111, 0);
DTCMUsed = MemHeadPtr(AppMallocDTCM);
printf("DTCM总大小 = %d字节,申请大小 = 6111字节,当前共使用大小 = %d字节\r\n",
DTCMUsed->size, DTCMUsed->used);
break;
/* 释放从DTCM申请的空间 */
case KEY_UP_K1:
/* 释放从DTCM申请的280字节空间 */
osRtxMemoryFree(AppMallocDTCM, DTCM_Addres0);
DTCMUsed = MemHeadPtr(AppMallocDTCM);
printf("释放DTCM动态内存区申请的0280字节,当前共使用大小 = %d字节\r\n", DTCMUsed->used);
/* 释放从DTCM申请的64字节空间 */
osRtxMemoryFree(AppMallocDTCM, DTCM_Addres1);
DTCMUsed = MemHeadPtr(AppMallocDTCM);
printf("释放DTCM动态内存区申请的0064字节,当前共使用大小 = %d字节\r\n", DTCMUsed->used);
/* 释放从DTCM申请的6111字节空间 */
osRtxMemoryFree(AppMallocDTCM, DTCM_Addres2);
DTCMUsed = MemHeadPtr(AppMallocDTCM);
printf("释放DTCM动态内存区申请的6111字节,当前共使用大小 = %d字节\r\n", DTCMUsed->used);
break;
/* 从AXI SRAM依次申请160字节,32字节和2333字节 */
case KEY_DOWN_K2:
/* 从AXI SRAM 申请160字节空间,使用指针变量AXISRAM_Addres0操作这些空间时不要超过160字节大小 */
printf("=========================================================\r\n");
AXISRAM_Addres0 = osRtxMemoryAlloc(AppMallocAXISRAM, 160, 0);
AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);
printf("AXI SRAM总大小 = %d字节,申请大小 = 0162字节,当前共使用大小 = %d字节\r\n",
AXISRAMUsed->size, AXISRAMUsed->used);
/* 从AXI SRAM 申请32字节空间,使用指针变量AXISRAM_Addres1操作这些空间时不要超过32字节大小 */
AXISRAM_Addres1 = osRtxMemoryAlloc(AppMallocAXISRAM, 32, 0);
AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);
printf("AXI SRAM总大小 = %d字节,申请大小 = 0032字节,当前共使用大小 = %d字节\r\n",
AXISRAMUsed->size, AXISRAMUsed->used);
/* 从AXI SRAM 申请2333字节空间,使用指针变量AXISRAM_Addres2操作这些空间时不要超过2333字节大小 */
AXISRAM_Addres2 = osRtxMemoryAlloc(AppMallocAXISRAM, 2333, 0);
AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);
printf("AXI SRAM总大小 = %d字节,申请大小 = 2333字节,当前共使用大小 = %d字节\r\n",
AXISRAMUsed->size, AXISRAMUsed->used);
break;
/* 释放从AXI SRAM申请的空间 */
case KEY_UP_K2:
/* 释放从AXI SRAM申请的160字节空间 */
osRtxMemoryFree(AppMallocAXISRAM, AXISRAM_Addres0);
AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);
printf("释放AXI SRAM动态内存区申请的0160字节,当前共使用大小 = %d字节\r\n", AXISRAMUsed->used);
/* 释放从AXI SRAM申请的32字节空间 */
osRtxMemoryFree(AppMallocAXISRAM, AXISRAM_Addres1);
AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);
printf("释放AXI SRAM动态内存区申请的0032字节,当前共使用大小 = %d字节\r\n", AXISRAMUsed->used);
/* 释放从AXI SRAM申请的2333字节空间 */
osRtxMemoryFree(AppMallocAXISRAM, AXISRAM_Addres2);
AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);
printf("释放AXI SRAM动态内存区申请的2333字节,当前共使用大小 = %d字节\r\n", AXISRAMUsed->used);
break;
/* 从D2域SRAM依次申请200字节,96字节和4111字节 */
case KEY_DOWN_K3:
/* 从D2域的SRAM申请200字节空间,使用指针变量SRAM1_Addres0操作这些空间时不要超过200字节大小 */
printf("=========================================================\r\n");
SRAM1_Addres0 = osRtxMemoryAlloc(AppMallocSRAM1, 200, 0);
SRAM1Used = MemHeadPtr(AppMallocSRAM1);
printf("D2域SRAM总大小 = %d字节,申请大小 = 0200字节,当前共使用大小 = %d字节\r\n",
SRAM1Used->size, SRAM1Used->used);
/* 从D2域的SRAM申请96字节空间,使用指针变量SRAM1_Addres1操作这些空间时不要超过96字节大小 */
SRAM1_Addres1 = osRtxMemoryAlloc(AppMallocSRAM1, 96, 0);
SRAM1Used = MemHeadPtr(AppMallocSRAM1);
printf("D2域SRAM总大小 = %d字节,申请大小 = 0096字节,当前共使用大小 = %d字节\r\n",
SRAM1Used->size, SRAM1Used->used);
/* 从D2域的SRAM申请4111字节空间,使用指针变量SRAM1_Addres2操作这些空间时不要超过4111字节大小 */
SRAM1_Addres2 = osRtxMemoryAlloc(AppMallocSRAM1, 4111, 0);
SRAM1Used = MemHeadPtr(AppMallocSRAM1);
printf("D2域SRAM总大小 = %d字节,申请大小 = 4111字节,当前共使用大小 = %d字节\r\n",
SRAM1Used->size, SRAM1Used->used);
break;
/* 释放从D2域SRAM申请的空间 */
case KEY_UP_K3:
/* 释放从D2域的SRAM申请的200字节空间 */
osRtxMemoryFree(AppMallocSRAM1, SRAM1_Addres0);
SRAM1Used = MemHeadPtr(AppMallocSRAM1);
printf("释放D2域SRAM动态内存区申请的0200字节,当前共使用大小 = %d字节\r\n", SRAM1Used->used);
/* 释放从D2域的SRAM申请的96字节空间 */
osRtxMemoryFree(AppMallocSRAM1, SRAM1_Addres1);
SRAM1Used = MemHeadPtr(AppMallocSRAM1);
printf("释放D2域SRAM动态内存区申请的0096字节,当前共使用大小 = %d字节\r\n", SRAM1Used->used);
/* 释放从D2域的SRAM申请的4111字节空间 */
osRtxMemoryFree(AppMallocSRAM1, SRAM1_Addres2);
SRAM1Used = MemHeadPtr(AppMallocSRAM1);
printf("释放D2域SRAM动态内存区申请的4111字节,当前共使用大小 = %d字节\r\n", SRAM1Used->used);
break;
/* 从D3域SRAM依次申请300字节,128字节和5111字节 */
case JOY_DOWN_OK:
/* 从D3域的SRAM申请300字节空间,使用指针变量SRAM4_Addres0操作这些空间时不要超过300字节大小 */
printf("=========================================================\r\n");
SRAM4_Addres0 = osRtxMemoryAlloc(AppMallocSRAM4, 300, 0);
SRAM4Used = MemHeadPtr(AppMallocSRAM4);
printf("D3域SRAM总大小 = %d字节,申请大小 = 0300字节,当前共使用大小 = %d字节\r\n",
SRAM4Used->size, SRAM4Used->used);
/* 从D3域的SRAM申请96字节空间,使用指针变量SRAM4_Addres1操作这些空间时不要超过96字节大小 */
SRAM4_Addres1 = osRtxMemoryAlloc(AppMallocSRAM4, 128, 0);
SRAM4Used = MemHeadPtr(AppMallocSRAM4);
printf("D3域SRAM总大小 = %d字节,申请大小 = 0128字节,当前共使用大小 = %d字节\r\n",
SRAM4Used->size, SRAM4Used->used);
/* 从D3域的SRAM申请5111字节空间,使用指针变量SRAM4_Addres2操作这些空间时不要超过5111字节大小 */
SRAM4_Addres2 = osRtxMemoryAlloc(AppMallocSRAM4, 5111, 0);
SRAM4Used = MemHeadPtr(AppMallocSRAM4);
printf("D3域SRAM总大小 = %d字节,申请大小 = 5111字节,当前共使用大小 = %d字节\r\n",
SRAM4Used->size, SRAM4Used->used);
break;
/* 释放从D3域SRAM申请的空间 */
case JOY_UP_OK:
/* 释放从D3域的SRAM申请的300字节空间 */
osRtxMemoryFree(AppMallocSRAM4, SRAM4_Addres0);
SRAM4Used = MemHeadPtr(AppMallocSRAM4);
printf("释放D3域SRAM动态内存区申请的0300字节,当前共使用大小 = %d字节\r\n", SRAM4Used->used);
/* 释放从D3域的SRAM申请的128字节空间 */
osRtxMemoryFree(AppMallocSRAM4, SRAM4_Addres1);
SRAM4Used = MemHeadPtr(AppMallocSRAM4);
printf("释放D3域SRAM动态内存区申请的0128字节,当前共使用大小 = %d字节\r\n", SRAM4Used->used);
/* 释放从D3域的SRAM申请的5111字节空间 */
osRtxMemoryFree(AppMallocSRAM4, SRAM4_Addres2);
SRAM4Used = MemHeadPtr(AppMallocSRAM4);
printf("释放D3域SRAM动态内存区申请的5111字节,当前共使用大小 = %d字节\r\n", SRAM4Used->used);
break;
default:
/* 其它的键值不处理 */
break;
}
}
}
}
/*
*********************************************************************************************************
* 函 数 名: PrintfHelp
* 功能说明: 打印操作提示
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void PrintfHelp(void)
{
printf("操作提示:\r\n");
printf("1. K1键按下,从DTCM依次申请280字节,64字节和6111字节\r\n");
printf("2. K1键松开,释放从DTCM申请的空间\r\n");
printf("3. K2键按下,从AXI SRAM依次申请160字节,32字节和2333字节\r\n");
printf("4. K2键松开,释放从AXI SRAM申请的空间\r\n");
printf("5. K3键按下,从D2域SRAM依次申请200字节,96字节和4111字节\r\n");
printf("6. K3键松开,释放从D2域SRAM申请的空间\r\n");
printf("7. 摇杆OK键按下,从D3域SRAM依次申请300字节,128字节和5111字节\r\n");
printf("8. 摇杆OK键松开,释放从D3域SRAM申请的空间\r\n");
}
/*
*********************************************************************************************************
* 函 数 名: PrintfLogo
* 功能说明: 打印例程名称和例程发布日期, 接上串口线后,打开PC机的超级终端软件可以观察结果
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void PrintfLogo(void)
{
printf("*************************************************************\n\r");
/* 检测CPU ID */
{
uint32_t CPU_Sn0, CPU_Sn1, CPU_Sn2;
CPU_Sn0 = *(__IO uint32_t*)(0x1FF1E800);
CPU_Sn1 = *(__IO uint32_t*)(0x1FF1E800 + 4);
CPU_Sn2 = *(__IO uint32_t*)(0x1FF1E800 + 8);
printf("\r\nCPU : STM32H743XIH6, BGA240, 主频: %dMHz\r\n", SystemCoreClock / 1000000);
printf("UID = %08X %08X %08X\n\r", CPU_Sn2, CPU_Sn1, CPU_Sn0);
}
printf("\n\r");
printf("*************************************************************\n\r");
printf("* 例程名称 : %s\r\n", EXAMPLE_NAME); /* 打印例程名称 */
printf("* 例程版本 : %s\r\n", DEMO_VER); /* 打印例程版本 */
printf("* 发布日期 : %s\r\n", EXAMPLE_DATE); /* 打印例程日期 */
/* 打印ST的HAL库版本 */
printf("* HAL库版本 : V1.3.0 (STM32H7xx HAL Driver)\r\n");
printf("* \r\n"); /* 打印一行空格 */
printf("* QQ : 1295744630 \r\n");
printf("* 旺旺 : armfly\r\n");
printf("* Email : armfly@qq.com \r\n");
printf("* 微信公众号: armfly_com \r\n");
printf("* 淘宝店: armfly.taobao.com\r\n");
printf("* Copyright www.armfly.com 安富莱电子\r\n");
printf("*************************************************************\n\r");
}
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
此处建议直接参考安富莱原文