没有合适的资源?快使用搜索试试~ 我知道了~
首页山外K60/KL26开发指南:快速入门与高效API
山外K60/KL26开发指南:快速入门与高效API
需积分: 4 0 下载量 130 浏览量
更新于2024-07-06
收藏 10.16MB PDF 举报
本文档是针对初学者和快速入门飞思卡尔K60/KL26单片机的教程,由山外メ雲ジ撰写,广州松飞电子科技有限公司于2014年发布。K60/KL26是飞思卡尔Kinetis系列中的一个子系列,该系列包含多个型号,如K60DN、K60FX和K64FX,单片机的功能和复杂性日益增加。 山外科技针对这些常用型号,开发了一套K60、KL26底层驱动库,旨在简化开发过程,让用户无需深入了解寄存器配置,只需通过调用API接口就能进行应用程序开发。库中如UART、FTM、I2C等模块,已经进行了优化,用户在改变系统时钟频率时,库会自动计算和选择合适的分频系数,减轻了开发者的工作负担。然而,值得注意的是,如果在main函数中修改时钟频率,可能需要重新初始化相关模块。 对于认为使用库就像填空一样,不利于深入学习的观点,文档指出,对于初学者来说,特别是那些没有系统学习过单片机底层的,应该把重点放在理解底层工作原理和借鉴优秀库的设计思想上。推荐的进一步学习资源是《轻松玩转ARMCortex-M4微控制器-基于KinetisK60》这本书,它特别适合初学者,注重讲解C语言、时序图和Datasheet的基础知识,帮助他们弥补基础知识的不足,从而加快学习进程。 本文档不仅提供了K60/KL26的开发工具,还强调了如何通过合理利用库和适当的学习策略,让初学者更快地掌握这款单片机,从而进入深入的嵌入式系统开发领域。
资源详情
资源推荐
攻城略地之一天攻破 K60/KL26 —— 松飞科技
山外论坛 h t t p : / / v c a n 1 2 3 . c o m 山 外 メ 雲 ジ
~ 15 ~
山外
参考原文出处:http://blog.chinaunix.net/uid-15473693-id-388637.html
那编译到时候,编译器是如何为这些变量数据分配地址的呢?
其实,这就是链接器 Linker 在发挥它的作用,它会根据配置文件,来为这些变量
数据分配合适的地址,这样我们就可以不需要考虑这些内存分布就能写出可运行的代
码。
编译器对代码进行编译,一般分为四个步骤:
通常情况下,链接器 Linker 的配置文件都是由官方提供,一般情况下,我们不需
要更改这些。但出于学习的目的,我们非常有必要去研究一下这些配置文件(例如需
要用到 IAP 或 ISP 时就得需要自行修改)。
在 Prj\IAR\config files 文件夹下,你可以看到有很多的 linker 配置文件:
这里的文件是用来分配数据在内存中的位置,配置 ROM、RAM 启动,linker 根据
这些文件来为 Kinetics 分配 4G 的虚拟寻址空间地址。如果把代码部分编译进去 RAM,
那就是 RAM 启动;如果把代码数据编译进去 ROM,那就是 ROM 启动(flash 启动)。
•替换和
展开宏
•删掉注
释
预编译
编译成汇
编语言
编译和
优化
汇编成机
器码
汇编
生成可执
行文件
链接
攻城略地之一天攻破 K60/KL26 —— 松飞科技
山外论坛 h t t p : / / v c a n 1 2 3 . c o m 山 外 メ 雲 ジ
~ 17 ~
山外
如果要 RAM 启动,我们要把代码编译进 SRAM_L ,定义中断向量表的位置。
可以打开 vcan_RAM_K60N512.icf 这个文件(用记事本打开就行),这个配置文
件是参考 128KB_Ram.icf 来重新修改和添加了注释。
山外已经对配置文件进行修改,在里面添加了很多注释:
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x1fff0000;
//RAM 启动要设置为 RAM 起始地址,ROM 启动也要设为 ROM 的起始地址
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x0; //ROM 地址
define symbol __ICFEDIT_region_ROM_end__ = 0x00040000;
define symbol __ICFEDIT_region_RAM_start__ = 0x1fff0000; //RAM 地址
define symbol __ICFEDIT_region_RAM_end__ = 0x20000000;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x1000; //堆大小
define symbol __ICFEDIT_size_heap__ = 0x800; //栈大小
/**** End of ICF editor section. ###ICF###*/
/**** 上边是由 ICF 编辑,下面是由我们手动配置 ****/
define symbol __region_RAM2_start__ = 0x20000000;//SRAM 是分成两块的,RAM2 即 SRAM_U ,RAM 为 SRAM_L
define symbol __region_RAM2_end__ = 0x20000000 + __ICFEDIT_region_RAM_end__
- __ICFEDIT_region_RAM_start__;
define exported symbol __VECTOR_TABLE = __ICFEDIT_intvec_start__;
//代码编译进 ROM ,则 0x00000000 ;RAM,则 __ICFEDIT_region_RAM_start__
define exported symbol __VECTOR_RAM = __ICFEDIT_region_RAM_start__ ;
//前面的 RAM 留给 RAM User Vector Table
//如果是 ROM 启动,则 common_startup 函数会把 __VECTOR_TABLE 的数据复制到 __VECTOR_RAM
define exported symbol __BOOT_STACK_ADDRESS = __region_RAM2_end__ - 8;
//0x2000FFF8;启动栈地址,中断向量表的第一个元素就是指向这里
/* 决定代码编译的地址 */
define exported symbol __code_start__ = __ICFEDIT_intvec_start__ + 0x410;
//代码编译进 ROM ,则 __ICFEDIT_region_ROM_start__ + 0x410 ,
//RAM,则 __ICFEDIT_region_RAM_start__ + 0x410 ,+0x410 ,是前面的留给 Vector Table
define memory mem with size = 4G; //4G 的虚拟寻址空间
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__
to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__
to __ICFEDIT_region_RAM_end__]
| mem:[from __region_RAM2_start__ to __region_RAM2_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; //堆,8 字节对齐
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; //栈,8 字节对齐
//手动初始化,在 common_startup 函数 里完成
中断向量表地址。Flash 和 SRAM 启
动的中断向量表地址是不一样的
这里就是代码的编译地址。加上
0x410,是前面的留给中断向量表
Kinetis 的 SRAM 是分成两块的。
这里是设置第二块的地址范围
中断向量表地址
可以看出栈的生长方向为向下
设置 ROM 和 RAM 的可用
内存地址范围
设置堆栈的大小
攻城略地之一天攻破 K60/KL26 —— 松飞科技
山外论坛 h t t p : / / v c a n 1 2 3 . c o m 山 外 メ 雲 ジ
~ 18 ~
山外
initialize manually { readwrite }; // 未初始化数据 .bss
initialize manually { section .data}; // 已初始化数据
initialize manually { section .textrw }; // __ramfunc 声明的子函数
do not initialize { section .noinit }; // 复位中断向量服务函数
define block CodeRelocate { section .textrw_init };
define block CodeRelocateRam { section .textrw };
//CodeRelocateRam 把代码复制到 RAM 中(对 flash 操作的函数必须这样)
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
//vectors.c 中设置 #pragma location = ".intvec" ,告诉编译器,这个是中断向量表,编译进去 .intvec
place at address mem:__code_start__ { readonly section .noinit };
//在 crt0.s 中设置了复位中断函数为 SECTION .noinit : CODE ,即把代码编译进去 .noinit
place in RAM_region { readonly, block CodeRelocate };
//把代码编译进去 RAM (调试用,掉电丢失) ,非调试,则设为 ROM_region
place in RAM_region { readwrite, block CodeRelocateRam,
block CSTACK, block HEAP };
Linker 根据 icf 配置文件来进行分配内存地址:
如果是 ROM 启动(flash 启动):
1. /*###ICF### Section handled by ICF editor, don't touch! ****/
2. /*-Editor annotation file-*/
3. /* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
4. /*-Specials-*/
5. define symbol __ICFEDIT_intvec_start__ = 0x00000000;
中断向量表地址。Flash 和 SRAM 启
动的中断向量表地址是不一样的
RAM 启动,会把只读数据、代码都编
译进去
RAM
设置中断向量表位置放在
__ICFEDIT_intvec_start__ 地
址上
设置 .noinit 段放在代码开头,
即复位中断服务函数,把复位
函数编译在代码开头
Flash
512KB
……
SRAM
128k
0x0000-0000
0x0007-FFFF
0x1FFF-0000
0x2001-0000
中断向量表
代码区
数据区
堆
栈
命令行参数
ROM Bootloader 中断向量表
Flash 配置寄存器
0x0000-0000
0x0000-0400
0x0000-0410
0x1FFF-0000
0x2000-FFF8
0x2001-0000
RAM Bootloader 中断向量表
RAM 配置寄存器
Code
……
堆
栈
配置
编译器根据
icf
文件来把中断向量表分
配到 Ram 区域,在线调试时由调试器
加载 SP 和 PC 的值。
取消自动初始化,改为由
common_startup
函数来初始化
攻城略地之一天攻破 K60/KL26 —— 松飞科技
山外论坛 h t t p : / / v c a n 1 2 3 . c o m 山 外 メ 雲 ジ
~ 19 ~
山外
6. /*-Memory Regions-*/
7. define symbol __ICFEDIT_region_ROM_start__ = 0x0;
8. define symbol __ICFEDIT_region_ROM_end__ = 0x00040000;
9. //0x00040000:P-flashk 256k D-flash 256k 0x00080000:P-flashk 512k
10. define symbol __ICFEDIT_region_RAM_start__ = 0x1fff0000;
11. //前面的 0x410 RAM 留给 RAM User Vector Table 。
12. define symbol __ICFEDIT_region_RAM_end__ = 0x20000000;
13. /*-Sizes-*/
14. define symbol __ICFEDIT_size_cstack__ = 0x2000;
15. define symbol __ICFEDIT_size_heap__ = 0x2000;
16. /**** End of ICF editor section. ###ICF###*/
17.
18.
19. /**** 上边是由 ICF 编辑,下面是由我们手动配置 ****/
20.
21. define symbol __region_RAM2_start__ = 0x20000000;
22. //SRAM 是分成两块的,RAM2 即 SRAM_U,RAM 为 SRAM_L
23. define symbol __region_RAM2_end__ = 0x20000000 + __ICFEDIT_region_RAM_end__
24. - __ICFEDIT_region_RAM_start__;
25.
26.
27. define exported symbol __VECTOR_TABLE = __ICFEDIT_intvec_start__;
28. //代码编译进 ROM ,则 0x00000000 ;RAM,则 __ICFEDIT_region_RAM_start__
29. define exported symbol __VECTOR_RAM = __ICFEDIT_region_RAM_start__;
30. //前面的 RAM 留给 RAM User Vector Table,即这里的设置。所以减 0x410
31. //common_startup 函数就是把 __VECTOR_TABLE 的数据复制到 __VECTOR_RAM
32.
33. define exported symbol __BOOT_STACK_ADDRESS = __region_RAM2_end__ - 8;
34. //0x2000FFF8; 启动栈地址
35.
36. /* 决定代码编译的地址 */
37. define exported symbol __code_start__ = __ICFEDIT_intvec_start__ + 0x410;
38. //+0x410 ,是前面的留给 Vector Table
39.
40. define memory mem with size = 4G; //4G 的虚拟寻址空间
41.
42. define region ROM_region =
43. mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
44.
45. define region RAM_region =
46. mem:[from __ICFEDIT_region_RAM_start__ + 0x410 to __ICFEDIT_region_RAM_end__]
47. | mem:[from __region_RAM2_start__ to __region_RAM2_end__];
48.
49.
50. define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; //堆
51. define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; //栈
52.
53. //手动初始化,在 common_startup 函数 里完成
54. initialize manually { readwrite }; // 未初始化数据 .bss
55. initialize manually { section .data}; // 已初始化数据
56. initialize manually { section .textrw }; // __ramfunc 声明的子函数
57.
58. do not initialize { section .noinit }; // 复位中断向量服务函数
59.
60. define block CodeRelocate { section .textrw_init };
61. define block CodeRelocateRam { section .textrw };
62. // 把 CodeRelocate 代码复制到 RAM 中的 CodeRelocateRam (对 flash 操作的函数必须这样)
63.
64. place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
65. //vectors.c 中设置#pragma location = ".intvec",告诉编译器,这个是中断向量表,编译进去 .intvec
66.
67. place at address mem:__code_start__ { readonly section .noinit };
68. //在 crt0.s 中设置了 Reset_Handler 为 SECTION .noinit : CODE
69. //即把 Reset_Handler 编译进__code_start__
70.
71. place in ROM_region { readonly, block CodeRelocate };
72. //把代码编译进去 ROM (调试用) ,非调试,则设为 ROM_region
73.
74. place in RAM_region { readwrite, block CodeRelocateRam,
设置 P-flash 和 D-flash 的
分区大小
设置堆栈大小
ROM 启动,就要把只读数据和
代码编译进 ROM
堆栈大小
剩余230页未读,继续阅读
mucherry
- 粉丝: 424
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 十种常见电感线圈电感量计算公式详解
- 军用车辆:CAN总线的集成与优势
- CAN总线在汽车智能换档系统中的作用与实现
- CAN总线数据超载问题及解决策略
- 汽车车身系统CAN总线设计与应用
- SAP企业需求深度剖析:财务会计与供应链的关键流程与改进策略
- CAN总线在发动机电控系统中的通信设计实践
- Spring与iBATIS整合:快速开发与比较分析
- CAN总线驱动的整车管理系统硬件设计详解
- CAN总线通讯智能节点设计与实现
- DSP实现电动汽车CAN总线通讯技术
- CAN协议网关设计:自动位速率检测与互连
- Xcode免证书调试iPad程序开发指南
- 分布式数据库查询优化算法探讨
- Win7安装VC++6.0完全指南:解决兼容性与Office冲突
- MFC实现学生信息管理系统:登录与数据库操作
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功