日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql 移植ucos_基于STM32F767的UCOSIII移植学习

發(fā)布時間:2024/7/19 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 移植ucos_基于STM32F767的UCOSIII移植学习 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

(一)移植前的準備

1.HAL庫基本工程模板

新建一個工程模塊,其中包含LED驅動和串口驅動程序即可,用于驗證UCOS-III系統(tǒng)能夠正常工作。

2.UCOS-III源碼準備

去Micrium官網下載最新的UCOSIII源碼,下載地址:Micrium官網下載地址,沒有注冊過的用戶需要注冊一下,我自己注冊的過程都是淚。由于我選擇的是正點原子F7的開發(fā)板,所以在官網上選擇合適源碼時就選擇F7的。具體版本選擇下圖中19年2月6號的版本:

下載完成之后發(fā)現(xiàn),發(fā)現(xiàn)源碼文件夾中東西很多大部分都是和網絡移植相關的,目前我們只移植最新版本的UCOSIII,所以這些文件夾都不需要去看。進入源碼目錄下的uCOS-III文件夾,發(fā)現(xiàn)里面只有針對IAR的編譯器的文件,難道MDK就涼涼了嗎?凡是先不要慌,雖然編譯器不同,但是實現(xiàn)的功能就是相同的,并不會影響到移植后操作系統(tǒng)的運行。

UCOSIII的移植

(一)源碼文件的摘選

1.在準備好的工程文件夾下新建一個UCOS-III目錄,用于存放和UCOSIII相關的所有代碼。在UCOS-III目錄下新建如下目錄,用于UCOS源碼的分類。

(1)將源碼目錄Micrium_STM32F746G-DISCO_Crypto\Micrium\Software\uC-CPU下的文件全部拷貝到我們創(chuàng)建的uC-CPU目錄下,為了減少文件夾的個數,我把ARM-Cortex-M\ARMv7-M目錄下和ARM-Cortex-M\ARMv7-M\ARM目錄下的文件都移到了自己創(chuàng)建的uC-CPU目錄下了。這里我要說明下一下IAR和ARM目錄下的文件,除了匯編文件有些不同以外,頭文件內容都是相同的,這邊選擇ARM目錄下的匯編文件還是IAR目錄下的匯編文件都行,因為我們都是要修改成MDK支持的形式的。

(2)將源碼目錄Micrium_STM32F746G-DISCO_Crypto\Micrium\Software\uC-LIB文件夾下的文件全部拷貝到自己創(chuàng)建的uC-LIB目錄下,這邊我直接把Micrium\Software\uC-LIB\Ports\ARM-Cortex-M4\RealView目錄下的文件和其他文件放在了一個文件夾下,具體如下圖所示:

由于我們使用的是MDK編譯,所以這邊選擇的是RealView目錄下的匯編文件,具體什么原因的話,網上有很多解釋,我就不復制他們的解釋了。

(3)將Micrium_STM32F746G-DISCO_Crypto\Micrium\Software\uCOS-III目錄下的文件全部拷貝到自己創(chuàng)建uCOS-III目錄下。點開Ports的目錄,發(fā)現(xiàn)最后只有一個IAR文件下,這邊我們先不用關注,只需將文件都拷貝過來,具體內容如下圖所示:

(4)將源碼例程目錄Micrium_STM32F746G-DISCO_Crypto\ST\STM32F746G_Disco\Crypto下的部分文件和OS3下的部分文件拷貝到自己創(chuàng)建的UCOS-CONFIG文件夾下。具體文件如下圖所示:

在源碼例程文件中,發(fā)現(xiàn)很多都是網絡相關的移植代碼,所以沒有拷貝過來。但是有一個clk_cfg.h很明顯不是和網絡相關的,為什么不移植過來呢?從名字上看就是和時鐘相關的,難道說不需要時鐘配置嗎?時鐘當然是需要配置的,但是裸機工程中時鐘已經配置OK了,這邊和時鐘相關的文件也就不需要了,后面操作系統(tǒng)的時鐘需要自己通過HAL庫配置,這邊就不詳細說明了。

(5)將Micrium_STM32F746G-DISCO_Crypto\ST\BSP\STM32F746G_Disco目錄下的bsp_cpu.c文件拷貝到自己創(chuàng)建的UCOS-BSP目錄下,并且新建一個bsp_cpu.h頭文件(用于包含操作系統(tǒng)的頭文件)。其他文件都不需要拷貝,大多是和芯片外設相關的初始化。

(二)文件添加

(1)打開MDK工程,將拷貝的文件添加至工程當中,具體內容如下圖所示:

以及頭文件路徑添加,如下圖所示:

上述文件都添加完成之后,點擊編譯,提示下圖錯誤:

出現(xiàn)unknown opcode什么的錯誤,而且出現(xiàn)在os_cpu_a.asm文件中,那就打開這個匯編文件看一下,是什么問題,發(fā)現(xiàn)PUBLIC關鍵字都沒有標藍,那肯定是由于這個關鍵字不是MDK的關鍵字,所以講PUBLIC修改為MDK所用的關鍵字EXPORT,具體EXPORT這個關鍵字怎么來的,我是查看了其他版本的UCOS在STM32的移植,看到用的是這個關鍵字,就直接抄過來了。還有錯誤與FPU相關,如下圖所示:

#ifdef __ARMVFP__

EXPORT OS_CPU_FP_Reg_Push

EXPORT OS_CPU_FP_Reg_Pop

#endif

查看了正點原子的移植手冊,發(fā)現(xiàn)上面說到

Cortex-M7內核中有個Lazy Stacking的功能,如果使用FPU功能的話就需要關閉這個功能,需要修改startup_stm32f767xx.s匯編文件,在里面關閉這個功能。

具體代碼如下所示:

IF {FPU} != "SoftVFP"

; Enable Floating Point Support at reset for FPU

LDR.W R0, =0xE000ED88 ; Load address of CPACR register

LDR R1, [R0] ; Read value at CPACR

ORR R1, R1, #(0xF <<20) ; Set bits 20-23 to enable CP10 and CP11 coprocessors

; Write back the modified CPACR value

STR R1, [R0] ; Wait for store to complete

DSB

; Disable automatic FP register content

; Disable lazy context switch

LDR.W R0, =0xE000EF34 ; Load address to FPCCR register

LDR R1, [R0]

AND R1, R1, #(0x3FFFFFFF) ; Clear the LSPEN and ASPEN bits

STR R1, [R0]

ISB ; Reset pipeline now the FPU is enabled

ENDIF

在startup_stm32f767xx.s中就如下圖所示:

修改完這些,接下去就解決… error: A1163E: Unknown opcode ARMVFP , expecting opcode or Macro 這個錯誤。將原先的判斷語句修改為如下語句:

IF {FPU} != "SoftVFP"

EXPORT OS_CPU_FP_Reg_Push

EXPORT OS_CPU_FP_Reg_Pop

ENDIF

IF {FPU} != "SoftVFP"

OS_CPU_FP_Reg_Push

MRS R1, PSP ; PSP is process stack pointer

CBZ R1, OS_CPU_FP_nosave ; Skip FP register save the first time

VSTMDB R0!, {S16-S31}

LDR R1, =OSTCBCurPtr

LDR R2, [R1]

STR R0, [R2]

OS_CPU_FP_nosave

BX LR

ENDIF

IF {FPU} != "SoftVFP"

OS_CPU_FP_Reg_Pop

VLDMIA R0!, {S16-S31}

LDR R1, =OSTCBHighRdyPtr

LDR R2, [R1]

STR R0, [R2]

BX LR

ENDIF

修改完成之后,再次編譯,依舊存在 error: A1163E: Unknown opcode RSEG , expecting opcode or Macro 的錯誤,這主要是由于編譯器關鍵字的問題,所以這里直接借鑒其他其他版本在MDK上的移植。具體修改代碼如下:

PRESERVE8

THUMB

AREA CODE, CODE, READONLY

再次編譯,發(fā)現(xiàn)這個匯編文件中還有一個警告: warning: A1581W: Added 2 bytes of padding at address 0x112,這是提示地址沒對齊,那就在末尾添加一個對齊指令,具體代碼如下:

OS_CPU_PendSVHandler

CPSID I ; Cortex-M7 errata notice. See Note #5

MOV32 R2, OS_KA_BASEPRI_Boundary ; Set BASEPRI priority level required for exception preemption

LDR R1, [R2]

MSR BASEPRI, R1

DSB

ISB

CPSIE I

MRS R0, PSP ; PSP is process stack pointer

STMFD R0!, {R4-R11, R14} ; Save remaining regs r4-11, R14 on process stack

MOV32 R5, OSTCBCurPtr ; OSTCBCurPtr->StkPtr = SP;

LDR R1, [R5]

STR R0, [R1] ; R0 is SP of process being switched out

; At this point, entire context of process has been saved

MOV R4, LR ; Save LR exc_return value

BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop

MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy;

MOV32 R1, OSPrioHighRdy

LDRB R2, [R1]

STRB R2, [R0]

MOV32 R1, OSTCBHighRdyPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;

LDR R2, [R1]

STR R2, [R5]

ORR LR, R4, #0x04 ; Ensure exception return uses process stack

LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;

LDMFD R0!, {R4-R11, R14} ; Restore r4-11, R14 from new process stack

MSR PSP, R0 ; Load PSP with new process SP

MOV32 R2, #0 ; Restore BASEPRI priority level to 0

MSR BASEPRI, R2

BX LR ; Exception return will restore remaining context

ALIGN

END

再次編譯,os_cpu_a.asm文件內沒有錯誤,還有兩個小錯誤:

將os_cpu_c.c中os.h的頭文件路徑修改意見,將bsp_cpu.c中的bsp_clk.h頭文件注釋掉,再次編譯。報錯信息如下圖:

發(fā)現(xiàn)報錯信息都在bsp_cpu.c當中,而且都是和時鐘頻率相關的,打開源碼例程中的bsp_clk.c文件,查看BSP_ClkFreqGet()函數,發(fā)現(xiàn)里面調用的函數不就是HAL庫提供的嗎,那我們直接將bsp_cpu.c中的時鐘獲取函數修改為HAL庫提供的函數,不就OK了嗎。修改后的代碼如下所示:

#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)

void CPU_TS_TmrInit (void)

{

CPU_INT32U fclk_freq;

CPU_INT32U reg_val;

/* ---- DWT WRITE ACCESS UNLOCK (CORTEX-M7 ONLY!!) ---- */

reg_val = CPU_BSP_REG_DWT_LSR; /* Read lock status register. */

if ((reg_val & CPU_BSP_BIT_DWT_LSR_SLI) != 0) { /* Check if Software lock control mechanism exits */

if ((reg_val & CPU_BSP_BIT_DWT_LSR_SLK) != 0) { /* Check if DWT access needs to be unlocked */

CPU_BSP_REG_DWT_LAR = CPU_BSP_DWT_LAR_KEY; /* Unlock DWT write access. */

}

}

fclk_freq = HAL_RCC_GetHCLKFreq();

CPU_BSP_REG_DEMCR |= DEF_BIT_24; /* Set DEM_CR_TRCENA */

CPU_BSP_REG_DWT_CR |= DEF_BIT_00; /* Set DWT_CR_CYCCNTENA */

CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);

}

#endif

#if (CPU_CFG_TS_32_EN == DEF_ENABLED)

CPU_INT64U CPU_TS32_to_uSec (CPU_TS32 ts_cnts)

{

CPU_INT64U ts_us;

CPU_INT64U fclk_freq;

fclk_freq = HAL_RCC_GetHCLKFreq();

ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);

return (ts_us);

}

#endif

#if (CPU_CFG_TS_64_EN == DEF_ENABLED)

CPU_INT64U CPU_TS64_to_uSec (CPU_TS64 ts_cnts)

{

CPU_INT64U ts_us;

CPU_INT64U fclk_freq;

fclk_freq = HAL_RCC_GetHCLKFreq();

ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);

return (ts_us);

}

#endif

修改完之后,再次編譯,發(fā)現(xiàn)了很多重復定義的錯誤,都適合__dbg_ucos-iii.c文件相關,那就直接移除掉這個文件,再編譯看看結果如何。

編譯之后發(fā)現(xiàn)只有一個未定義的錯誤,打開os_cpu.h頭文件,發(fā)現(xiàn)了下面這行代碼:

#define OS_TASK_SW_SYNC() __ISB()

明明定義了,卻還是提示未定義的錯誤,那我搜索了一下__ISB()函數,在cmsis_armcc.h中明確定義了,難道沒添加頭文件引起的嗎,那就添加頭文件再編譯一下,報錯信息更多了,那很明顯不是這個問題了。看到cmsis_armcc.h中有這一行代碼:

#define __ISB() do {\

__schedule_barrier();\

__isb(0xF);\

__schedule_barrier();\

} while (0U)

那就直接修改成

#define OS_TASK_SW_SYNC() __isb(0xF)

這樣編譯倒是沒問題了。但是系統(tǒng)運行起來有沒有問題就不知道,先這么做吧,這個頭文件中還有一行代碼也需要修改:

#ifdef__ARMVFP__

#define OS_CPU_ARM_FP_EN 1u

#else

#define OS_CPU_ARM_FP_EN 0u

#endif

修改為

#ifdef __TARGET_FPU_SOFTVFP

#define OS_CPU_ARM_FP_EN 1u

#else

#define OS_CPU_ARM_FP_EN 0u

#endif

編譯后無錯誤?,F(xiàn)在這系統(tǒng)能夠正常運行起來了嗎?講實話我也不太清楚,那就測試一下吧。

(三)測試系統(tǒng)

拷貝如下代碼至main.c中。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "bsp_cpu.h"

//任務優(yōu)先級

#define START_TASK_PRIO2

//任務堆棧大小

#define START_STK_SIZE 512

//任務控制塊

OS_TCB StartTaskTCB;

//任務堆棧

CPU_STK START_TASK_STK[START_STK_SIZE];

//任務函數

void start_task(void *p_arg);

//任務優(yōu)先級

#define LED0_TASK_PRIO3

//任務堆棧大小

#define LED0_STK_SIZE 128

//任務控制塊

OS_TCB Led0TaskTCB;

//任務堆棧

CPU_STK LED0_TASK_STK[LED0_STK_SIZE];

void led0_task(void *p_arg);

//任務優(yōu)先級

#define LED1_TASK_PRIO4

//任務堆棧大小

#define LED1_STK_SIZE 128

//任務控制塊

OS_TCB Led1TaskTCB;

//任務堆棧

CPU_STK LED1_TASK_STK[LED1_STK_SIZE];

//任務函數

void led1_task(void *p_arg);

//任務優(yōu)先級

#define FLOAT_TASK_PRIO5

//任務堆棧大小

#define FLOAT_STK_SIZE256

//任務控制塊

OS_TCBFloatTaskTCB;

//任務堆棧

CPU_STKFLOAT_TASK_STK[FLOAT_STK_SIZE];

//任務函數

void float_task(void *p_arg);

/*****************************************************************************************************************************************

* Function Name: main

* Input: None

* Output: None

* Returns: None

* Description: 主函數

* Note: None

*****************************************************************************************************************************************/

int main(void)

{

OS_ERR err;

CPU_SR_ALLOC();

HW_Init();

MT_Init();

OSInit(&err); //初始化UCOSIII

CPU_CRITICAL_ENTER(); //進入臨界區(qū)

//創(chuàng)建開始任務

OSTaskCreate((OS_TCB * )&StartTaskTCB,//任務控制塊

(CPU_CHAR* )"start task", //任務名字

(OS_TASK_PTR )start_task, //任務函數

(void* )0,//傳遞給任務函數的參數

(OS_PRIO )START_TASK_PRIO, //任務優(yōu)先級

(CPU_STK * )&START_TASK_STK[0],//任務堆棧基地址

(CPU_STK_SIZE)START_STK_SIZE/10,//任務堆棧深度限位

(CPU_STK_SIZE)START_STK_SIZE,//任務堆棧大小

(OS_MSG_QTY )0,//任務內部消息隊列能夠接收的最大消息數目,為0時禁止接收消息

(OS_TICK )0,//當使能時間片輪轉時的時間片長度,為0時為默認長度,

(void * )0,//用戶補充的存儲區(qū)

(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任務選項,為了保險起見,所有任務都保存浮點寄存器的值

(OS_ERR * )&err);//存放該函數錯誤時的返回值

CPU_CRITICAL_EXIT();//退出臨界區(qū)

OSStart(&err); //開啟UCOSIII

while(1)

{

}

}

//開始任務函數

void start_task(void *p_arg)

{

OS_ERR err;

CPU_SR_ALLOC();

p_arg = p_arg;

CPU_Init();

#if OS_CFG_STAT_TASK_EN > 0u

OSStatTaskCPUUsageInit(&err); //統(tǒng)計任務

#endif

#ifdef CPU_CFG_INT_DIS_MEAS_EN//如果使能了測量中斷關閉時間

CPU_IntDisMeasMaxCurReset();

#endif

#ifOS_CFG_SCHED_ROUND_ROBIN_EN//當使用時間片輪轉的時候

//使能時間片輪轉調度功能,設置默認的時間片長度s

OSSchedRoundRobinCfg(DEF_ENABLED,10,&err);

#endif

CPU_CRITICAL_ENTER();//進入臨界區(qū)

//創(chuàng)建LED0任務

OSTaskCreate((OS_TCB * )&Led0TaskTCB,

(CPU_CHAR* )"led0 task",

(OS_TASK_PTR )led0_task,

(void* )0,

(OS_PRIO )LED0_TASK_PRIO,

(CPU_STK * )&LED0_TASK_STK[0],

(CPU_STK_SIZE)LED0_STK_SIZE/10,

(CPU_STK_SIZE)LED0_STK_SIZE,

(OS_MSG_QTY )0,

(OS_TICK )0,

(void * )0,

(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,

(OS_ERR * )&err);

//創(chuàng)建LED1任務

OSTaskCreate((OS_TCB * )&Led1TaskTCB,

(CPU_CHAR* )"led1 task",

(OS_TASK_PTR )led1_task,

(void* )0,

(OS_PRIO )LED1_TASK_PRIO,

(CPU_STK * )&LED1_TASK_STK[0],

(CPU_STK_SIZE)LED1_STK_SIZE/10,

(CPU_STK_SIZE)LED1_STK_SIZE,

(OS_MSG_QTY )0,

(OS_TICK )0,

(void * )0,

(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,

(OS_ERR * )&err);

//創(chuàng)建浮點測試任務

OSTaskCreate((OS_TCB * )&FloatTaskTCB,

(CPU_CHAR* )"float test task",

(OS_TASK_PTR )float_task,

(void* )0,

(OS_PRIO )FLOAT_TASK_PRIO,

(CPU_STK * )&FLOAT_TASK_STK[0],

(CPU_STK_SIZE)FLOAT_STK_SIZE/10,

(CPU_STK_SIZE)FLOAT_STK_SIZE,

(OS_MSG_QTY )0,

(OS_TICK )0,

(void * )0,

(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,

(OS_ERR * )&err);

CPU_CRITICAL_EXIT();//進入臨界區(qū)

OSTaskSuspend((OS_TCB*)&StartTaskTCB,&err);//掛起開始任務

}

//led0任務函數

void led0_task(void *p_arg)

{

OS_ERR err;

p_arg = p_arg;

while(1)

{

HW_Led0_On(); //LED0打開

OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延時200ms

HW_Led0_Off(); //LED0關閉

OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延時500ms

}

}

//led1任務函數

void led1_task(void *p_arg)

{

OS_ERR err;

p_arg = p_arg;

while(1)

{

HW_Led1_On();

HW_Delay_ms(500);//延時500ms

HW_Led1_Off();

HW_Delay_ms(500);

OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_HMSM_STRICT,&err);

}

}

//浮點測試任務

void float_task(void *p_arg)

{

OS_ERR err;

CPU_SR_ALLOC();

static double double_num=0.00;

while(1)

{

double_num+=0.01f;

CPU_CRITICAL_ENTER();//進入臨界區(qū)

printf("double_num的值為: %.4f\r\n",double_num);

CPU_CRITICAL_EXIT();//退出臨界區(qū)

OSTimeDlyHMSM(0,0,0,20,OS_OPT_TIME_HMSM_STRICT,&err);

}

}

編譯后,燒寫進開發(fā)板,查看現(xiàn)象:LED燈沒亮;那系統(tǒng)肯定沒有運行起來,通過Debug看看哪里出問題了,結果發(fā)現(xiàn)程序停在了如下地方:

那說明是PendSV中斷處理出了問題,看看整個工程中哪里需要調整。os_cpu_a.asm匯編文件中定義了OS_CPU_PendSVHandler函數,這是Micrium官方移植例程中修改了PendSV中斷函數的名稱,所以這邊需要修改回來,然后再編譯報該函數的重定義錯誤。

這邊屏蔽掉stm32f7xx_it.c中的PendSV_Handler函數定義,再次編譯;沒有報錯,那就再下載驗證一下。結果還是失敗了,那就再Debug一下,看看是哪里的問題,發(fā)現(xiàn)程序運行之后,開始任務調度之后就掛在空閑任務上。找來找去沒發(fā)現(xiàn)什么問題,本來都準備放棄了,后來看到操作系統(tǒng)的時間都是通過滴答定時器中斷產生的,然后仔細看了一下代碼,雖然使用了滴答定時器,但是沒有使用中斷,那趕緊加上試試,順便將stm32f7xx_it.h中定義的滴答定時器中斷函數屏蔽掉。編譯之后沒報錯,那就在測試一下。終于,LED燈如愿的閃爍起來 ,串口也正常工作起來了,說明操作系統(tǒng)真正運行起來了。

下面附上移植后的工程。

鏈接:https://pan.baidu.com/s/1AGw1SWNMI_BpX7NLsxvQdg

提取碼:bzne

復制這段內容后打開百度網盤手機App,操作更方便哦

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結

以上是生活随笔為你收集整理的mysql 移植ucos_基于STM32F767的UCOSIII移植学习的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。