IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> IAR : STM32F407 memory management -> 正文阅读

[嵌入式]IAR : STM32F407 memory management

前言

以前工程用的是正点原子的内存管理组件。
这次加了2片SRAM, 在正点原子原版的内存管理组件上,将第2片SRAM的操作加上了。
在lite-os的任务中跑了一下,好使。

但是主内存只能管理20KB, 要不lite-os初始化卡死或任务建立失败。可能是lite-os配置中,不用的特性开多了,导致内存用量大。以后再研究, 看看将不用的特性关了或不建立那么多任务或事件看看。我主要用外挂的2片SRAM(每片1MB),也不在乎主内存用多了。下次换F429, 用SDRAM.

正点原子的实现是MDK版的,用在IAR工程时,全局数据(变量,数组,结构)定义要改下,否则编译不过。
在IAR中,指定数据不需要编译器初始化,指定物理地址时,和MDK工程中的语法是不一样的。

笔记

更新后的内存管理组件

内存管理组件管理 CCM, 主内存,外挂2片SRAM.

// @file inc_common.h
// @brief 公用头文件

#ifndef __INC_COMMON_H__
#define __INC_COMMON_H__

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#endif // #ifndef __INC_COMMON_H__

//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F407开发板
//内存管理 驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2014/5/15
//版本:V1.2
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//********************************************************************************
//V1.1 20140706
//1,修改部分函数名字,防止和其他代码的名字冲突(比如LWIP).
//2,修改内存池为32字节对齐
//V1.2 20140716
//1,修改my_mem_malloc函数,对于大内存分配错误的bug.
// 	 

// @file malloc.h

#ifndef __MALLOC_H
#define __MALLOC_H

#include "inc_common.h"

//定义三个内存池
#define SRAMCCM  0 // CCM内存池(此部分SRAM仅仅CPU可以访问!!!)
#define SRAMIN	 1 // 内部内存池
#define SRAMEX1  2 // 外部内存池1
#define SRAMEX2  3 // 外部内存池2

#define SRAMBANK 4 // 定义支持的SRAM块数.	

// MEM_CCM内存参数设定.mem3处于CCM,用于管理CCM(特别注意,这部分SRAM,仅CPU可以访问!!)
#define MEM_CCM_BLOCK_SIZE              32 // 内存块大小为32字节
#define MEM_CCM_MAX_SIZE                (60 * 1024) // 最大管理内存60K  (64KB - 内存管理用掉的%7的内存)
#define MEM_CCM_ALLOC_TABLE_SIZE        (MEM_CCM_MAX_SIZE / MEM_CCM_BLOCK_SIZE) // 内存表大小

// MEM_IN内存参数设定.mem1完全处于内部SRAM里面.
#define MEM_IN_BLOCK_SIZE               32 // 内存块大小为32字节

// 具体主内存可以管理多少KB, 要看map文件才知道
// 在.map的 "ENTRY LIST" 描述末尾,看用掉的主内存(0x2xxxxxxx)有多少,然后(128KB -  用掉的主内存大小) * (100% - 7%),就是可以管理的主内存用量

// 哪块内存用的大,看属性为Data,开始地址为0x2xxx,xxxx 的数据就知道
// e.g. Tx_Buff                 0x2000'3fd4  0x17d0  Data  Gb  ethernetif.o [1] // 这里在主内存(0x2xxx,xxxx)上用了6K多的内存

//[1] = z:\my_dev\x\Obj
//[2] = dl7M_tlf.a
//[3] = m7M_tls.a
//[4] = rt7M_tl.a
//[5] = shb_l.a
//
//  82'117 bytes of readonly  code memory
//  16'024 bytes of readonly  data memory
//  31'209 bytes of readwrite data memory // 总共用了31KB主内存

// 将基础组件都加完,然后看map文件的"ENTRY LIST"末尾的内存总用量, 计算用内存管理组件,可以管理的实际内存大小
// 可以用内存管理组件管理的内存用量(KB) = (128KB - 31KB) * (100% - 7%(内存管理块的估算大小)) = 97 * 0.93 = 90.21 => 90KB  - RTOS mem
// 主内存具体能管理多少, 需要实际试验才知道. 如果lite-os初始化卡或失败,或者建立任务失败,BOARD_SRAM_SIZE_KB 就要大些, 这里自己管理的内存(MEM_IN_MAX_SIZE)就再小点
// 最终将MEM_IN_MAX_SIZE调整成一个合适的KB数, 将剩余的主内存管理起来
#define MEM_IN_MAX_SIZE		        (20 * 1024) // 最大管理内存(HAL库, 基础组件(FATFS, LWIP, RTOS, 内存管理) 都用了一些,没有128KB可用)
#define MEM_IN_ALLOC_TABLE_SIZE         (MEM_IN_MAX_SIZE / MEM_IN_BLOCK_SIZE) // 内存表大小

// MEM_EX1内存参数设定.mem2的内存池处于外部SRAM里面(addr = 0x68000000)
#define MEM_EX1_BLOCK_SIZE              32 // 内存块大小为32字节
#define MEM_EX1_MAX_SIZE                (960 * 1024) // 最大管理内存960K (1024KB - 内存管理用掉的%7的内存)
#define MEM_EX1_ALLOC_TABLE_SIZE        (MEM_EX1_MAX_SIZE / MEM_EX1_BLOCK_SIZE) // 内存表大小

// MEM_EX2内存参数设定.mem2的内存池处于外部SRAM里面(addr = 0x6C000000)
#define MEM_EX2_BLOCK_SIZE              32 // 内存块大小为32字节
#define MEM_EX2_MAX_SIZE                (960 * 1024) // 最大管理内存960K (1024KB - 内存管理用掉的%7的内存)
#define MEM_EX2_ALLOC_TABLE_SIZE        (MEM_EX2_MAX_SIZE / MEM_EX2_BLOCK_SIZE) // 内存表大小

// 内存管理控制器
struct _m_mallco_dev
{
  void (*init)(uint8_t);        // 初始化
  uint8_t (*perused)(uint8_t);  // 内存使用率
  uint8_t* membase[SRAMBANK];   // 内存池 管理SRAMBANK个区域的内存
  uint16_t* memmap[SRAMBANK];   // 内存管理状态表
  uint8_t memrdy[SRAMBANK];    // 内存管理是否就绪
};
extern struct _m_mallco_dev mallco_dev; // 在mallco.c里面定义

void my_mem_init(uint8_t memx); // 内存管理初始化函数(外/内部调用)
void mymemset(void* s, uint8_t c, uint32_t count); // 设置内存
void mymemcpy(void* des, void* src, uint32_t n); // 复制内存     
uint32_t my_mem_malloc(uint8_t memx, uint32_t size); // 内存分配(内部调用)
uint8_t my_mem_free(uint8_t memx, uint32_t offset); // 内存释放(内部调用)
uint8_t my_mem_perused(uint8_t memx); // 获得内存使用率(外/内部调用) 


//用户调用函数
void myfree(uint8_t memx,void* ptr); // 内存释放(外部调用)
void* mymalloc(uint8_t memx, uint32_t size); // 内存分配(外部调用)
void* myrealloc(uint8_t memx, void* ptr, uint32_t size); // 重新分配内存(外部调用)

// 针对4块内存的用户调用函数, 省去了指定内存类型
void my_mem_init_CCM(); // 内存管理初始化函数(外/内部调用)
void myfree_CCM(void* ptr); // 内存释放(外部调用)
void* mymalloc_CCM(uint32_t size); // 内存分配(外部调用)
void* myrealloc_CCM(void* ptr, uint32_t size); // 重新分配内存(外部调用)
uint8_t my_mem_perused_CCM(); // 获得内存使用率(外/内部调用)

void my_mem_init_IN(); // 内存管理初始化函数(外/内部调用)
void myfree_IN(void* ptr); // 内存释放(外部调用)
void* mymalloc_IN(uint32_t size); // 内存分配(外部调用)
void* myrealloc_IN(void* ptr, uint32_t size); // 重新分配内存(外部调用)
uint8_t my_mem_perused_IN(); // 获得内存使用率(外/内部调用)

void my_mem_init_EX1(); // 内存管理初始化函数(外/内部调用)
void myfree_EX1(void* ptr); // 内存释放(外部调用)
void* mymalloc_EX1(uint32_t size); // 内存分配(外部调用)
void* myrealloc_EX1(void* ptr, uint32_t size); // 重新分配内存(外部调用)
uint8_t my_mem_perused_EX1(); // 获得内存使用率(外/内部调用)

void my_mem_init_EX2(); // 内存管理初始化函数(外/内部调用)
void myfree_EX2(void* ptr); // 内存释放(外部调用)
void* mymalloc_EX2(uint32_t size); // 内存分配(外部调用)
void* myrealloc_EX2(void* ptr, uint32_t size); // 重新分配内存(外部调用)
uint8_t my_mem_perused_EX2(); // 获得内存使用率(外/内部调用)

#endif // #ifndef __MALLOC_H

//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F407开发板
//内存管理 驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2014/5/15
//版本:V1.2
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//********************************************************************************
//V1.1 20140706
//1,修改部分函数名字,防止和其他代码的名字冲突(比如LWIP).
//2,修改内存池为32字节对齐
//V1.2 20140716
//1,修改my_mem_malloc函数,对于大内存分配错误的bug.
// 	 

// @file malloc.c

#include "malloc.h"

// 内存池(32字节对齐)
#pragma pack(32)

__no_init volatile
uint8_t membase_CCM[MEM_CCM_MAX_SIZE] @ 0X10000000; // 内部CCM内存池

// __no_init volatile 主内存让编译器去初始化
uint8_t membase_IN[MEM_IN_MAX_SIZE]; // 内部SRAM内存池

__no_init volatile
uint8_t membase_EX1[MEM_EX1_MAX_SIZE] @ 0X68000000; // 外部SRAM内存池1

__no_init volatile
uint8_t membase_EX2[MEM_EX2_MAX_SIZE] @ 0X6C000000; // 外部SRAM内存池1


// 内存管理表
__no_init volatile
uint16_t memmapbase_CCM[MEM_CCM_ALLOC_TABLE_SIZE] @ (0X10000000 + MEM_CCM_MAX_SIZE); // 内部CCM内存池MAP

__no_init volatile
uint16_t memmapbase_IN[MEM_IN_ALLOC_TABLE_SIZE]; // 内部SRAM内存池MAP

__no_init volatile
uint16_t memmapbase_EX1[MEM_EX1_ALLOC_TABLE_SIZE] @ (0X68000000 + MEM_EX1_MAX_SIZE); // 外部SRAM内存池MAP

__no_init volatile
uint16_t memmapbase_EX2[MEM_EX2_ALLOC_TABLE_SIZE] @ (0X6C000000 + MEM_EX2_MAX_SIZE); // 外部SRAM内存池MAP


// 内存管理参数	   
const uint32_t memtblsize[SRAMBANK] = {
  MEM_CCM_ALLOC_TABLE_SIZE,
  MEM_IN_ALLOC_TABLE_SIZE,
  MEM_EX1_ALLOC_TABLE_SIZE,
  MEM_EX2_ALLOC_TABLE_SIZE
}; // 内存表大小

const uint32_t memblksize[SRAMBANK] = {
  MEM_CCM_BLOCK_SIZE, 
  MEM_IN_BLOCK_SIZE, 
  MEM_EX1_BLOCK_SIZE,
  MEM_EX2_BLOCK_SIZE
}; // 内存分块大小

const uint32_t memsize[SRAMBANK] = {
  MEM_CCM_MAX_SIZE, 
  MEM_IN_MAX_SIZE, 
  MEM_EX1_MAX_SIZE,
  MEM_EX2_MAX_SIZE
}; // 内存总大小

#pragma pack()


// 内存管理控制器
struct _m_mallco_dev mallco_dev =
{
  my_mem_init, // 内存初始化
  my_mem_perused, // 内存使用率
  
  (uint8_t*)membase_CCM, 
  (uint8_t*)membase_IN, 
  (uint8_t*)membase_EX1, 
  (uint8_t*)membase_EX2, // 内存池
  
  (uint16_t*)memmapbase_CCM,
  (uint16_t*)memmapbase_IN,
  (uint16_t*)memmapbase_EX1, 
  (uint16_t*)memmapbase_EX2, // 内存管理状态表
  
  0,
  0,
  0, 
  0,// 内存管理未就绪
};

// 复制内存
// *des:目的地址
// *src:源地址
// n:需要复制的内存长度(字节为单位)
void mymemcpy(void* des, void* src, uint32_t n)  
{  
  uint8_t* xdes = des;
  uint8_t* xsrc = src;
  
  while(n--) {
    *xdes++ = *xsrc++;
  }
}

// 设置内存
// *s:内存首地址
// c :要设置的值
// count:需要设置的内存大小(字节为单位)
void mymemset(void* s, uint8_t c, uint32_t count)  
{  
  uint8_t* xs = s;
  
  while(count--) {
    *xs++ = c;
  }
}

// 内存管理初始化  
// memx:所属内存块
void my_mem_init(uint8_t memx)  
{  
  mymemset(mallco_dev.memmap[memx], 0, memtblsize[memx] * sizeof(uint16_t)); // 内存状态表数据清零  
  mymemset(mallco_dev.membase[memx], 0, memsize[memx]);	// 内存池所有数据清零  
  mallco_dev.memrdy[memx] = 1; // 内存管理初始化OK  
}

// 获取内存使用率
// memx:所属内存块
// 返回值:使用率(0~100)
uint8_t my_mem_perused(uint8_t memx)  
{  
  uint32_t used = 0;  
  uint32_t i = 0;  
  
  for (i = 0; i < memtblsize[memx]; i++)  
  {  
    if (mallco_dev.memmap[memx][i]) {
      used++;
    }
  } 
  
  return ((used * 100) / memtblsize[memx]);  
}

// 内存分配(内部调用)
// memx:所属内存块
// size:要分配的内存大小(字节)
// 返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 
uint32_t my_mem_malloc(uint8_t memx, uint32_t size)  
{  
  signed long offset = 0;  
  uint32_t nmemb = 0; // 需要的内存块数  
  uint32_t cmemb = 0; // 连续空内存块数
  uint32_t i = 0;  
  
  if (!mallco_dev.memrdy[memx]) {
    mallco_dev.init(memx); // 未初始化,先执行初始化 
  }
  
  if (0 == size) {
    return 0XFFFFFFFF;//不需要分配
  }
  
  nmemb = size / memblksize[memx]; // 获取需要分配的连续内存块数
  if (size % memblksize[memx]) {
    nmemb++;
  }
  
  for (offset = memtblsize[memx] - 1; offset >= 0; offset--) // 搜索整个内存控制区  
  {     
    if (!mallco_dev.memmap[memx][offset]) {
      cmemb++;//连续空内存块数增加
    } else {
      cmemb=0; // 连续内存块清零
    }
    
    if (cmemb == nmemb) // 找到了连续nmemb个空内存块
    {
      for (i = 0; i < nmemb; i++) // 标注内存块非空 
      {  
        mallco_dev.memmap[memx][offset + i] = nmemb;  
      }
      
      return (offset * memblksize[memx]); // 返回偏移地址  
    }
  }
  
  return 0XFFFFFFFF;//未找到符合分配条件的内存块  
}

// 释放内存(内部调用) 
// memx:所属内存块
// offset:内存地址偏移
// 返回值:0,释放成功;1,释放失败;  
uint8_t my_mem_free(uint8_t memx, uint32_t offset)  
{  
  int i = 0;  
  
  if (!mallco_dev.memrdy[memx]) // 未初始化,先执行初始化
  {
    mallco_dev.init(memx);    
    return 1; // 未初始化  
  }
  
  if (offset < memsize[memx]) // 偏移在内存池内. 
  {  
    int index = offset / memblksize[memx]; // 偏移所在内存块号码  
    int nmemb = mallco_dev.memmap[memx][index]; // 内存块数量
    for (i = 0; i < nmemb; i++) // 内存块清零
    {  
      mallco_dev.memmap[memx][index+i] = 0;  
    }
    
    return 0;  
  } else {
    return 2; // 偏移超区了.  
  }
}

// 释放内存(外部调用) 
// memx:所属内存块
// ptr:内存首地址 
void myfree(uint8_t memx, void* ptr)  
{  
  uint32_t offset = 0;   
  
  if (ptr == NULL) {
    return; // 地址为0.
  }
  
  offset = (uint32_t)ptr - (uint32_t)mallco_dev.membase[memx];     
  my_mem_free(memx,offset); // 释放内存      
}

// 分配内存(外部调用)
// memx:所属内存块
// size:内存大小(字节)
// 返回值:分配到的内存首地址.
void* mymalloc(uint8_t memx, uint32_t size)
{  
  uint32_t offset = 0;
  
  offset = my_mem_malloc(memx, size);
  if (0XFFFFFFFF == offset) {
    return NULL;
  } else {
    return (void*)((uint32_t)mallco_dev.membase[memx] + offset);
  }
}

// 重新分配内存(外部调用)
// memx:所属内存块
// *ptr:旧内存首地址
// size:要分配的内存大小(字节)
// 返回值:新分配到的内存首地址.
void* myrealloc(uint8_t memx, void* ptr, uint32_t size)  
{  
  uint32_t offset = 0;
  
  offset = my_mem_malloc(memx,size);   	
  if (0XFFFFFFFF == offset) {
    return NULL;
  } else{  									   
    mymemcpy((void*)((uint32_t)mallco_dev.membase[memx] + offset), ptr, size); // 拷贝旧内存内容到新内存   
    myfree(memx, ptr); // 释放旧内存
    return (void*)((uint32_t)mallco_dev.membase[memx] + offset); // 返回新内存首地址
  }  
}

void my_mem_init_CCM()
{
  my_mem_init(SRAMCCM);
}

void myfree_CCM(void* ptr)
{
  myfree(SRAMCCM, ptr);
}

void* mymalloc_CCM(uint32_t size)
{
  return mymalloc(SRAMCCM, size);
}

void* myrealloc_CCM(void* ptr, uint32_t size)
{
  return myrealloc(SRAMCCM, ptr, size);
}

uint8_t my_mem_perused_CCM()
{
  return my_mem_perused(SRAMCCM);
}

void my_mem_init_IN()
{
  my_mem_init(SRAMIN);
}

void myfree_IN(void* ptr)
{
  myfree(SRAMIN, ptr);
}

void* mymalloc_IN(uint32_t size)
{
  return mymalloc(SRAMIN, size);
}

void* myrealloc_IN(void* ptr, uint32_t size)
{
  return myrealloc(SRAMIN, ptr, size);
}

uint8_t my_mem_perused_IN()
{
  return my_mem_perused(SRAMIN);
}

void my_mem_init_EX1()
{
  my_mem_init(SRAMEX1);
}

void myfree_EX1(void* ptr)
{
  myfree(SRAMEX1, ptr);
}

void* mymalloc_EX1(uint32_t size)
{
  return mymalloc(SRAMEX1, size);
}

void* myrealloc_EX1(void* ptr, uint32_t size)
{
  return myrealloc(SRAMEX1, ptr, size);
}

uint8_t my_mem_perused_EX1()
{
  return my_mem_perused(SRAMEX1);
}

void my_mem_init_EX2()
{
  my_mem_init(SRAMEX2);
}

void myfree_EX2(void* ptr)
{
  myfree(SRAMEX2, ptr);
}

void* mymalloc_EX2(uint32_t size)
{
  return mymalloc(SRAMEX2, size);
}

void* myrealloc_EX2(void* ptr, uint32_t size)
{
  return myrealloc(SRAMEX2, ptr, size);
}

uint8_t my_mem_perused_EX2()
{
  return my_mem_perused(SRAMEX2);
}

测试代码

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 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 "lwip.h"
#include "sdio.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
#include "fsmc.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "malloc.h"
/* 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 MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void led_app_running()
{
  LOS_TaskDelay(1000);
  HAL_GPIO_WritePin(MCU_LED0_GPIO_Port, MCU_LED0_Pin, GPIO_PIN_SET); // on
  
  LOS_TaskDelay(1000);
  HAL_GPIO_WritePin(MCU_LED0_GPIO_Port, MCU_LED0_Pin, GPIO_PIN_RESET); // off
}

void led_app_stop()
{
  LOS_TaskDelay(100);
  HAL_GPIO_WritePin(MCU_LED0_GPIO_Port, MCU_LED0_Pin, GPIO_PIN_SET); // on
  
  LOS_TaskDelay(100);
  HAL_GPIO_WritePin(MCU_LED0_GPIO_Port, MCU_LED0_Pin, GPIO_PIN_RESET); // off
}

void LAN8720_RESET(void)
{
//    HAL_GPIO_WritePin(ETH_PHYAD0_GPIO_Port, ETH_PHYAD0_Pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(ETH_RESET_GPIO_Port, ETH_RESET_Pin, GPIO_PIN_RESET);
    HAL_Delay(55);
    HAL_GPIO_WritePin(ETH_RESET_GPIO_Port, ETH_RESET_Pin, GPIO_PIN_SET);
    HAL_Delay(55);
}

void test_mem_ccm(void)
{
  uint8_t c_per = 0; // 内存用量百分比
  c_per = my_mem_perused_CCM(); // 内存使用率
  uint8_t* puc_buf = mymalloc_CCM(0x4000); // 先申请16KB用一下
  c_per = my_mem_perused_CCM(); // 内存使用率
  if (NULL != puc_buf)
  {
    strcpy((char*)puc_buf, "hello memory operation");
    if (('h' == puc_buf[0]) && ('\0' == puc_buf[strlen((char*)puc_buf)]))
    {
      // memory operation is ok
      puc_buf[0] = puc_buf[0];
    }
    
    myfree_CCM(puc_buf);
  }
}

void test_mem_in(void)
{
  uint8_t c_per = 0; // 内存用量百分比
  c_per = my_mem_perused_IN(); // 内存使用率
  uint8_t* puc_buf = mymalloc_IN(0x4000); // 先申请16KB用一下
  c_per = my_mem_perused_IN(); // 内存使用率
  if (NULL != puc_buf)
  {
    strcpy((char*)puc_buf, "hello memory operation");
    if (('h' == puc_buf[0]) && ('\0' == puc_buf[strlen((char*)puc_buf)]))
    {
      // memory operation is ok
      puc_buf[0] = puc_buf[0];
    }
    
    myfree_IN(puc_buf);
  }
}

void test_mem_ex1(void)
{
  uint8_t c_per = 0; // 内存用量百分比
  c_per = my_mem_perused_EX1(); // 内存使用率
  uint8_t* puc_buf = mymalloc_EX1(0x4000); // 先申请16KB用一下
  c_per = my_mem_perused_EX1(); // 内存使用率
  if (NULL != puc_buf)
  {
    strcpy((char*)puc_buf, "hello memory operation");
    if (('h' == puc_buf[0]) && ('\0' == puc_buf[strlen((char*)puc_buf)]))
    {
      // memory operation is ok
      puc_buf[0] = puc_buf[0];
    }
    
    myfree_EX1(puc_buf);
  }
}

void test_mem_ex2(void)
{
  uint8_t c_per = 0; // 内存用量百分比
  c_per = my_mem_perused_EX2(); // 内存使用率
  uint8_t* puc_buf = mymalloc_EX2(0x4000); // 先申请16KB用一下
  c_per = my_mem_perused_EX2(); // 内存使用率
  if (NULL != puc_buf)
  {
    strcpy((char*)puc_buf, "hello memory operation");
    if (('h' == puc_buf[0]) && ('\0' == puc_buf[strlen((char*)puc_buf)]))
    {
      // memory operation is ok
      puc_buf[0] = puc_buf[0];
    }
    
    myfree_EX2(puc_buf);
  }
}
  
static void TaskTotal(void)
{
  /* 任务都是一个无限循环,不能返回 */
  
  LOS_TaskDelay(1000);
  
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  LAN8720_RESET();
  
  MX_SDIO_SD_Init();
  MX_SPI2_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  MX_USART6_UART_Init();
  MX_FSMC_Init();
  
  // 在FSMC初始化后,开始内存的初始化
  my_mem_init_CCM();
  my_mem_init_IN();
  my_mem_init_EX1();
  my_mem_init_EX2();
  
  MX_LWIP_Init();

  /* Initialize interrupts */
  MX_NVIC_Init();
  
  // test memory
  test_mem_ccm();
  test_mem_in();
  test_mem_ex1();
  test_mem_ex2();
  
  while(1)
  {
    MX_LWIP_Process();
      
    // led_app_running();
    // test_out1234(); // ok
    // test_out5678();
    
    // test_input1to16(); // ok
    
    // LED2_TOGGLE;
    // printf("任务1运行中,每1000ms打印一次信息\r\n");
    // LOS_TaskDelay(1000);		
  }
}

UINT32 Test1_Task_Handle = 0;

// 创建总任务
static UINT32 Creat_TaskTotal()
{
  //定义一个创建任务的返回类型,初始化为创建成功的返回值
  UINT32 uwRet = LOS_OK;			
  
  //定义一个用于创建任务的参数结构体
  TSK_INIT_PARAM_S task_init_param;	
  
  task_init_param.usTaskPrio = 3;	/* 任务优先级,数值越小,优先级越高 */
  task_init_param.pcName = "TaskTotal";/* 任务名 */
  task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskTotal;/* 任务函数入口 */
  task_init_param.uwStackSize = 1024;		/* 堆栈大小 */
  
  uwRet = LOS_TaskCreate(&Test1_Task_Handle, &task_init_param);/* 创建任务 */
  return uwRet;
}

static UINT32 AppTaskCreate(void)
{
  /* 定义一个返回类型变量,初始化为LOS_OK */
  UINT32 uwRet = LOS_OK;
  
  uwRet = Creat_TaskTotal();
  if (uwRet != LOS_OK)
  {
    // printf("Test1_Task任务创建失败!失败代码0x%X\n",uwRet);
    return uwRet;
  }
  return LOS_OK;
}

void HAL_Delay(uint32_t Delay)
{
  LOS_TaskDelay(Delay);
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  UINT32 uwRet = 0;
  /* USER CODE END 1 */

  /* 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 */
  
  // 因为网卡初始化代码中用到了 HAL_Delay, 即使换成LOS_TaskDelay(), 也要先执行LOS_KernelInit()
  uwRet = LOS_KernelInit();
  if (uwRet != LOS_OK)
  {
    return LOS_NOK;
  }

  LOS_Inspect_Entry(); // lite-os自带的检查任务
  
  /* USER CODE END SysInit */


  /* USER CODE BEGIN 2 */
  
  // 创建所有任务
  uwRet = AppTaskCreate();
  if (uwRet != LOS_OK)
  {
    // printf("AppTaskCreate创建任务失败!失败代码0x%X\n",uwRet);
    return LOS_NOK;
  }
  
  
  LOS_Start();
  /* 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};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** 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 = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enables the Clock Security System
  */
  HAL_RCC_EnableCSS();
}

/**
  * @brief NVIC Configuration.
  * @retval None
  */
static void MX_NVIC_Init(void)
{
  /* RCC_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(RCC_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(RCC_IRQn);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @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 */
  
  line = line;
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-06 11:19:00  更:2021-09-06 11:19:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:29:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码