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);
}
搭建主要的BIOSproject基于上篇文章DSP-BIOS使用入门,func_task0、func_task1和swi_adc都是上篇文章中的在DSP/BIOS中使用任务和软中断的例程,这里事实上没什么用。暂且无论。
要在硬件上跑。一定要在Global Setting中设置好,
另外硬件上——我的板子上GPIO_PIN3连接着LED,低电平点亮!
cmd文件都是DSP/BIOS配置文件自己主动配置好了,不用管了临时。
挂上仿真器,下载到板子的RAM上运行!OK,成功。
DSP/BIOS操作系统启动过程
事实上在上一篇中已经讲过DSP/BIOS的启动过程。这里最好还是再唠叨一下:
- 系统上电复位,从Flash装载完程序后。首先从C/C++环境入口_c_int00開始运行
- 利用.cinit记录初始化.bss段
- 调用BIOS_init初始化用到的各个模块
- 处理.pinit表。如C++中的全局对象的构造函数就在这个时候运行
- 进入main函数运行
- main函数返回,调用BIOS_start启动DSP/BIOS操作系统
事实上除了当中第1步对我们烧写Flash有指导意义外,其他各步骤都是无关紧要的(当然,仅就这里讨论的问题而言)。
基于此。这里烧写Flash的思路就是:在系统复位后。程序跳转到_c_init00之前,写一段从Flash拷贝应用程序到内存的代码就好了。
迁移到操作系统的Flash烧写
在之前“TMS320C6713烧写Flash的通用方法”一文中。已经详述了怎样烧写裸机的代码,这里仅仅须要对DSP/BIOSproject做非常少的改动,就可无缝的将之前的烧写方法用在这里,以下还是按步骤来,主要描写叙述一些不同的地方(这样清晰些):
加入二级Bootloader用到的文件(3个)到project中,例如以下图,
确定下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接口的寄存器配置!
划分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中不easy出问题(尽管说多占用一些RAM吧)。
写cmd文件(user.cmd,如上图)
DSP/BIOS已经自己主动生成了一个CMD文件,最好不要去改动,仅仅须要将DSP/BIOS自己主动生成的从project中移除(不是删了。而是Remove)。自己新建一个。将DSP/BIOS的包括进来即可了,
-lbios_firstcfg.cmd
-lcsl6713.lib SECTIONS
{
/* RAM */
.boot_load: {} > BOOT_RAM /* User defined */
}
-lbios_firstcfg.cmd将自己主动生成的包括进来,关键是添加了.boot_load段,该段专门用于放置二级Bootloader。将user.cmd包括到project中。
改动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段。
好了,没什么事了。你能够编译,接着按“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张载程序后在内存运行的东西先都读出来。在通过还有一个project烧写不就能够了吗?我最后就是这么做的,在这过程中还一直庆幸自己对cmd文件、内存等还算了解。甚至在将从内存中导出的东西改动成头文件还用到了VIM(神一样的编辑器)。
学习DSP/BIOS。我庆幸之前已经用过了uCOS ii。非常快就入门了。所谓“书到用时方恨少”,当然自知当中韵味了。
有些网友看过我的“TMS320C6713烧写Flash的通用方法”一文,于是来问我:
“怎么我直接拷贝哪些汇编过去不行呢?”
然后,我回答:
“您能回去看看那汇编是干什么的吗?”
回答说:
“汇编太复杂了,您就说下为什么吧。
”
好吧,我实在不知怎么去劝导他,仅仅有深刻体会这些汇编实现的功能及整个启动的流程(代码运行/跳转的过程),才干保证无论硬件怎么变、环境怎么变,都能正确的成功的烧写!
IT界一直存在着这么一种观点:
“这代码什么的都有了,会用即可了。不用反复造轮子!
”
这话没错,可惜用错了地方,我仅仅能说:
“轮子是有了,可这轮子好使吗?敢保证跑它十天八天不会挂吗?”
一旦成了标准。你能够不用反复造轮子了,否则,“不断的改进”才是创造的源泉。
DSP/BIOS使用之初窥门径——滴答时钟及烧写Flash的更多相关文章
- 晶振虚焊导致TI 28335 DSP 烧写FLASH后,连接仿真器时正常工作,拔掉仿真器却不能启动运行
遇到个诡异的问题,28335的DSP,之前程序调试一切正常,但是烧写FLASH后,拔掉仿真器却始终部工作. 解决思路: 1) 检查配置文件貌似没什么问题,复制到其他工程,在开发板上拔掉仿真器启动正常. ...
- liunx驱动----系统滴答时钟的使用
2019-3-12系统滴答定时器中断使用 定义一个timer 其实就是使用系统的滴答定时器产生一个中断. 初始化timer init_timer函数 实现如下 void fastcall ini ...
- STM32 系统滴答计时器
;//us与系统滴答的被乘数 ;//ms与系统滴答的被乘数 ;//系统运行秒数 /** * @description:系统滴答计时系统初始化 * @param 无 * @retval 无 */ voi ...
- STM32学习笔记(六) SysTick系统时钟滴答实验(stm32中断入门)
系统时钟滴答实验很不难,我就在面简单说下,但其中涉及到了STM32最复杂也是以后用途最广的外设-NVIC,如果说RCC是实时性所必须考虑的部分,那么NVIC就是stm32功能性实现的基础,NVIC的难 ...
- uCOS的软件定时器、uCOS时钟节拍和滴答定时器的关系
uCOS2.81后的版本中有软件定时器的概念,如果要开启定时器任务,需要在OS_CFG.H文件中 #define OS_TMR_EN 1 软件定时器其实跟硬件中断是相 ...
- Cortex-M0系统滴答定时器Systick详解
上图是LPC1114系统滴答定时器(SysTick)的结构图.系统滴答定时器位于Cortex-M0内核中,也就是说,不论是LPC1114,还是其他的Cortex-M0内核单片机,都有这个系统定时器.其 ...
- STM32 - SYSTICK(系统滴答定时器)
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15).在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基.例如,为多个任务许以不同数目 ...
- 系统滴答定时器(SysTick)中断配置
系统滴答定时器(SysTick)中断配置 在STM32标准库中是通过SysTick_Config()函数配置时钟中断的,然后SysTick_Handler()函数自动定时触发其中的函数. if(Sys ...
- DSP/BIOS程序启动顺序
基于TI的DSP芯片的应用程序分为两种:一般应用程序:DSP/BIOS应用程序. 为简化编程,TI提供了一套C的编程接口,它以API和宏的形式封装了TI的所有硬件模块,这套接口统称DSP/BIOS.D ...
随机推荐
- NOIP2016模拟赛三 Problem B: 神奇的树
题面 Description 有一棵神奇的树.这棵树有N个节点,在每个节点上都有宝藏,每个宝藏价值V[i]金币:对于每条边,每经过一次都要花费C[i]金币. 值得注意的是,每个宝藏只能领取一次(也可以 ...
- mysql事物隔离级别
mysql实现了四种隔离级别 Read Uncommitted(未提交读) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少.读取 ...
- Vuex 通俗版教程
作者 Yeaseon 已关注 2017.03.16 16:44* 字数 1245 阅读 243评论 2喜欢 4 本文基本上是官方教程的盗版,用通俗易懂的文字讲解Vuex,也对原文内容有删减. 如果你对 ...
- 用NSLogger代替NSLog输出调试信息
安装 NSLogger分为两部分,LoggerClient和NSLogger Viewer,你的App需要导入前者,后者是一个独立的mac应用,NSLogger所有的调试信息将输出到这个应用中. 安装 ...
- GestureDetector 完全解析
个人原创 OnDown(MotionEvent e):用户触发DonenEvent就会执行onShowPress(MotionEvent e):用户触发DonenEvent后,在很短大概0.5秒内,没 ...
- Mogodb集群搭建
1.上传解压软件包 cd /home/dinpay/ 解压:tar -zxvf mongodb-linux-x86_64-rhel62-3.2.2.tgz 重命名: mv mongodb-lin ...
- mysql 远程登陆不上
当使用 TCP/IP 连接 mysql 时, 出现 : Can't connect to MySQL server on 'xxx.xxx.xxx.xxx.'(111) 这个错误. 经过重复折腾: 确 ...
- apue学习笔记(第十二章 线程控制)
本章将讲解控制线程行为方面的详细内容,而前面的章节中使用的都是它们的默认行为 线程属性 pthread接口允许我们通过设置每个对象关联的不同属性来细调线程和同步对象的行为.管理这些属性的函数都遵循相同 ...
- apue学习笔记(第五章 标准I/O)
本章讲述标准I/O库 流和FILE对象 对于标准I/O库,它们的操作是围绕流进行的.流的定向决定了所读.写的字符是单字节还是多字节的. #include <stdio.h> #includ ...
- kettle转换之多线程
kettle转换之多线程 ETL项目中性能方面的考虑一般是最重要的.特别是所讨论的任务频繁运行,或一些列的任务必须在固定的时间内运行.本文重点介绍利用kettle转换的多线程特性.以优化其性能. ...