一、開發環境
開發板:野火stm32f407
系統:rt-thread V4.1.1
二、鏈接腳本配置
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x00100000 { ; load region size_regionER_IROM1 0x08000000 0x00100000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO)}RW_IRAM1 0x20000000 0x00020000 { ; RW data.ANY (+RW +ZI)}RW_IRAM2 0x10000000 0x00010000 { ; RW data*(.CCM_RAM)}
}
具體配置可參考文章鏈接
https://mp.weixin.qq.com/s/s_CHsM7ykF6-n2dVwfaGUQ
三、測試代碼
使用單片機的CCNM內存創建變量和線程,打印變量和線程的地址信息,使用指令查看主RAM的信息。直接貼測試代碼,如下:
/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2018-11-06 SummerGift first version* 2018-11-19 flybreak add stm32f407-atk-explorer bsp*/#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>/* defined the LED0 pin: PF7 */
#define LED0_PIN GET_PIN(F, 7)/* 定義在CCM RAM里面的變量 */
//__attribute__((section (".CCM_RAM"))) uint32_t BufInfo[10];
//__attribute__((section (".CCM_RAM"))) uint16_t Count=5;//可以定義初值uint32_t BufInfo[10] __attribute__((section (".CCM_RAM")));uint16_t Count __attribute__((section (".CCM_RAM"))) =5;//可以這樣定義初值uint16_t CNT __attribute__((section(".CCM_RAM"), used));//使用 __attribute__((used)) 確保變量不被優化掉
__attribute__((section (".CCM_RAM"),used)) uint16_t NUM=5;//使用 __attribute__((used)) 確保變量不被優化掉/* 定義在CCM RAM里面的線程 */
#if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 1))rt_align(RT_ALIGN_SIZE)
#elseALIGN(RT_ALIGN_SIZE)
#endif
//__attribute__((section (".CCM_RAM"))) static char thread1_stack[1024*60];
//__attribute__((section (".CCM_RAM"))) static struct rt_thread thread1;static char thread1_stack[1024*2] __attribute__((section (".CCM_RAM")));static struct rt_thread thread1 __attribute__((section (".CCM_RAM")));#if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 1))rt_align(RT_ALIGN_SIZE)
#elseALIGN(RT_ALIGN_SIZE)
#endifstatic char thread2_stack[1024*2] __attribute__((section (".CCM_RAM")));static struct rt_thread thread2 __attribute__((section (".CCM_RAM")));/* 定義在CCM RAM里面的信號量 */
__attribute__((section (".CCM_RAM"))) static struct rt_semaphore test_sem;/* 線程 1 入口 */
static void thread1_entry(void *param)
{rt_uint32_t count = 0;rt_kprintf("count_addr= %x\r\n",&count);rt_uint32_t buf[10];for(int i=0;i<10;i++){rt_kprintf("buf[%d]_addr= %x\r\n",i,&buf[i]);}/* 線程 1 擁有較高的優先級,以搶占線程 1 而獲得執行 */static rt_err_t result;for (;;){/* 永久方式等待信號量,獲取到信號量,則執行 number 自加的操作 */result = rt_sem_take(&test_sem, RT_WAITING_FOREVER);if ( result == RT_EOK){/* 線程 1 打印計數值 */rt_kprintf("thread1 count: %d\n", count++);}else{rt_kprintf("thread 1 result is %d\n", result);}}/* 線程 1 運行結束后也將自動被系統脫離 */}/* 線程 2 入口 */
static void thread2_entry(void *param)
{rt_uint32_t count = 0;rt_kprintf("count_addr2= %x\r\n",&count);rt_uint32_t buf[10];for(int i=0;i<10;i++){rt_kprintf("buf[%d]_addr2= %x\r\n",i,&buf[i]);}for (;;){/* 線程 1 打印計數值 */rt_kprintf(" release test_sem.\n");rt_sem_release(&test_sem);rt_thread_mdelay(10000);}/* 線程 1 運行結束后也將自動被系統脫離 */}int main(void)
{/* set LED0 pin mode to output */rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);Count++;for(int i=0;i<10;i++){rt_kprintf("BufInfo[%d]_addr= %x\r\n",i,&BufInfo[i]);}BufInfo[0] = Count;rt_kprintf("CCMBuf1_addr= %x, BufInfo[0] = %d\r\n",BufInfo,BufInfo[0]);rt_kprintf("CCMCount_addr= %x, Count = %d\r\n",&Count,Count); rt_kprintf("CNT= %x, CNT = %d\r\n",&CNT,CNT); rt_kprintf("NUM= %x, NUM = %d\r\n",&NUM,NUM); rt_thread_mdelay(5000); rt_kprintf("intput free\r\n"); rt_thread_mdelay(10000);rt_sem_init(&test_sem, "testSem", 0, RT_IPC_FLAG_PRIO);rt_kprintf("test_sem_addr= %x\r\n",&test_sem); rt_thread_mdelay(10000);/* 初始化線程 1,名稱是 thread1,入口是 thread1_entry */rt_thread_init(&thread1,"thread1",thread1_entry,RT_NULL,&thread1_stack[0],sizeof(thread1_stack),25, 5);rt_thread_startup(&thread1);rt_kprintf("thread1_addr= %x\r\n",&thread1); rt_kprintf("thread1_stack_addr= %x\r\n",thread1_stack); rt_thread_mdelay(10000);/* 初始化線程 2,名稱是 thread2,入口是 thread2_entry */rt_thread_init(&thread2,"thread2",thread2_entry,RT_NULL,&thread2_stack[0],sizeof(thread2_stack),25, 5);rt_thread_startup(&thread2);rt_kprintf("thread2_addr= %x\r\n",&thread2); rt_kprintf("thread2_stack_addr= %x\r\n",thread2_stack); rt_thread_mdelay(10000); rt_kprintf("intput free\r\n"); rt_thread_mdelay(10000);while (1){rt_pin_write(LED0_PIN, PIN_HIGH);rt_thread_mdelay(500);rt_pin_write(LED0_PIN, PIN_LOW);rt_thread_mdelay(500);}
}
測試結果:
打印變量的信息
打印線程的信息