目录
- AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告
- AIR32F103(二) Linux环境和LibOpenCM3项目模板
- AIR32F103(三) Linux环境基于标准外设库的项目模板
- AIR32F103(四) 27倍频216MHz,CoreMark跑分测试
- AIR32F103(五) FreeRTOSv202112核心库的集成和示例代码
- AIR32F103(六) ADC,I2S,DMA和ADPCM实现的录音播放功能
- AIR32F103(七) AIR32F103CBT6/CCT6启用96K内存
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 的内存容量.
启用隐藏内存的流程
切换216MHz的代码
#define SysFreq_Set (*((void (*)(uint32_t, FlashClkDiv , uint8_t, uint8_t))(*(uint32_t *)0x1FFFD00C))) uint32_t AIR_RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul, FlashClkDiv Latency) { volatile uint32_t sramsize = 0; assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource)); assert_param(IS_RCC_PLL_MUL(RCC_PLLMul)); *(volatile uint32_t *)(0x400210F0) = BIT(0);//开启sys_cfg门控 *(volatile uint32_t *)(0x40016C00) = 0xa7d93a86;//解一、二、三级锁 *(volatile uint32_t *)(0x40016C00) = 0xab12dfcd; *(volatile uint32_t *)(0x40016C00) = 0xcded3526; // 这一步记录了RAM大小 sramsize = *(volatile uint32_t *)(0x40016C18); *(volatile uint32_t *)(0x40016C18) = 0x200183FF;//配置sram大小, 将BOOT使用对sram打开 *(volatile uint32_t *)(0x4002228C) = 0xa5a5a5a5;//QSPI解锁 SysFreq_Set(RCC_PLLMul,Latency ,0,1); RCC->CFGR = (RCC->CFGR & ~0x00030000) | RCC_PLLSource; // 在这一步, 将之前的RAM大小再设置回去, 如果把这个sramsize直接改为 0x20018000, 就使得整个96K都可用了 *(volatile uint32_t *)(0x40016C18) = sramsize; *(volatile uint32_t *)(0x400210F0) = 0;//开启sys_cfg门控 *(volatile uint32_t *)(0x40016C00) = ~0xa7d93a86;//加一、二、三级锁 *(volatile uint32_t *)(0x40016C00) = ~0xab12dfcd; *(volatile uint32_t *)(0x40016C00) = ~0xcded3526; *(volatile uint32_t *)(0x4002228C) = ~0xa5a5a5a5;//QSPI解锁 return 1; }
上面的代码用地址表示比较难阅读, 能换成寄存器表达的都换成寄存器表达后, 看起来会简单些
uint32_t AIR_RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul, FlashClkDiv Latency) { assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource)); assert_param(IS_RCC_PLL_MUL(RCC_PLLMul)); RCC->RCC_SYSCFG_CONFIG = 1; // Unlock sys_cfg gate control SYSCFG->SYSCFG_LOCK = 0xa7d93a86; // Unlock from level 1 to 3 SYSCFG->SYSCFG_LOCK = 0xab12dfcd; SYSCFG->SYSCFG_LOCK = 0xcded3526; SYSCFG->SYSCFG_RSVD0[5] = 0x200183FF; // Set sram size, enable BOOT for sram *(__IO uint32_t *)(FLASH_R_BASE + 0x28C) = 0xa5a5a5a5; // Unlock QSPI AIR_SysFreq_Set(RCC_PLLMul, Latency, 0, 1); RCC->CFGR = (RCC->CFGR & ~0x00030000) | RCC_PLLSource; // Restore previous config SYSCFG->SYSCFG_RSVD0[5] = 0x20018000; RCC->RCC_SYSCFG_CONFIG = 0; // Lock sys_cfg gate control SYSCFG->SYSCFG_LOCK = ~0xa7d93a86; // Lock from level 1 to 3 SYSCFG->SYSCFG_LOCK = ~0xab12dfcd; SYSCFG->SYSCFG_LOCK = ~0xcded3526; *(__IO uint32_t *)(FLASH_R_BASE + 0x28C) = ~0xa5a5a5a5;// Lock QSPI return 1; }
测试 96K 内存的例子
测试96K内存的源代码
- GitHub https://github.com/IOsetting/air32f103-template/tree/master/Examples/NonFreeRTOS/DMA
- Gitee https://gitee.com/iosetting/air32f103-template/tree/master/Examples/NonFreeRTOS/DMA
DMA_TC_Interrupt_96k_Malloc 和 DMA_TC_Interrupt_96k_Static 这两个示例分别演示动态和静态使用超过64K内存的情况. 在运行这两个例子前, 需要对项目代码做一些调整
1. 编辑 Libraries/LDScripts/air32f103cbt6.ld 或 air32f103cct6
修改 RAM LENGTH 为 96K
MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K <---- 修改这个值为 96K MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K }
2. 编辑 Libraries/AIR32F10xLib/src/system_air32f10x.c
确认启用了 SYSCLK_FREQ_216MHz 这个宏配置
//#define SYSCLK_FREQ_HSE HSE_VALUE //#define SYSCLK_FREQ_24MHz 24000000 //#define SYSCLK_FREQ_36MHz 36000000 //#define SYSCLK_FREQ_48MHz 48000000 //#define SYSCLK_FREQ_56MHz 56000000 //#define SYSCLK_FREQ_72MHz 72000000 #define SYSCLK_FREQ_216MHz 216000000 <---- 启用这个配置
3. 动态和静态申请
47000 个 uint16_t, 对应了 47K * 2 = 94K 内存
动态申请
#define BUFF_SIZE 47000 uint16_t *dma_buf; ... dma_buf = (uint16_t *)malloc(BUFF_SIZE * sizeof(uint16_t)); printf("Malloc size: %drn", BUFF_SIZE * sizeof(uint16_t));
静态申请
#define BUFF_SIZE 47000 uint16_t dma_buf[BUFF_SIZE];
需要确保在未完成内存容量设置前, 不要使用 dma_buf
最后
据说除了额外的RAM, 还有额外的FLASH, 但是我没试成功, 在写入flash后校验不通过, 也可能我使用的姿势不对.
原先AIR32F103CBT6只有32K内存, 不能跑Helix MP3解码, 现在的96K内存足够跑两个, LOL