DSP/BIOS使用之初窥门径——滴答时钟及烧写Flash

操作平台和环境

  • DSP型号:TMS320C6713
  • 仿真器:XDS510PLUS
  • Flash型号:AM29LV800BT或AM29LV800BT都试过(一般接口一样,差别不大)
  • RAM型号:MT48LC16M16A2P(注意16位数据线接口)
  • DSP/BIOS库:V5.31.02
  • CSL库:(假定读者已经会使用了)

边写LED程序,边聊聊操作系统的滴答时钟

在上篇文章DSP-BIOS使用入门的基础上,这里用用DSP/BIOS操作系统的CLK和PRD模块,这两个模块涉及到硬件定时器,我们使用仿真器先在RAM上将LED闪烁灯的程序调通。

CLK作用:片上定时器管理,学过ARM的都知道滴答时钟,CLK就是DSP操作系统的滴答时钟!

学过操作系统的也都知道(当然,像在现在的学校,学过操作系统都不知道的不在少数):操作系统必须要提供时基,才能实现调度!这个时基就是滴答时钟提供的(PC也不例外,也有时基)。

但C6713上没有专门的滴答时钟模块,因此是通过DSP上的通用定时器触发,其中断函数也就是Timer的中断函数,比如要设置滴答时钟为1ms,则其属性可以设置如下:

上面配置Timer0滴答时钟,注意哦,Microseconds表示us,Millisecond才表示ms!

从上面配置也可以看到,Timer0的CPU中断号(CPU Interrupt)是HWI_INT14,我们到HWI(硬件中断模块)下看看是不是,

在CLK中配置为滴答时钟的Timer,滴答中断函数(也是Timer0中断函数)也固定了,这里是CLK_F_isr,不可修改!

练习:试试在CLK中配置其它的Timer,再看看HWI中对应的硬件中断的变化?
答案:CLK中配置的Timer与HWI中对应的Timer中断是关联的。

好了,我们说回写LED程序,就写一个最简单的吧——让一个LED灯闪烁,使用滴答时钟定时,时间间隔为1s。

滴答时钟不是1ms吗?怎么实现1s的定时呢?这就还得了解一个模块——周期函数PDR。PDR的触发是基于滴答时钟周期的倍数,PRD是一种特殊的软件中断(可以查看SWI模块下,有一个PDR_swi的软中断),这点与CLK不同,CLK是硬件Timer中断实现的。

如上图所示,勾选上Use CLK Manager to drive PDR后,就是用CLK周期计数来触发PDR。我们插入一个PDR对象LedLink_PDR,配置属性如下,

滴答时钟CLK既然是1ms,Period表示经过的滴答时钟次数(ticks),因此LedLink_PDR的周期为1ms*1000 = 1000ms = 1s,这就达到了定时1s的目的。我们接着在.c文件中实现上面的(软)中断函数LedLink,

#include "bios_firstcfg.h"
#include <csl.h>          // CSL 库头文件
#include <csl_gpio.h>     // CSL 库的GPIO头文件

static GPIO_Handle hGpio;

int main(void)
{
    CSL_init();

    hGpio = GPIO_open(GPIO_DEV0,GPIO_OPEN_RESET);
    GPIO_reset(hGpio);
    GPIO_pinEnable(hGpio,GPIO_PIN3);
    GPIO_pinDirection(hGpio,GPIO_PIN3,GPIO_OUTPUT);
    GPIO_pinWrite(hGpio,GPIO_PIN3,0);

    LOG_enable(&trace);
    LOG_printf(&trace, "Hello DSP/BIOS %d.", 0); 

    return 0;
} 

void LedLink(void)
{
    static Uint16 i =0;

    i = (i + 1) & 0x01;
    GPIO_pinWrite(hGpio,GPIO_PIN3, i);
}

搭建基本的BIOS工程基于上篇文章DSP-BIOS使用入门,func_task0、func_task1和swi_adc都是上篇文章中的在DSP/BIOS中使用任务和软中断的例程,这里其实没什么用,暂且不管。

要在硬件上跑,一定要在Global Setting中设置好,

另外硬件上——我的板子上GPIO_PIN3连接着LED,低电平点亮!cmd文件都是DSP/BIOS配置文件自动配置好了,不用管了暂时。挂上仿真器,下载到板子的RAM上运行!OK,成功!

DSP/BIOS操作系统启动过程

其实在上一篇中已经讲过DSP/BIOS的启动过程,这里不妨再唠叨一下:

  1. 系统上电复位,从Flash装载完程序后,首先从C/C++环境入口_c_int00开始执行
  2. 利用.cinit记录初始化.bss段
  3. 调用BIOS_init初始化用到的各个模块
  4. 处理.pinit表,如C++中的全局对象的构造函数就在这个时候执行
  5. 进入main函数执行
  6. main函数返回,调用BIOS_start启动DSP/BIOS操作系统

其实除了其中第1步对我们烧写Flash有指导意义外,其它各步骤都是无关紧要的(当然,仅就这里讨论的问题而言)。基于此,这里烧写Flash的思路就是:在系统复位后,程序跳转到_c_init00之前,写一段从Flash拷贝应用程序到内存的代码就好了!

迁移到操作系统的Flash烧写

在之前“TMS320C6713烧写Flash的通用方法”一文中,已经详述了如何烧写裸机的代码,这里只需要对DSP/BIOS工程做很少的改动,就可无缝的将之前的烧写方法用在这里,下面还是按步骤来,主要描述一些不同的地方(这样清晰些):

  1. 添加二级Bootloader用到的文件(3个)到工程中,如下图,

    确定下boot_c671x.s62文件中的copy_done函数是这样的:

    copy_done:
        mvkl .S2 _c_int00,b0
        mvkh .S2 _c_int00,b0
        b    .S2 b0
        nop   5
    

    而不是这样的:

    copy_done:
        mvkl .S2 _main,b0
        mvkh .S2 _main,b0
        b    .S2 b0
        nop   5
    

    因为我们要先执行从Flash拷贝代码到内存,再执行c_int00跳转到main函数。

    这里下载三个bootloader文件!如果您使用的RAM或Flash与我的不同,请修改c6713_emif.s62中关于EMIF接口的寄存器配置!

  2. 划分Memory,设置“段”

    这就按照“TMS320C6713烧写Flash的通用方法”中裸机划分内存的方法划分,

    MEMORY
    {
        BOOT_RAM   : o=00000000h,l=00000400h
        IRAM       : o=00000400h,l=00040000h
        FLASH_BOOT : o=90000000h,l=00000400h
        FLASH_REST : o=90000400h,l=000FFB00h
    }
    

    heap放在了IRAM上。

    如上图,也按照“TMS320C6713烧写Flash的通用方法”按中的cmd分配的,大都分配到IRAM中不容易出问题(虽然说多占用一些RAM吧)。

  3. 写cmd文件(user.cmd,如上图)

    DSP/BIOS已经自动生成了一个CMD文件,最好不要去修改,只需要将DSP/BIOS自动生成的从工程中移除(不是删了,而是Remove),自己新建一个,将DSP/BIOS的包含进来就行了,

    -lbios_firstcfg.cmd
    -lcsl6713.lib
    
    SECTIONS
    {
        /* RAM */
        .boot_load: {} > BOOT_RAM
    
        /* User defined */
    }
    

    -lbios_firstcfg.cmd将自动生成的包含进来,关键是增加了.boot_load段,该段专门用于放置二级Bootloader。将user.cmd包含到工程中。

  4. 修改DSP/BIOS复位中断

    在“TMS320C6713烧写Flash的通用方法”中,曾经修改vecs.s汇编文件,将原来的复位向量

    vectors:
    vector0:   VEC_ENTRY _c_int00    ;RESET
    vector1:   VEC_ENTRY _vec_dummy  ;NMI
    vector2:   VEC_ENTRY _vec_dummy  ;RSVD
    

    改成了

    vectors:
    vector0:   VEC_ENTRY _boot       ;RESET
    vector1:   VEC_ENTRY _vec_dummy  ;NMI
    vector2:   VEC_ENTRY _vec_dummy  ;RSVD
    

    这里也一样,只不过可以通过IDE直接修改,

    这里的_boot就是二级Bootloader文件boot_c671x.s62中的boot段。

  5. 好了,没什么事了,你可以编译,接着按“TMS320C6713烧写Flash的通用方法”中的方法完成烧写了。

给自己也给大家的忠告

还在1~2个月之前,我还对DSP烧写Flash一无所知,更对DSP/BIOS一无所知,然后,从网络上Download了十来篇论文,然后一篇一篇的看了一遍,虽说不能立刻完全明白,但零星的还是感觉知道了那么一点,然后准备自己动手写,却发现无处着手——那些论文尽是框架大论!完全无法满足初学者的需求。

于是又在网上Google/Baidu浪淘沙一样的想找一些简单的,尤其是给出几乎每步详细步骤的,可惜的是——毫无所获!后来想想,折腾了这么几天,还是不知道从哪入手,不行了,于是去找来了TI的关于二级Bootloader的手册http://www.ti.com.cn/cn/lit/an/spra999a/spra999a.pdf,一页页的看(其实手册很短,也就十几二十页),突然发现慢慢有了些眉目。TI的手册上给出了二级引导的源码,并描述了那样做的原因和过程,于是根据该手册提供的相关资料一点点将Bootloader的过程拼凑了起来!关键是在_c_int00和main函数之间下功夫。

后来就参考TI的文档开始写了,但启动文件是写好了,但怎么烧写到Flash中一直困扰着我,如果烧写和应用程序在同一个程序中,那不是就成了“鸡生蛋还是蛋生鸡”的问题了吗?(其实这个可以通过硬件上外置一个拨码开关来设置,就可以令程序自烧写)。然而我也没有开关,从一个QQ群里咨询了一位大牛,大牛给了我一份他烧写的方法,顿时豁然开朗,把DSP张载程序后在内存运行的东西先都读出来,在通过另一个工程烧写不就可以了吗?我最后就是这么做的,在这过程中还一直庆幸自己对cmd文件、内存等还算了解,甚至在将从内存中导出的东西修改成头文件还用到了VIM(神一样的编辑器)。学习DSP/BIOS,我庆幸之前已经用过了uCOS ii,很快就入门了,所谓“书到用时方恨少”,当然自知其中韵味了。

有些网友看过我的“TMS320C6713烧写Flash的通用方法”一文,于是来问我:

“怎么我直接拷贝哪些汇编过去不行呢?”

然后,我回答:

“您能回去看看那汇编是干什么的吗?”

回答说:

“汇编太复杂了,您就说下为什么吧。”

好吧,我实在不知怎么去劝导他,只有深刻体会这些汇编实现的功能及整个启动的流程(代码执行/跳转的过程),才能保证不管硬件怎么变、环境怎么变,都能正确的成功的烧写!

IT界一直存在着这么一种观点:

“这代码什么的都有了,会用就行了,不用重复造轮子!”

这话没错,可惜用错了地方,我只能说:

“轮子是有了,可这轮子好使吗?敢保证跑它十天八天不会挂吗?”

一旦成了标准,你可以不用重复造轮子了,否则,“不断的改进”才是创造的源泉!

DSP/BIOS使用之初窥门径——滴答时钟及烧写Flash

时间: 2024-08-28 20:33:56

DSP/BIOS使用之初窥门径——滴答时钟及烧写Flash的相关文章

STM32学习笔记9(SysTick滴答时钟)

我不得不说意法半导体确实有点风骚!甚至有点变态.我对ST文档 STM32F10XXX参考手册的编辑水平真是不敢恭维.手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑.比如前面我说过的关于NVIC嵌套向量中断控制器的介绍,这部分我认为是非常重要的,但当你看完他这部分介绍,你根本不会设置中断服务程序,他有哪些寄存器都不知道,更别说去设置了,NVIC的详细介绍是在Cotex-M3中有详细的介绍,不多说.今天我们说的是systick定时器. systick定时

6.SysTick系统时钟滴答实验(stm32中断入门)

系统时钟滴答实验很不难,我就在面简单说下,但其中涉及到了STM32最复杂也是以后用途最广的外设-NVIC,如果说RCC是实时性所必须考虑的部分,那么NVIC就是stm32功能性实现的基础,NVIC的难度并不高,但是理解起来还是比较复杂的,我会在本文中从实际应用出发去说明,当然最好去仔细研读宋岩翻译的<Cortex-M3权威指南>第八章,注意这不是一本教你如何编写STM32代码的工具书,而是阐述Cortex-M3内核原理的参考书,十分值得阅读. SysTick系统时钟的核心有两个,外设初始化和S

一步一步教你用Swift开发俄罗斯方块:No.4 滴答作响的时钟机制

为什么标题要叫做"滴答作响的时钟机制"呢? 想必我们大家都玩过俄罗斯方块,那些不同形状的东西,就是哪些不同形状,你懂的,会随着游戏级别的提高而下降的越来越快.是的 ,我们也要模仿那样,做出我们自己的时钟机制. 我们可以看到SKScene里面有一个函数 update(currentTime: CFTimeInterval). 这个函数被没一帧所调用.帧,frame, 是什么? 你可以理解一帧就是一副静态的图片,如果很多图片在很短的时间内连续播放,就成了动画.当你的眼睛开始去预知每一帧图像

STM32系统时钟配置,滴答定时器配置相关

以后实在找不到问题出现在哪里,注意还有这么个地方需要留意: 今天在调试滴答定时器,找半天找不到延时为什么不准确,原来以前的代码中,"SYSCLK_FREQ_72MHz"被写成了64MHz了,把这里重新改为72MHz就可以了,走过的路过的,希望这个提醒可以对大家有所帮助,不过大家还是要看实际情况. 原文地址:https://www.cnblogs.com/data-base-of-ssy/p/9513371.html

STM32 的系统滴答定时器( Systick) 彻底研究解读

作者:王健 前言 SysTick 比起那些 TIM 定时器可以说简单多啦~~~~~哥的心情也好了不少, 嘎嘎!! ARM Cortex-M3 内核的处理器内部包含了一个 SysTick 定时器,它是一个24 位的倒计数定时器,注意,是倒计数! 当计到 0 时它就会从 LOAD 寄存器中自动重装载定时初值.只要不把 CTRL 寄存器中的 ENABLE 为清 0,它就永不停息! 遗憾的是,SysTick 定时器在<STM32 参考手册>里一个屁都没放,只有在<ARM Cortex-M3 技术

《零死角玩转STM32》-18-SysTick系统滴答定时器

参考资料:<STM32F4XX内核参考手册>:4.4.8-SHPRX(System Handler Priority Register)与4.5- System Tick Timer. 1. 简介 SysTick是一个24Bit的系统定时器,属于CM4内核的外设,相关寄存器与部分库函数中core_cm4.h中定义.SysTick一般用于操作系统,用于产生时基,维持OS的心跳. 如下所示:当计数器被使能(STC_CTRL: Bit0-ENABLE)并且计数器到0时,STK_LOAD中的预设值会被

系统定时器(滴答定时器)

  ARM Cortex-M3内核中有一个Systick定时器,它是一个24位(0~(2^24-1))的倒计数定时器,当计数到0时,它就会从Load寄存器中自动重装定时初值,只要不把CTRL寄存器中的ENABLE清0,它就永不停.   时钟源可以是内部时钟FCLK或外部时钟STCLK        配置系统定时器步骤:      ①选择时钟源       ②设定重载数(reload)       ③开启中断       ④启动滴答定时器 在core_cm3.h中有关于系统定时器的配置:    

STM32之系统滴答定时器

一.SysTick(系统滴答定时器)概述 操作系统需要一个滴答定时器周期性产生中断,以产生系统运行的节拍.在中断服务程序里,基于优先级调度的操作系统会根据进程优先级切换任务,基于时间片轮转系统会根据时间片切换任务.总之,滴答定时器是一个操作系统的"心跳". Cortex-M3在内核部分封装了一个滴答定时器--SysTick,在之前的ARM内核通常是不会把定时器做进内核,定时器都是SOC厂商自己制作的外设.显然,Cortex-M3封装了这么一个定时器,对于将操作系统移植到不同SOC厂商生

滴答清单 - Todo & 任务提醒(Record things and remind)

插件介绍: 对于有强迫症和健忘症的小编来说,经常会忘记一些重要的或琐碎而又必须做的事情,相信有很多朋友也有一样的烦恼,如果用笔记本记录的话又相对麻烦一些,于是一些记录相关的软件就运应而生,这就为大家推荐这款任务清单.滴答清单是Todo管理神器TickTick的中文版,能帮您随时随地记录和管理所有事项.您可以用它制定学习.工作计划,生成读书.购物.旅行清单,设置生日.约会.还款提醒等. 使用说明: 将滴答清单 - Todo & 任务提醒(Record things and remind)添加chr