AIR32F103(七) AIR32F103CBT6/CCT6啟用96K記憶體

2022-12-26 06:01:07

目錄

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的程式碼

#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記憶體的原始碼

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