这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» 软件与操作系统» 【白骨精】hanshuyujifen2的进程帖 8.20更新 示例工程中串口初始

共44条 4/5 |‹ 1 2 3 4 5 跳转至
院士
2013-07-15 15:04:12 打赏
31楼

看来军爷这几天被检查逮到了……

军爷先休息几天吧,也等等大家


高工
2013-07-15 18:05:46 打赏
32楼

走了。但是没时间了。这几天上班忙


高工
2013-07-16 00:04:46 打赏
33楼
void NVIC_Config(void)这个函数是不是少了点东西?

高工
2013-07-16 08:54:40 打赏
34楼
usart初始化那里也要加东西的。在usart初始化部分打开usart的中断。USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);

高工
2013-07-16 12:18:19 打赏
35楼

解决链接时候的六个警告:

1、分散加载文件中的四个警告

需要在分散加载文件中,将空的区域使用EMPTY属性标识,说明这个空间是预留的。这样编译器就不会警告了

EMPTY 属性,i就是告诉链接器这是我要保留一个空白内存块,你别管了。修改后的sct文件如下:

LOAD_INTERFLASHROM 0x08000000 0x00100000 { ; load region size_region
EXEC_INTERROM 0x08000000 0x00100000 { ; load address = execution address
* (.vector,+First) ; 1024k
*(InRoot$$Sections)
.ANY (+RO)
}
EXEC_VECTORRAM 0x20000000EMPTY0x00000400 { ; vector table region in ram
} ; 1k
EXEC_BSSDATARAM 0x20000400 0x00001c00 { ; zi and rw data region in ram
.ANY (+RW +ZI)
} ; 7k
EXEC_SYSTEMRAM 0x20002000EMPTY0x00018000 { ; ut/kernel management region

} ; 100k
EXEC_USERRAM 0x2001b000EMPTY0x00001000 { ; user manual region in ram
} ; 4k
EXEC_STACKRAM 0x2001c000EMPTY0x00000000 { ; default stack top

} ; 0k
ARM_LIB_HEAP 0x2001A000 EMPTY 0x500 ; 这是为了使用printf之类的系统库设置的
{
}
ARM_LIB_STACK 0x2001A500 EMPTY 0x500
{
}
} ; sum: 112k
2、解决链接时候的警告

警告1、.\out\kernel-rom.axf: Warning: L6306W: '~PRES8 (The user did not require code to preserve 8-byte data objects)' section knl_dispatch.o(.text) should not use the address of 'REQ8 (Code was permitted to depend on the 8-byte aligment of 8-byte data items)' function knl_power_low.

警告2、.\out\kernel-rom.axf: Warning: L6306W: '~PRES8 (The user did not require code to preserve 8-byte data objects)' section knl_int.o(.text) should not use the address of 'REQ8 (Code was permitted to depend on the 8-byte aligment of 8-byte data items)' function knl_timer_handler.

解决这两个警告,参考http://www.keil.com/support/docs/3268.htm

注意这个即可:All C code generated by the RealView compiler assumes that stack allocation is aligned on 8-byte boundaries. You must ensure that the assembler interrupt handler has an 8-byte aligned stack by specifying thePRESERVE8directive at the beginning of your assembly file.

于是我在发出警告的两个文件里边,.text段之前加了PRESERVE8,警告就消除了

参考上边的一段红字,PRESERVE8这个关键字用来声明字节对齐的。声明之后,链接器就不会警告这里没有对齐了。

于是在knl_int.s和knl_dispatch中的所有.text段前面加上PRESERVE8关键字,警告就消除了。

格式是这样的:

PRESERVE8
AREA |.text|,CODE,READONLY
THUMB
GLOBAL Csym(enaint) [CODE]

。。。。。。。。。。。。。。。。



高工
2013-07-19 21:02:32 打赏
36楼

继续更新,开始玩转开发板的硬件部分


EM-SAM3S开发板例子工程中的启动文件分析

【预备知识】

Cortex-M3内核规定,起始地址必须存放堆顶指针,而第二个地址则必须存放复位中断入口向量地址,这样在Cortex-M3内核复位后,会自动从起始地址的下一个32位空间取出复位中断入口向量,跳转执行复位中断服务程序。对比ARM7/ARM9内核,Cortex-M3内核则是固定了中断向量表的位置而起始地址是可变化的。

【启动分析】

在例子程序中,MCU启动时,会将vector中定义的第二个地址作为程序的入口地址。即Reset_Handler。

至于为什么会从vector加载,可以查看分散加载文件(.sct)。这里有这么一段:

Vector_region 0x400000

{

board_cstartup_keil.o (vectors, +FIRST)

}

这个声明就是让链接器将board_cstartup_keil.o加载到0x400000。

而0x400000就是内部flash的起始地址:

clip_image002

board_cstartup_keil.o由board_cstartup_keil..c生成。这个文件中,定义了两个东西:__vector_table[]和static void _Reset_Handler( void )

__vector_table就是中断向量表,__vector_table的第二个地址就是_Reset_Handler。因此,MCU启动时将向量表加载完成后,就开始执行_Reset_Handler这个函数。

在这个函数中跳转到main函数。好了,花花丽丽的C开始了。

(至于为什么加载到了0x400000是__vector_table而不是_Reset_Handler,那是因为那个+FIRST这个属性)

【总结一下】

1、在分散加载文件中,设置程序加载到的位置。加载到0x400000这个地址的,就会在启动时候执行。

2、这里的启动文件有很简单的两个东西,中断向量表和函数_Reset_Handler。中断向量表的第二个地址就是复位中断程序入口地址。

3、汇编文件workaround.s没用了。删掉里边的内容都没关系。于是一行汇编代码都没有了,这也算是自己写sct文件的好处吧。


高工
2013-07-20 09:52:42 打赏
37楼

一种设置寄存器的宏定义方法

#define EEFC_FMR_FWS_Pos 8

#define EEFC_FMR_FWS_Msk (0xfu << EEFC_FMR_FWS_Pos) /**< \brief (EEFC_FMR) Flash Wait State */

#define EEFC_FMR_FWS(value) ((EEFC_FMR_FWS_Msk & ((value) << EEFC_FMR_FWS_Pos)))

在程序中使用时候:

EFC->EEFC_FMR = EEFC_FMR_FWS(3);

=((EEFC_FMR_FWS_Msk & ((3) << EEFC_FMR_FWS_Pos)))

=(0xfu << EEFC_FMR_FWS_Pos) & ((3) << EEFC_FMR_FWS_Pos)))

=(0xfu << 8) & ((3) << 8))

再看看寄存器:

EFC->EEFC_FMR = EEFC_FMR_FWS(3);

这句代码刚好就设置了FWS寄存器,省去了很多手动计算还提高了代码的可读性。


设置时钟的步骤(一点垃圾翻译)

设置时钟步骤

1、打开主振荡器

设置寄存器CKGR_MOR中的MOSCXTEN域可使能主时钟。用户可以通过写CKGR_MOR中的MOSCXTST域来定义一个主时钟的启动时间。一旦这个寄存器被正确配置,用户必须等待寄存器PMC_SR中的MOSCXTS位被置位。这个过程可以通过查询状态寄存器完成,如果PMC_IER中相应的中断打开也可以通过中断来检测。

2、检查主振荡器频率

在某些情况下,用户可能需要精确地测量主时钟的频率。这个测量可以通过CKGR_MCFR寄存器来完成。

一旦寄出器CKGR_MCFR中的MAINFRDY域被设置,用户就可以读寄存器CKGR_MCFR中的MAINF域了。这个读出的数字是主时钟在慢时钟十六个周期内所运行的周期。

3、设置PLL和分频器

所有的PLL金额分频器参数都是通过寄存器CKGR_PLLxR来配置完成的。

DIV域是用来控制分频器的,当PLL被使用时,它必须被设置成1。默认情况下,DIV域被设置为0,这就意味值分频器被关闭了。(没有频率输出)

MUL域是PLL的倍频系数。这个参数可以被设置为从02047之间的值。如果MUL被设置为0PLL将会被关闭,其他情况下PLL的输出频率=PLL的输入频率×(MUL+1

PLLCOUNT域指定了在CKGR_PLLR被置位之后,PMC_SR寄存器中的LOCK位被置位之前,要经历的慢时钟周期数。

PMC_PLL寄存器被写入时,用户必须等待PMC_SR中的LOCK位被置位。这个过程可以通过查询或者中断来完成。

寄存器CKGR_PLLR中的所有参数可以通过一次写操作完成。在一些情况下,一下这些位会被拉低,以指明PLL没有准备好:MULDIV被修改、lock位。

PLL锁定时,LOCK位被重新置位。用户在使用PLL之前必须等待LOCK置位。

4、选择主时钟和处理器时钟

主时钟和处理器时钟可以通过寄存器PMC_MCKR来配置。

CSS域用来选择主时钟的驱动源。默认情况下主时钟会被选择。

PRES域用来控制主时钟的分频。用户可在一下几个值中选择分频系数:(1, 2, 3, 4, 8, 16, 32, 64)

5、可编程时钟的选择

可编程时钟通过寄存器PMC_SCER, PMC_SCDRPMC_SCSR控制。

6、使能外设时钟

当所有以上步骤都完成时,可通过寄存器PMC_PCER0, PMC_PCER1, PMC_PCDR0 and PMC_PCDR1来使能或者失能外设时钟。



院士
2013-07-30 10:15:22 打赏
38楼

总线时钟。

当年 从AVR转到ARM上,这个总线时钟理解了好长一段时间


高工
2013-07-30 20:15:59 打赏
39楼

趁着他们看晚会的空,我更新个点灯程序:

本来贴这里的,后来觉得还是单独发一贴好了

http://forum.eepw.com.cn/thread/235157/1



高工
2013-07-30 20:20:36 打赏
40楼

比较麻烦的一个东西。我玩了几天51就转过来的,那里没的总线时钟。

ARM7里边也有,但是没这么复杂。

计算CM3的时钟并记住,还是有点难度的



共44条 4/5 |‹ 1 2 3 4 5 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]