AIR32F103CBT6 和 AIR32F103CCT6 分別帶 32K Byte和 64K Byte 記憶體. 對於48pin封裝的 AIR32F103, 32K和64K的記憶體已經是市面上M3晶元中相當不錯的容量, 至於64pin封裝的AIR32F103RPT6, 96K的記憶體只在市場上的高端型號... ...
目錄
- 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: %d\r\n", 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