目录

AIR32F103CBT6和CCT6的隐藏内存空间

TYPE AIR32F103CBT6 AIR32F103CCT6 AIR32F103RPT6
Flash 128K 256K 256K
RAM 32K 64K 96K
Pack lqfp48 lqfp48 lqfp64

根据数据手册, AIR32F103CBT6 和 AIR32F103CCT6 分别带 32K Byte和 64K Byte 内存. 对于48pin封装的 AIR32F103, 32K和64K的内存已经是市面上M3芯片中相当不错的容量, 至于64pin封装的AIR32F103RPT6, 96K的内存只在市场上的高端型号中出现, 例如雅特力的AT32F403A系列.

但是实际上这两个型号和 AIR32F103RPT6 一样, 内存空间为96K.

这个隐藏的内存空间, 是 Hedley Rainnie 在观察切换216MHz的过程中发现的. 这个容量也得到了合宙技术的确认.

具体的记录可以查看 http://www.hrrzi.com/2022/12/the-air32f103.html. 在切换216MHz的过程中, 在将RCC->RCC_SYSCFG_CONFIG置零之前, 可以通过SYSCFG->SYSCFG_RSVD0[5]这个寄存器设置内存空间的结束地址. 将这个地址设为 0x20018000 后, 在代码中就可以使用 96K Byte 的内存容量.

启用隐藏内存的流程

查看代码 https://gitee.com/openLuat/luatos-soc-air32f103/blob/master/Libraries/AIR32F10xLib/src/air32f10x_rcc_ex.c

切换216MHz的代码

  1. #define SysFreq_Set (*((void (*)(uint32_t, FlashClkDiv , uint8_t, uint8_t))(*(uint32_t *)0x1FFFD00C)))
  2. uint32_t AIR_RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul, FlashClkDiv Latency)
  3. {
  4. volatile uint32_t sramsize = 0;
  5. assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource));
  6. assert_param(IS_RCC_PLL_MUL(RCC_PLLMul));
  7. *(volatile uint32_t *)(0x400210F0) = BIT(0);//开启sys_cfg门控
  8. *(volatile uint32_t *)(0x40016C00) = 0xa7d93a86;//解一、二、三级锁
  9. *(volatile uint32_t *)(0x40016C00) = 0xab12dfcd;
  10. *(volatile uint32_t *)(0x40016C00) = 0xcded3526;
  11. // 这一步记录了RAM大小
  12. sramsize = *(volatile uint32_t *)(0x40016C18);
  13. *(volatile uint32_t *)(0x40016C18) = 0x200183FF;//配置sram大小, 将BOOT使用对sram打开
  14. *(volatile uint32_t *)(0x4002228C) = 0xa5a5a5a5;//QSPI解锁
  15. SysFreq_Set(RCC_PLLMul,Latency ,0,1);
  16. RCC->CFGR = (RCC->CFGR & ~0x00030000) | RCC_PLLSource;
  17. // 在这一步, 将之前的RAM大小再设置回去, 如果把这个sramsize直接改为 0x20018000, 就使得整个96K都可用了
  18. *(volatile uint32_t *)(0x40016C18) = sramsize;
  19. *(volatile uint32_t *)(0x400210F0) = 0;//开启sys_cfg门控
  20. *(volatile uint32_t *)(0x40016C00) = ~0xa7d93a86;//加一、二、三级锁
  21. *(volatile uint32_t *)(0x40016C00) = ~0xab12dfcd;
  22. *(volatile uint32_t *)(0x40016C00) = ~0xcded3526;
  23. *(volatile uint32_t *)(0x4002228C) = ~0xa5a5a5a5;//QSPI解锁
  24. return 1;
  25. }

上面的代码用地址表示比较难阅读, 能换成寄存器表达的都换成寄存器表达后, 看起来会简单些

  1. uint32_t AIR_RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul, FlashClkDiv Latency)
  2. {
  3. assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource));
  4. assert_param(IS_RCC_PLL_MUL(RCC_PLLMul));
  5. RCC->RCC_SYSCFG_CONFIG = 1; // Unlock sys_cfg gate control
  6. SYSCFG->SYSCFG_LOCK = 0xa7d93a86; // Unlock from level 1 to 3
  7. SYSCFG->SYSCFG_LOCK = 0xab12dfcd;
  8. SYSCFG->SYSCFG_LOCK = 0xcded3526;
  9. SYSCFG->SYSCFG_RSVD0[5] = 0x200183FF; // Set sram size, enable BOOT for sram
  10. *(__IO uint32_t *)(FLASH_R_BASE + 0x28C) = 0xa5a5a5a5; // Unlock QSPI
  11. AIR_SysFreq_Set(RCC_PLLMul, Latency, 0, 1);
  12. RCC->CFGR = (RCC->CFGR & ~0x00030000) | RCC_PLLSource;
  13. // Restore previous config
  14. SYSCFG->SYSCFG_RSVD0[5] = 0x20018000;
  15. RCC->RCC_SYSCFG_CONFIG = 0; // Lock sys_cfg gate control
  16. SYSCFG->SYSCFG_LOCK = ~0xa7d93a86; // Lock from level 1 to 3
  17. SYSCFG->SYSCFG_LOCK = ~0xab12dfcd;
  18. SYSCFG->SYSCFG_LOCK = ~0xcded3526;
  19. *(__IO uint32_t *)(FLASH_R_BASE + 0x28C) = ~0xa5a5a5a5;// Lock QSPI
  20. return 1;
  21. }

测试 96K 内存的例子

测试96K内存的源代码

DMA_TC_Interrupt_96k_Malloc 和 DMA_TC_Interrupt_96k_Static 这两个示例分别演示动态和静态使用超过64K内存的情况. 在运行这两个例子前, 需要对项目代码做一些调整

1. 编辑 Libraries/LDScripts/air32f103cbt6.ld 或 air32f103cct6

修改 RAM LENGTH 为 96K

  1. MEMORY
  2. {
  3. FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
  4. RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K <---- 修改这个值为 96K
  5. MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
  6. }

2. 编辑 Libraries/AIR32F10xLib/src/system_air32f10x.c

确认启用了 SYSCLK_FREQ_216MHz 这个宏配置

  1. //#define SYSCLK_FREQ_HSE HSE_VALUE
  2. //#define SYSCLK_FREQ_24MHz 24000000
  3. //#define SYSCLK_FREQ_36MHz 36000000
  4. //#define SYSCLK_FREQ_48MHz 48000000
  5. //#define SYSCLK_FREQ_56MHz 56000000
  6. //#define SYSCLK_FREQ_72MHz 72000000
  7. #define SYSCLK_FREQ_216MHz 216000000 <---- 启用这个配置

3. 动态和静态申请

47000 个 uint16_t, 对应了 47K * 2 = 94K 内存

动态申请

  1. #define BUFF_SIZE 47000
  2. uint16_t *dma_buf;
  3. ...
  4. dma_buf = (uint16_t *)malloc(BUFF_SIZE * sizeof(uint16_t));
  5. printf("Malloc size: %d\r\n", BUFF_SIZE * sizeof(uint16_t));

静态申请

  1. #define BUFF_SIZE 47000
  2. uint16_t dma_buf[BUFF_SIZE];

需要确保在未完成内存容量设置前, 不要使用 dma_buf

最后

据说除了额外的RAM, 还有额外的FLASH, 但是我没试成功, 在写入flash后校验不通过, 也可能我使用的姿势不对.

原先AIR32F103CBT6只有32K内存, 不能跑Helix MP3解码, 现在的96K内存足够跑两个, LOL

AIR32F103(七) AIR32F103CBT6/CCT6启用96K内存的更多相关文章

  1. 如何启用“锁定内存页”选项 (Windows)

    默认情况下,禁用 Windows 策略"锁定内存页"选项.必须启用此权限才能配置地址窗口化扩展插件 (AWE).此策略将确定哪些帐户可以使用进程将数据保留在物理内存中,从而阻止系统 ...

  2. InnoDB启用大内存页

    在 Linux 操作系统上运行内存需求量较大的应用程序时,由于其采用的默认页面大小为 4KB,因而将会产生较多 TLB Miss 和缺页中断,从而大大影响应用程序的性能.当操作系统以 2MB 甚至更大 ...

  3. 七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 4.@property参数 5.@class和循环retain的使用 6.NSString的内存管理

    1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程 ...

  4. JVM 专题十二:运行时数据区(七)对象的实例化内存布局与访问定位

    1. 对象的实例化 1.1 创建对象的方式 new 最常见的方式 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 Class的newInstance() ...

  5. linux内存基础知识和相关调优方案

    内存是计算机中重要的部件之中的一个.它是与CPU进行沟通的桥梁. 计算机中全部程序的执行都是在内存中进行的.因此内存的性能对计算机的影响很大.内存作用是用于临时存放CPU中的运算数据,以及与硬盘等外部 ...

  6. xcode 手动管理内存 的相关知识点总结

    一.XCode4.2以后支持自动释放内存ARC xcode自4.2以后就支持自动释放内存了,但有时我们还是想手动管理内存,这如何处理呢. 很简单,想要取消自动释放,只要在  Build Setting ...

  7. python统计某一个进程名所占用的内存

    设计思路: 通过python,执行cmd中tasklist命令,获取要统计的进程的相关信息:通过正则表达式,查找出进程名称.进程pid.内存使用,然后打印出来. 作为pythoner,有时候需要统计p ...

  8. Memcache 内存分配策略和性能(使用)状态检查

    前言: 一直在使用Memcache,但是对其内部的问题,如它内存是怎么样被使用的,使用一段时间后想看看一些状态怎么样?一直都不清楚,查了又忘记,现在整理出该篇文章,方便自己查阅.本文不涉及安装.操作. ...

  9. iOS-OC内存管理

    目标 1.[理解]内存管理 2.[掌握]第一个MRC程序 3.[掌握]内存管理的原则 4.[理解]野指针与僵尸对象 5.[理解]单个对象的内存管理 6.[理解]多个对象的内存管理 7.[掌握]set方 ...

  10. C++内存分析

    在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 栈:就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区.里面的变量通常是局部变量.函数参数 ...

随机推荐

  1. 第一个java程序进行总结

    1.java程序编写-编译-运行的过程 编写:我们将编写的java代码保存在以".java"结尾的源文件中 编译:使用javac.exe命令编译我们的java源文件.格式:java ...

  2. 2.MongoDB系列之创建更新删除文档

    1. 插入文档 // 单条插入 db.getCollection('blog').insertOne({'type': 'mongodb'}) // 批量 插入 db.getCollection('b ...

  3. springboot项目中使用shiro实现用户登录以及权限的验证

    欢迎大家加入我的社区:http://t.csdn.cn/Q52km 社区中不定时发红包 更加高级的验证用户权限:用户表.角色表.权限表.多表联合:https://blog.csdn.net/weixi ...

  4. 动词时态=>2.动作的时间状态结合

    动作和时间结合 现在的四种时态 现在进行时态 对于 现在这个时间点,这个 动作 还在进行当中 例如:我现在正在喝水 现在完成时态 对于 现在这个时间点,这个 动作 已然完成 例子:我现在已经喝完了水 ...

  5. Adobe Acrobat Pro 2021 for mac安装教程,完美使用!!!

    adobe acrobat是最优秀的PDF编辑软件,有了它用户可以随时随地的进行签署.支持创建PDF.编辑PDF.导出PDF.合并文件等各种管理PDF文件的实用的功能,非常好用,可以说是PDF转换的必 ...

  6. Linux下MMDetection环境配置

    1. 准备工作 Linux发行版. Pop!_OS 22.04 LTS (NVIDIA) (Ubuntu衍生) 对Linux进行配置,更改国内镜像源. 安装conda环境. 官网下载安装脚本(bash ...

  7. CSS动画-transition/animation

    HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...

  8. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(33)-Fiddler如何抓取WebSocket数据包

    1.简介 本来打算再写一篇这个系列的文章也要和小伙伴或者童鞋们说再见了,可是有人留言问WebSocket包和小程序的包不会抓,那就关于这两个知识点宏哥就再水两篇文章. 2.什么是Socket? 在计算 ...

  9. 【JAVA】详解在JAVA中int与Integer的区别以及背后的原因。

    区别 首先我们要明确,这两点之间有什么区别? 主要有以下几点: 数据类型不同:int是基础数据类型,而 Integer是包装数据类型: 默认值不同:int的默认值是 0,而 Integer的默认值是 ...

  10. 嵌入式-C语言基础:结构体

    数组只能存放一种类型的数据,而结构体内可以存放不同类型的数据. #include<stdio.h> #include <string.h> struct Student { c ...