精华内容
下载资源
问答
  • 图:FreeRTOS的官网上图中,点击能支持的MCU,找到Xilinx的,如下图: 图:SupportMCUs 支持Xilinx的页面可以看到,支持的工具是GCC(后面我们保留源码文件夹就只保留GCC的就OK。)。我下载的是v10.0.0的版本...

    软件版本:VIvado HLx 2018.2

    从FreeRTOS的官网中下载源代码:

    https://www.freertos.org/a00104.html

    图:FreeRTOS的官网

    上图中,点击能支持的MCU,找到Xilinx的,如下图:

    图:SupportMCUs 支持Xilinx的页面

    可以看到,支持的工具是GCC(后面我们保留源码文件夹就只保留GCC的就OK。)。

    我下载的是v10.0.0的版本(因为在2018.2自带的FreeRTOS BSP是10.0.0的),删除源码中不必要的文件夹(有关编译器的只保留GCC,有关硬件的只保留Cortex A9),最后保留下来的图下所示,并创建SourceInsight工程。

    图:删除源码中的无关文件夹

    其实Xilinx 提供的BSP有选项可以自带BSP(参考FreeRTOS网站:https://www.freertos.org/a00090.html#XILINX),不用做过多的移植,直接写应用程序就OK,下载源码是为了学习FreeRTOS,了解其原理。

    在BSP源码中,有一个配置文件FreeRTOSConfig.h,如下图。

    图:FreeRTOSConfig.h

    不同架构的MCU在使用的时候配置也不同,在此配置文件中可以完成FreeRTOS的裁剪和配置。注释部分写得很清楚,不要在这个头文件中做任何编辑,需要改变配置在Board Support Package Settings中完成,如下图。

    图:Board Support Package Settings

    这个配置头文件FreeRTOSConfig.h主要包含“INCLUDE_xxx”开始的宏和“configxxx”开始的宏,具体每个宏控制什么,表达什么意思,可以参照正点原子的《FreeRTOS开发手册.pdf》第三章的内容,这个教程在他们官网上下载。

    展开全文
  • 基于之前的分析,freeRTOS的移植主要集中在以下部分,它们对应的源文件如下移植之前必须清楚待移植嵌入式系统的硬件架构,尤其是CPU和存储器的相关细节。...以下将以freeRTOS官网上给出的基于ZYNQ_Z...

    基于之前的分析,freeRTOS的移植主要集中在以下部分,

    它们对应的源文件如下

    移植之前必须清楚待移植嵌入式系统的硬件架构,尤其是CPU和存储器的相关细节。后边将一一提到。实际上freeRTOS需要移植的必要代码都已经在portable.h中声明(不含freeRTOS_Config.h配置的可选功能),我们只需要按照该文件填写好对应的宏和函数即可。

    以下将以freeRTOS官网上给出的基于ZYNQ_ZC702的工程,对一些常见的需要移植的代码进行分析。

    初始化Task Stack

    对应函数声明强制如下,

    StackType_t*pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void*pvParameters )

    其在freeRTOS创建TASK时被调用,用于初始化TASK的STACK,细节参考API函数xTaskCreate()、xTaskCreateStatic()、xTaskCreateRestricted和xTaskCreateRestrictedStatic()。

    该函数的处理十分简单,实际就是压栈过程,但寄存器的取值完全用用户确定,但是需要注意以下几点

    前两点需要用户查询CPU相关硬件手册,是必须做的。后两者并不强制要求,但是在实际移植中常常用到,可以用来检测OS崩溃。

    若业务代码没有频繁创建TASK,处于便于维护的考虑,建议用C语言实现。

    以下为freeRTOS官网提供的部分代码,可见其认为栈是向下生长的,按照R15到R0的顺序进行入栈的,出栈时必须保证这样的顺序。

    启动调度器

    对应函数声明强制如下,

    BaseType_t xPortStartScheduler( void )

    其在freeRTOS提供的API函数vTaskStartScheduler()中调用,用于OS启动时设置ISR、初始系统硬件和运行firstTASK。

    其中,

    freeRTOS官网上的代码实际上是使用函数vConfigureTickInterrupt()来设置中断和完成硬件初始化的,然后调用汇编语言实现的函数vPortRestoreTaskContext()运行first TASK

    vConfigureTickInterrupt()的基本流程如下图所示,其中使用了大量的ZYNQ 7000的提供的BSP,对于其他的硬件模块,也可以使用类似的流程完成相应中断设置和初始化

    其中,

    只需要在首次配置中断时使用,使用BSP提供的API函数XScuGic_CfgInitialize()

    以下为相应代码,实际上所有外设中断都可以如是配置。

    vPortRestoreTaskContext()实际上就是出栈的处理过程,也用于任务切换的处理过程,在后边会提到。

    ISR

    一般而言,ISR处理过程如下图所示,包含压栈、用户自定义处理和出栈过程,

    其中,

    该部分的移植需要特别考虑如何提高出栈和压栈代码的效率,以及提供给用户更加方便的用户自定义处理过程的API接口。

    除此之外,还需要考虑如何将ISR注册到CPU认可的中断向量表中去。

    FreeRTOS使用了中断向量表替换的方式来完成注册,如下图所示,其中的函数vPortInstallFreeRTOSVectorTable()需要在操作系统启动前调用

    对应的中断处理向量表freertos_vector_table如下,

    PS:freertos_vector_table需要在链接器文件中注册,其中尤其要注意把vector_table的KEEP修饰关键字去掉

    freeRTOS提供了名为FreeRTOS_IRQ_Handler的函数来实现ISR,细节如下。

    压栈过程代码如下,其中的176行即对当前TASK进行压栈,在此之前,保存了了R14和SPSR,然后切入到SVC模式。

    用户自定义处理过程相关代码如下,其中,

    出栈过程相关代码如下,其中

    TASK切换

    如之前所述,TASK切换主要是压栈和出栈操作。freeRTOS还提供了了以API函数用于选取当前处于ready状态的优先级最高的TASK,即vTaskSwitchContextConst(),并且freeRTOS还提供了名为pxCurrentTCB的变量用于指示当前TASK的栈顶地址。

    freeRTOS提供函数FreeRTOS_SWI_Handler用于TASK切换,

    其中portSAVE_CONTEXT为实现压栈的宏,其中首先切换到了SYS模式,然后将必要的寄存器,中断嵌套层数(ulCriticalNestingConst)等全部入栈保存。

    其中portRESTORE_CONTEXT为实现压栈的宏,其中过程与portSTORE_CONTEXT()刚好相反,但是由于OS提供的vTaskSwitchContextConst()中已经改变了当前OS执行TASK信息(pxCurrentTCBConst),因此出栈后切换到到了另外一TASK。

    中断控制

    如之前所属,OS基于中断实现了临界区和主动触发TASK切换的功能,它们以宏的方式定义,名称如下,

    freeRTOS官网上提供了相关代码,非常简单易懂,这里就不在累述。

    展开全文
  • 本帖最后由 八度空间 于 2017-3-12 11:32 编辑移植硬件平台:项目板子编译环境:IAR7.6库版本:V1.2.2FreeRTOS版本:V9.0.0一、下载FreeRTOS源码官网直接下载http://www.freertos.org/a00104.html或者原子哥光盘附带...

    本帖最后由 八度空间 于 2017-3-12 11:32 编辑

    移植硬件平台:项目板子

    编译环境:IAR7.6

    库版本:V1.2.2

    FreeRTOS版本:V9.0.0

    一、下载FreeRTOS源码

    官网直接下载http://www.freertos.org/a00104.html或者原子哥光盘附带的,本贴也上传

    1.jpg (44.2 KB, 下载次数: 9)

    2017-3-12 10:18 上传

    二、解压源码

    2.1、新建工程,工程中建FreeRTOS文件夹存放源码

    2.2、打开解压文件“..\FreeRTOSv9.0.0”

    2.jpg (22.87 KB, 下载次数: 12)

    2017-3-12 10:25 上传

    2.3、打开“FreeRTOS”文件夹,看到“Source”文件夹,这就是源码了,至于“FreeRTOS-Plus”文件夹就大家自己研究了,像研究水果6plus一样研究

    3.jpg (17.61 KB, 下载次数: 9)

    2017-3-12 10:28 上传

    将此文件夹所有东西拷贝到工程新建的“FreRTOS”文件夹中

    4.jpg (22.96 KB, 下载次数: 7)

    2017-3-12 10:30 上传

    2.4、在源码demo文件夹里“..\FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK”(STM32F302是Cortex-M4内核的)拷贝“FreeRTOSConfig.h”文件到工程中(放位置随意)

    5.jpg (40.24 KB, 下载次数: 11)

    2017-3-12 10:35 上传

    6.jpg (41.95 KB, 下载次数: 11)

    2017-3-12 10:37 上传

    二、打开IAR软件新建工程(可参考http://www.openedv.com/thread-74004-1-1.html这贴进行,至于MDK就大家自行新建了

    ),往文件夹丢文件就是了

    7.jpg (24.39 KB, 下载次数: 7)

    2017-3-12 10:40 上传

    “port.c和portmacro.h”文件路径“..\FreeRTOS\portable\IAR\ARM_CM4F”

    “portasm.s”文件路径(IAR工程必须添加,MDK工程没有的):“..\FreeRTOS\portable\IAR\ARM_CM4F”

    ”heap_x“文件路径:”..\FreeRTOS\portable\MemMang“

    三、配置工程,添加头文件路径(可参考http://www.openedv.com/thread-74004-1-1.html这贴进行)

    8.jpg (62.16 KB, 下载次数: 7)

    2017-3-12 10:46 上传

    四、配置IAR环境完成

    4.1、编写main函数

    9.jpg (15.63 KB, 下载次数: 4)

    2017-3-12 10:48 上传

    就弄了两个任务在跑,一个是闪灯(板子上只有一个LED),一个是串口每隔1s就输出一个浮点运算(前面说的STM32F302使用的是Cortex-M4内核),有带浮点计算单元的FPU

    4.2、修改文件”FreeRTOSConfig.h“

    打开文件,在开头位置,增加相关的环境预编译条件

    12.jpg (38.46 KB, 下载次数: 5)

    2017-3-12 10:57 上传

    上一个框框就是文件自带的,我增加几个编译环境的宏定义判断,或者去掉也行,下面一个框框就是MDK编译环境的区别了,接下来就是FreeRTOS裁剪宏定义了

    4.3、修改”SYSTEM“相关文件

    4.3.1、修改”sys“文件

    主要是增加宏定义相关说明,详见工程

    4.3.2、修改”delay“文件

    增加FreeRTOS支持

    [mw_shl_code=applescript,true]/**

    *****************************************************************************

    * @name   : 初始化延时函数

    *

    * @Brief  : 主要Cortex-M3内核对系统时钟计数单元

    *           详细见《Cortex-M3权威指南(中文)》第216页 a)  时钟周期(CYCCNT) 的内容

    *           周立功《CM3计数参考手册》第28、29页、第110、125页

    *

    * @Input  : none

    *

    * @Output : none

    *

    * @Return : none

    *****************************************************************************

    **/

    void delay_init(void)

    {

    #if _DELAY_TYPE == 1  //使用其他资源做延时时基

    DEM_CTRL |= 1<<24;  //该位必须为1,使能跟踪和调试模块的使用。详细见:周立功《CM3计数参考手册》第115页介绍

    //在没有使用跟踪时,该位使能对功率使用的控制。它能够由应用程序或调试器使能,供ITM使用

    //在DWT能够使用之前,调试异常和监控控制寄存器的TRCENA(bit24)位必须置位

    DWT_CTRL |= 1<<0;  //使能DWT_CYCCNT计数器。

    //如果不使能,则计数器不执行计数操作,因此不会产生PC采样或CYCCNTENA事件。

    //在正常使用时,CYCCNT计数器应由调试器初始化为0。

    #else  //使用嘀嗒定时器做延时时基

    #if _SYSTEM_SUPPORT_ROTS == 1  //运行了OS

    uint32_t RELOAD = 0;  //挡计数器倒数到0时的重装值,有效位:0 ~ 23

    #endif

    #if _SYSTEM_SUPPORT_ROTS == 1  //运行了OS

    #if _RTOS_TYPE == 2  //FreeRTOS

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);

    fac_us = SystemCoreClock / 1000000;

    RELOAD = SystemCoreClock / 1000000;

    #endif

    #else

    /* 根据SysTick定时器的时钟分频来确定重装值 */

    /* 8分频时除以8000‘000,1分频时除以1000’000 */

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);  //选择外部时钟 HCLK / 8

    fac_us = SystemCoreClock / 8000000;  //系统时钟的 1/8

    #endif

    #if _SYSTEM_SUPPORT_ROTS == 1  //运行了OS

    #if _RTOS_TYPE == 0  //uCOS

    RELOAD = SystemCoreClock / 8000000;        //每秒钟的计数次数,单位Hz

    RELOAD *= 1000000 / OS_TICKS_PER_SEC;        //根据操作系统的心跳时长来计算溢出时间,单位:KHz

    //RELOAD为24位计数器,最大值为:16777216

    fac_ms = 1000 / OS_TICKS_PER_SEC;

    #elif _RTOS_TYPE == 1  //RAW-OS

    RELOAD = SystemCoreClock / 8000000;        //每秒钟的计数次数,单位Hz

    RELOAD *= 1000000 / RAW_TICKS_PER_SECOND;  //根据操作系统的心跳时长来计算溢出时间,单位:KHz

    //RELOAD为24位计数器,最大值为:16777216

    fac_ms = 1000 / RAW_TICKS_PER_SECOND;

    #elif _RTOS_TYPE == 2  //FreeRTOS

    RELOAD *= 1000000 / configTICK_RATE_HZ;  //设置溢出时间

    //RELOAD为24位计数器,最大值为:16777216

    fac_ms = 1000 / configTICK_RATE_HZ;

    #endif

    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;        //开启SysTick定时器中断请求

    SysTick->LOAD = RELOAD;        //溢出计数值,每1/TICKINT_CNT秒中断一次

    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;      //开始倒数

    #else  //没有运行OS

    fac_ms = (uint16_t)fac_us*1000;        //ms需要的SysTick时钟数

    #endif

    #endif  //end _DELAY_TYPE

    }[/mw_shl_code]

    [mw_shl_code=applescript,true]/**

    *****************************************************************************

    * @Name   : 延时n个us

    *

    * @Brief  : none

    *

    * @Input  : nus:要延时的us数

    *

    * @Output : none

    *

    * @Return : none

    *****************************************************************************

    **/

    void delay_us(uint32_t nus)

    {

    #if _DELAY_TYPE == 1  //使用其他资源做延时时基

    uint32_t savecount,endcnt,CPU_cnt;

    savecount = DWT_CYCCNT;        //保存计数器当前数值

    CPU_cnt = nus*(SystemCoreClock/(1000*1000));        //计算达到所需延时值的CPU时钟数。即多少个系统时钟计数

    //得到更精确延时时间,减去前面代码运行的时间即可

    endcnt = savecount + CPU_cnt;        //计算所需延时时间DWT_CYCCNT的计数值,在溢出时返回到0

    if(endcnt > savecount)        //所需延时值大于当前计数值

    {

    while(DWT_CYCCNT < endcnt);        //循环等待所需要的延时时间的CPU时钟计数值

    }

    else        //小于当前计数值

    {

    while(DWT_CYCCNT > endcnt);        //等待计数器溢出翻转

    while(DWT_CYCCNT < endcnt);        //等待所需延时时间到达

    }

    #else  //使用嘀嗒定时器做延时时基

    uint32_t temp=0;

    #if _SYSTEM_SUPPORT_ROTS == 1  //运行了OS

    uint32_t VAL_Prev=0;  //开始计时之前的值

    uint32_t VAL_Now=0;   //当前计时值

    uint32_t VAL_cnt=0;   //计数

    uint32_t Reload=SysTick->LOAD;  //获取到LOAD的值

    temp = nus*fac_us;  //得到延时的节拍数

    #if _RTOS_TYPE == 0  //uCOS

    OSSchedLock();  //阻止ucos调度,防止打断us延时

    #elif _RTOS_TYPE == 1  // RAW-OS

    raw_disable_sche();  //阻止RAW-OS调度,防止打断us延时

    #elif _RTOS_TYPE == 2  //FreeRTOS

    #endif

    VAL_Prev = SysTick->VAL;  //保存当前的计数值

    while(1)

    {

    VAL_Now = SysTick->VAL;  //读取数值

    if(VAL_Now != VAL_Prev)

    {

    if(VAL_Now < VAL_Prev)  VAL_cnt += VAL_Prev-VAL_Now;  //因为SysTick是一个递减的定时器

    else                      VAL_cnt += Reload - VAL_Now + VAL_Prev;

    VAL_Prev = VAL_Now;  //刷新

    if(VAL_cnt >= temp)  break;  //超过/等于需要的延时值了,则退出循环

    }

    };

    #if _RTOS_TYPE == 0  //uCOS

    OSSchedUnlock();  //开启ucos调度

    #elif _RTOS_TYPE == 1  // RAW-OS

    raw_enable_sche();  //开启RAW-OS调度

    #elif _RTOS_TYPE == 2  //FreeRTOS

    #endif

    #else  //没有运行os

    SysTick->LOAD = nus*fac_us; //时间加载

    SysTick->VAL = 0x00;        //清空计数器

    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;      //开始倒数

    do

    {

    temp = SysTick->CTRL;

    }while(temp&0x01&&!(temp&(1<<16)));        //等待时间到达

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;        //关闭计数器

    SysTick->VAL = 0x00;        //清空计数器

    #endif  //end _SYSTEM_SUPPORT_ROTS

    #endif  //end _DELAY_TYPE

    }

    /**

    *****************************************************************************

    * @Name   : 延时n个ms

    *

    * @Brief  : 1、延时ms级定义,延时范围:1 ~ 65535ms。延时最大值可变,不爆机uint32_t/1000范围即可

    *           2、SysTick->LOAD为24位寄存器,所以,最大延时为:

    *              nms <= 0xffffff*8*1000/SYSCLK

    *              SYSCLK单位为Hz,nms单位为ms

    *              注意nms的范围 0 ~ 1864(72M情况下)

    *

    * @Input  : nms:要延时的ms数

    *

    * @Output : none

    *

    * @Return : none

    *****************************************************************************

    **/

    void delay_ms(uint16_t nms)

    {

    #if _DELAY_TYPE == 1  //使用其他资源做延时时基

    delay_us((uint32_t)(nms*1000));  //采用普通的延时

    #else  //使用嘀嗒定时器做延时时基

    #if _SYSTEM_SUPPORT_ROTS == 1  //运行了OS

    #if _RTOS_TYPE == 0  //uCOS

    if (OSRunning == OS_TRUE && OSLockNesting == 0)  //ucos已经在跑了

    #elif _RTOS_TYPE == 1  // RAW-OS

    if (raw_os_active == RAW_OS_RUNNING && raw_int_nesting == 0)

    #elif _RTOS_TYPE == 2  //FreeRTOS

    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)  //系统已经在运行

    #endif

    {

    if(nms > fac_ms)  //延时大于ucos基数

    {

    #if _RTOS_TYPE == 0  //uCOS

    OSTimeDly(nms/fac_ms);  //采用ucos延时

    #elif _RTOS_TYPE == 1  // RAW-OS

    raw_sleep(nms / fac_ms);

    #elif _RTOS_TYPE == 2  //FreeRTOS

    vTaskDelay(nms/fac_ms);  //FreeRTOS延时

    #endif

    }

    nms %= fac_ms;  //ucos无法提供小于节拍的延时了

    }

    if (nms == 0)  return;  //没意义了,直接退出,不加这句,在运行RAW-OS时会死机

    delay_us((uint32_t)(nms*1000));  //采用普通的延时

    #else  //没有运行os

    uint32_t temp;

    SysTick->LOAD = (uint32_t)nms*fac_ms;        //时间加载(SysTick->LOAD为24bit)

    SysTick->VAL = 0x00;           //清空计数器

    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;      //开始倒数

    do

    {

    temp = SysTick->CTRL;

    }while(temp&0x01&&!(temp&(1<<16)));        //等待时间到达

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;        //关闭计数器

    SysTick->VAL = 0x00;        //清空计数器

    #endif  //end _SYSTEM_SUPPORT_ROTS

    #endif  //end _DELAY_TYPE

    }[/mw_shl_code]

    4.3.3、修改”usart“文件

    主要修改串口中断接收函数兼容FreeRTOS

    [mw_shl_code=applescript,true]/**

    *****************************************************************************

    * @Name   : 串口接收中断服务程序

    *

    * @Brief  : none

    *

    * @Input  : none

    *

    * @Output : none

    *

    * @Return : none

    *****************************************************************************

    **/

    void USART1_IRQHandler(void)

    {

    #if USART_USER_DMA_EN

    uint16_t usart_rx_len = 0;

    #else

    uint8_t res;

    #endif

    #if _SYSTEM_SUPPORT_ROTS == 1

    #if _RTOS_TYPE == 0  //uCOS

    OSIntEnter();

    #elif _RTOS_TYPE == 1  //RAW-OS

    raw_enter_interrupt();

    #elif _RTOS_TYPE == 2  //FreeRTOS

    #endif

    #endif

    #if USART_USER_DMA_EN

    if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)

    {

    /* ==================== STM32F0xx Series chips ==================== */

    #if __STM32xx == 0x00  //STM32F0xx

    DMA_Cmd(DMA1_Channel3, DISABLE);  //先关闭,预防干扰

    usart_rx_len = USART_REC_LEN - DMA_GetCurrDataCounter(DMA1_Channel3);

    DMA1_Channel3->CNDTR = (uint16_t)USART_REC_LEN;

    /* ==================== STM32F4xx Series chips ==================== */

    #elif __STM32xx == 0x04  //STM32F4xx

    DMA_Cmd(DMA2_Stream5, DISABLE);  //先关闭,预防干扰

    DMA_ClearFlag(DMA2_Stream5, DMA_FLAG_TCIF5);

    usart_rx_len = USART_REC_LEN - DMA_GetCurrDataCounter(DMA2_Stream5);

    DMA2_Stream5->NDTR = (uint16_t)USART_REC_LEN;

    #else  //STM32F10x or STM32F3xx

    DMA_Cmd(DMA1_Channel5, DISABLE);  //先关闭,预防干扰

    usart_rx_len = USART_REC_LEN - DMA_GetCurrDataCounter(DMA1_Channel5);

    DMA1_Channel5->CNDTR = (uint16_t)USART_REC_LEN;

    #endif

    //

    //判断是否接受到回车符

    //

    if (USART_RX_BUF[usart_rx_len-2] == 0x0D)  //CR (carriage return)

    {

    if (USART_RX_BUF[usart_rx_len-1] == 0x0A)  //LF (NL line feed, new line)

    {

    usart_rx_len -= 2;  //\r\n不计算在内

    USART_RX_STA = (usart_rx_len & 0x3FFF);  //得到接收数据长度

    USART_RX_STA |= 0x8000;  //标志接收完成标志

    }

    else

    {

    USART_RX_STA = 0;

    }

    }

    /* ==================== STM32F0xx Series chips ==================== */

    #if __STM32xx == 0x00  //STM32F0xx

    DMA_Cmd(DMA1_Channel3, ENABLE);

    /* ==================== STM32F4xx Series chips ==================== */

    #elif __STM32xx == 0x04  //STM32F4xx

    DMA_Cmd(DMA2_Stream5, ENABLE);

    #else  //STM32F10x or STM32F3xx

    DMA_Cmd(DMA1_Channel5, ENABLE);

    #endif

    (void)USART_ReceiveData(USART1);

    }

    USART_ClearITPendingBit(USART1, USART_IT_IDLE);

    #else

    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收到数据

    {

    res = USART_ReceiveData(USART1);  //读取接收到的数据

    if ((USART_RX_STA & 0x8000) == 0)  //接收未完成

    {

    if ((USART_RX_STA & 0x4000) != 0)  //接收到了0x0d

    {

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

    修改内容如下

    当用户数据当中有0x0d的时候修正的错误的判断

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

    if(res != 0x0a)

    {

    USART_RX_BUF[USART_RX_STA & 0x3fff] = 0x0d;        //补上丢失的0x0d数据

    USART_RX_STA++;

    USART_RX_BUF[USART_RX_STA & 0x3fff] = res;        //继续接收数据

    USART_RX_STA++;

    USART_RX_STA &= 0xbfff;                                                //清除0x0d标志

    }

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

    修改完成

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

    else

    {

    USART_RX_STA |= 0x8000;  //接收完成了

    }

    }

    else //还没收到0x0d

    {

    if(res == 0x0d)

    {

    USART_RX_STA |= 0x4000;

    }

    else

    {

    USART_RX_BUF[USART_RX_STA & 0x3fff] = res;

    USART_RX_STA++;

    if (USART_RX_STA > (USART_REC_LEN - 1))

    {

    USART_RX_STA = 0;//接收数据错误,重新开始接收

    }

    }

    }

    }        //end 接收未完成

    }        //end 接收到数据

    #endif

    #if _SYSTEM_SUPPORT_ROTS == 1

    #if _RTOS_TYPE == 0  //uCOS

    OSIntExit();

    #elif _RTOS_TYPE == 1  // RAW-OS

    raw_finish_int();

    #elif _RTOS_TYPE == 2  //FreeRTOS

    #endif

    #endif

    }[/mw_shl_code]

    五、至此,也差不多了,点击编译改错,最后得到这么一个框框提示

    10.jpg (13.9 KB, 下载次数: 10)

    2017-3-12 11:09 上传

    大家是否也觉得不可思议,头文件路径已经添加了,为啥报错???有木有有木有(在这里我想了很久,不明白IAR为啥报错)

    11.jpg (57.11 KB, 下载次数: 3)

    2017-3-12 10:53 上传

    打开”FreeRTOSConfig.h“文件查看报错在哪里,仔细看报错文件路径

    13.jpg (19.99 KB, 下载次数: 10)

    2017-3-12 11:08 上传

    后面提示的是文件”portasm.s”路径报错,于是打开此文件,是任务切换什么的,汇编文件,再回头看看IAR配置,有这么一项

    14.jpg (42.13 KB, 下载次数: 9)

    2017-3-12 11:11 上传

    汇编文件管理,看到一个Preprocessor选项,二话不说,增加路径

    15.jpg (44.86 KB, 下载次数: 6)

    2017-3-12 11:14 上传

    再次编译

    16.jpg (11.71 KB, 下载次数: 5)

    2017-3-12 11:14 上传

    没错误没警告

    六、下载到板子,看到LED在闪烁,接上串口,每隔一段时间输出一个小数,结果一致

    展开全文
  • freeRTOS移植——ZYNQ7000简介

    千次阅读 2018-06-10 11:42:28
    ZYNQ 7000使用AMR CortexA9 CPU,移植freeRTOS之前首先需要了解它的基本结构和配置,侧重于一下几点· 寄存器分布· 中断配置· 配套的汇编指令集· IRAM和DRAMPS:关于ARM的学习,个人认为,最好是以项目为驱动...

    ZYNQ 7000使用AMR CortexA9 CPU,移植freeRTOS之前首先需要了解它的基本结构和配置,侧重于一下几点

    ·       寄存器分布

    ·       中断配置

    ·       配套的汇编指令集

    ·       IRAM和DRAM

    PS:关于ARM的学习,个人认为,最好是以项目为驱动,为自己设定一个小项目,诸如这里讨论的移植freeRTOS,或是经典的跑马灯实验。基于设定的项目,直接去ARM官网上查找相应资料,其中英语可能会成为较大的阻碍,这就需要好好自己好好提升英语能力了。有人可能觉得百度或者各种中文论坛也不错,但我这次移植也去用了用,资料较少,而且大部分都相互抄袭,没有太多影响,作为入门的科普还行,想要进一步做项目还是得去官网。

     

    硬件架构

    ARM Cortex A9为双核结构,如下图所示,之前说的sector即为下图中的APU


    其中只需要重点关注,

    ·        ZYNQ 7000拥有两块ARMCortex A9 CPU,运行主频可配(我用的666.66667MHz)。

    ·        每块CPU都对应有32KB的ICache和DCache,它们共享512KB的L2 Cache和256KB的SRAM。

    ·        输入到sector的中断由GIC模块管理。

     

    寄存器

    ARM Cortex A9 CPU共计有37个寄存器,如下图所示,


    其中

    ·        ARM Cortex A9 CPU有多种运行模式,不同模式下访问的寄存器是不同的,RTOS的移植只关注其中几种

    ·       用户模式(user mode),正常运行模式,

    ·       系统模式(system mode),具有系统特权的运行模式

    ·       中断模式(IRQ mode),处理中断的运行模式

    ·       监督模式(Supervisor mode),OS保护模式,处理系统复位和软件中断的模式

    ·        寄存器分为通用寄存器和分组寄存器两类

    ·       R0~R7为通用寄存器,所有CPU运行模式下,CPU访问的R0~R7都是同一样的寄存器,都是R0_user~R7_user

    ·       R8~12在FIQ mode下,为R8_fiq~R12_fiq;其他模式下为R8_ user ~R12_ user,由此可见,FIQ的处理是可不需要压栈和出栈。

    ·       SP和LR,在user mode和system mode下为SP_user和LP_user,其他模式都为自己独有的寄存器SP_xx和LP_x,SP作为stack pointer register使用,LR用于存放函数调用时子函数执行完成后的指令返回地址。也被记为R13和R14

    ·       PC为通用寄存器,存放当前CPU下一步需要从ICache中取出的指令位置,其为当前执行的指令地址+x(CPU会提前取出多条指令优化排序执行),x为8(针对ARM指令)或4(针对Thmbr指令),也被记为R15

    ·       CPSR为当前CPU状态寄存器,其是通用寄存器

    ·       SPSR为CPU状态保存寄存器,除usermode和system mode外,每种模式都有自己独立的状态保存寄存器

     

    汇编指令

    ARM Cortex A9 CPU使用的汇编指令集为ARMv8,可以在其官网上找到相关文档,或者搜索相关指令,网址是:https://developer.arm.com/。文档非常冗长,建议是找个现成的汇编小程序,一边阅读一边查指令含义,如此可以很快地掌握常用指令。

    ARM指令集大致分为如下几类

    汇编其中使用的寄存器名如下图所示(实际上改为小写也行)


    除此之外,ARM的汇编指令还可以操作协处理器(NEON)的寄存器,它们的名称如下,


    中断

    ARM Cortex A9 CPU可处理的中断分为SGI、PPI和SPI三类

    ·        SGI,中断ID 1~15,为软件触发中断

    ·        PPI,中断ID 16~31,为私有中断,

    ·        SPI,中断ID 31~95,为共享中断,

    它们都由GIC进行管理,我们可以通过对GIC的配置来管理所有的中断。

     

    BSP

    ZYNQ 7000往往使用XILINK的SDK进行开发,其提供了一个名为BSP的软件工程用于封装硬件,可以简单地理解为硬件驱动库。如下图所示,它向OS和业务代码提供功能接口。实际上,BSP和OS我们往往将其通称为平台。


    XILINX提供的BSP比较庞大,包含了CPU所有相关硬件的驱动程序。这里我们只关心FreeRTOS的移植中要使用的中断向量表和定时器。

    对于中断向量表,可以在BPS中找到如下默认设置的中断向量表_vectors_table


    其中我们需要重点关注78行的SVCHandler和82行的IRQHandler,它们分别对应任务切换的中断和OS提供给用户的中断(包括用于时间片的中断)。

    但是该中断向量表定义的ISR并不能够用于支撑freeRTOS,需要进行改写。

     

     

    PS:这里83行和84行的IRQ和FIQ都可用于OS提供给用户的中断,它们分别对应CPU的IRQ和FIQ模式,我们暂时只使用IRQ。

     

    附:

    中断向量表的加载在boot过程中完成,其中vector_base为取值为_vectors_table的宏


    SVC的ISR函数如下



    IRQ的ISR函数如下,可见其是不能支持退出中断后的任务切换,需要进行改写。




    展开全文
  • 1,运行环境vivado2019.2,win10,ZYNQ 7000系列 2,FreeRTOS官网源码下载 https://www.freertos.org/ , 3,FreeRTOS 是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、...
  • <p>Beside the check for the frametype in <code>xNetworkInterfaceOutput(), it will call <code>vPrintResourceStats()</code> from FreeRTOS_IP.c, in stead of a local function <code>prvMonitorResources(), ...
  • 问题描述: zynq7000 上 PS standalone裸跑,PS timer计时器中断,PL-->PS中断均工作正常,将代码移植到freertos工程时,中断不执行,task运行正常。 解决: Xilinx FreeRTOS (9.0.1) BSP, 中有一个文件: ...
  • zynq freeRTOS初始化中断

    千次阅读 2019-02-19 22:55:24
    问题描述: zynq7000 上 PS standalone裸跑,PS timer计时器中断,PL--&gt;PS中断均工作正常,将代码移植到freertos工程时,中断不执行,task运行正常。 解决: Xilinx FreeRTOS (9.0.1) BSP, 中有一个文件: ....
  • ZYNQ7000 freertos 中断

    2019-01-17 22:34:36
    问题描述: zynq7000 上 PS standalone裸跑,PS timer计时器中断,PL--&gt;PS中断均工作正常,将代码移植到freertos工程时,中断不执行,task运行正常。 解决: Xilinx FreeRTOS (9.0.1) BSP, 中有一个文件: ...
  • 相对于复杂的 Linux,FreeRTOS 等实时操作系统给我们带来更灵活更方便的开发,更直接的和底层 FPGA 进行交互。 1,新建工程,OS Platform 选择 freertos901_xilinx 2,本实验选择 FreeRTOS Lwip Echo Server示范...
  • ZYNQ进阶之路9--PS端实现FreeRTOS嵌入式系统导论FreeRTOS简介实现步骤 导论 在之前的章节中我们我们完成了PS端、PL端和PS+PL的一些工程,本章节我们插入一个小插曲,讲解FreeRTOSZYNQ中是如何实现的。 FreeRTOS...
  • Xilinx ZYNQ FreeRTOS+Tracealyze(移植) PL端配置 使用ZYNQ IP Core,打开串口、网口等所需接口。(新手注意:需要生成bit文件后,并输出相应硬件平台,网上教程很多,请参考其它教程)。 PS端配置 创建任务,注意...
  • zynq FreeRTOS 不能进中断

    千次阅读 2019-02-16 23:33:58
    转载:https://forums.xilinx.com/t5/嵌入式软件开发/分享-在FreeRTOS...在FreeRTOS的main()函数里初始化设备,不能收到中断。 FreeRTOS在 void vTaskStartScheduler( void )里调用 configSETUP_TICK_INTERRUPT(),...
  • ZYNQ上使用FreeRTOS

    千次阅读 2018-12-02 21:20:56
    FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。 由于RTO...
  • 硬件:ZYNQ-7000 开发环境:XILINX SDK CPU0:linux CPU1:freertos 以下是调试freertos时的调试笔记,20191031。 正常情况下,FREERTOS具有CPU利用率统计功能。配置步骤如下: ① 自 定 义 配 置 一 下 ,首 先 在 ...
  • ARM启动一般从0x00000000开始启动,当然也有可能从SD、其他的地址(M3默认0x80000000),那么A9默认从0开始,打开vector_asm.s....global _freertos_vector_table .global _vector_table .global FIQInterrupt .g...
  • 使用普通的Timer中断方式时,Timer中断可以正常运行,但是UDP通信进程无法启动。其中TimerIntrHandler是中断服务程序,打印程序运行时间与从BRAM中读取的数据。 void SetupInterruptSystem(XScuGic *...
  • 一、ARM架构分析 在ARM有以上寄存器组,...任务用SYS寄存器组(USR组),操作系统用SVC组,中断用IRQ组,FreeRtos共用了三组以上的。 RTOS跑的任务都属于内核级线程,在SYS下,我们可以看到,RTOS保存数据以及回...
  • 本应用指南演示了如何使用FreeRTOS操作系统——Zynq-7000 AP SoC的两种推荐操作系统之一(另外一种是Linux)。 FreeRTOS是一种只含有少量文件的免费操作系统,易于连接、使用和维护。FreeRTOS支持多线程或任务、互斥...
  • ZYNQ7020+ OPENAMP+LINUX+freertos。方案合作联系本人 https://www.bilibili.com/read/cv8203311
  • ISE运行版本为ISE14.4 ;在zedboard上运行freertos并实现按键中断; 板级支持包下载页面:http://download.csdn.net/detail/oxp7085915/6729125
  • 总结Zynq-7000 这款器件中的Timer定时器中断,为FreeRTOS中断做准备。在 ZYNQ 的纯 PS 里实现私有定时器中断。 每隔一秒中断一次, 在中断函数里计数加 1, 通过串口打印输出。 私有中断PPI包含: 全局定时器, ...
  • ZYNQ下LINUX+FREERTOS同时运行

    千次阅读 2019-12-23 14:34:38
    zynq_fsbl . elf -- fpga -- u - boot -- add freertos_cpu1 . elf -- force 三、试验效果 执行 poke 0xfffffff0 0x18000000 启动cpu1的应用程序。效果如下: root@zedboard : ~ # poke 0xfffffff0 0x...

空空如也

空空如也

1 2 3 4 5 6
收藏数 106
精华内容 42
关键字:

freertoszynq