1.列表解析。
我们好,我是豹哥,猎豹的豹,犀利哥的哥。前几日豹哥给我们讲的是嵌入式开发里的source文件。
(1)这是一个,让人听起来万分喜洋洋的术语,代表着您可以因而一个巡回将拥有值放到一个列表中。python列表解析属于python的迭代中的一种,相比较python
for循环速度会快很多。下面看下python列表解析是怎么工作的:
众所周知,嵌入式开发属于偏底层的付出,首要编程语言是C和汇编。所以本文要讲的source文件根本指的就是c文件和汇编文件。
虽然在平凡开发中,我们都只会关切自己成立的.c/.h/.s源文件,但其实咱们不知不觉中也跟很多不是大家创设的源文件在社交,那么问题来了,一个完整的嵌入式工程(以基于ARM
Cortex-M控制器的工程为例)到底会含有哪些source文件呢?
现在就到了豹哥的show
time了,豹哥将这个文件按来源分为五类十种,下边豹哥按系列逐一分析这一个文件:
第一类:Provided by Committee
第一类公事由C标准委员会提供,该类文件伴随着专业的昭示而逐渐扩展。该类文件重大就是一种,即C标准库。
1. C standard Library
我们都清楚C语言是有正统的,常见的C标准有ANSI
C(C89)、C99、C11,而C标准函数库(C Standard
library)就是所有符合C标准的头文件的聚集,以及常用的函数库实现程序。C标准库由Committee制订发布,平日会被含有在IDE里。列举部分宽广文件和函数如下,是不是认为似曾相识?
/* 常用文件 */ assert.h,stdio.h,stddef.h,stdint.h,string.h ...
/* 常用定义 */ bool,NULL,uint8_t,uint16_t,uint32_t...
/* 常用函数 */ assert(),printf(),memset(),memcpy()...
a = [x+2 for x in range(10)]
print (a)
----------------------------
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
第二类:Provided by IDE(Compiler)
第二类公事由IDE提供,C语言是编译型语言,需要编译器将C程序汇编成机器码,所有便有了有的跟编译器特性相关的函数库。
2. Compiler Library
我们在支付嵌入式应用时需要倚重集成开发环境(IDE),常见的IDE有GCC(GNUC),Keil
MDK(ARMCC),IAR
EWARM(ICCARM),这一个IDE都有配套的C编译器,这一个编译器是各有特色的,为了充足显示各编译器特色,配套的函数库便应运而生。
编译器函数库是因IDE而异的,此处仅讲一个事例以供参考,需要通晓更多需查看各IDE手册。
以IAR
EWARM里的DLib_Product_string.h文件为例,该公文中重定义了memcpy的兑现:
#define _DLIB_STRING_SKIP_INLINE_MEMCPY
#pragma inline=forced_no_body
__EFF_NENR1NW2R1 __ATTRIBUTES void * memcpy(void * _D, const void * _S, size_t _N)
{
__aeabi_memcpy(_D, _S, _N);
return _D;
}
第三类:Provided by ARM
第三类公事由ARM提供,嵌入式程序的实施靠的是控制器内核(此处指的内核便是ARM内核),ARM公司在计划基本时,提供了部分内核模块的接口,开发者可以经过那些接口访问基本资源,CMSIS
header里就是这一个内核模块资源的接口。
3. CMSIS header
完整的CMSIS
header目录应该是下边那些样子,而必须要爱抚的只有\CMSIS\Include下面的core_cmx.h文件
\CMSIS
\Core
\DAP /* ARM debugger实现 */
\Driver /* ARM统一的常用外设driver API */
\DSP_Lib /* ARM优化实现的DSP Lib */
\Include /* ARM内核资源接口 */
\arm_xx.h
\cmsis_xx.h
\core_cmx.h
\Lib /* ARM优化实现的标准Lib */
\Pack
\RTOS /* ARM推出的RTOS- RTX */
\RTOS2
\SVD
\Utilities
core_cmx.h文件里定义了根本资源接口,里面最常用的三大模块是SCB,SysTick,NVIC,一个嵌入式开发的老资格看到这多少个模块应该要向豹哥挥手示意,来,让豹哥看见你们的双手~~~
注:python会在解释器里对range(10)举行迭代,依次把列表里的情节取出来,赋值给最左边的x,然后实施x+2的操作,并且把执行好的结果保存在列表里。等range(10)迭代完之后就新生成了一个列表,结果就是[2, 3, 4,
5, 6, 7, 8, 9, 10, 11],从上边能够观察,那也是树立python 列表的一个措施。
第四类:Provided by Chip Producer
第四类公事是由ARM芯片生产商提供,大家在选型一个ARM芯片时,除了看ARM内核类型外,还得看芯片里面外设资源,是这多少个外设导致了ARM芯片差别,于是便有了各大ARM厂商争奇斗艳,比如NXP(Freescale),
ST,
Microchip(Atmel),ARM厂商赋予了ARM芯片各个外设资源,同时也会提供这多少个外设资源的接口。
该品种下文件有四种:
4.
device.h:芯片头文件,紧要含有中断号定义(xx_IRQn)、外设模块类型定义(xx_Type)
、外设基地址定义(xx_BASE)。
/////////////////////////////////////////////////////
// 中断号定义
typedef enum IRQn {
NotAvail_IRQn = -128,
/* Core interrupts */
NonMaskableInt_IRQn = -14,
HardFault_IRQn = -13,
...
SysTick_IRQn = -1,
/* Device specific interrupts */
WDT0_IRQn = 0,
...
} IRQn_Type;
////////////////////////////////////////////////////
// 外设寄存器定义
typedef struct {
__IO uint32_t MOD;
...
__IO uint32_t WINDOW;
} WWDT_Type;
#define WWDT_WINDOW_WINDOW_MASK (0xFFFFFFU)
#define WWDT_WINDOW_WINDOW_SHIFT (0U)
#define WWDT_WINDOW_WINDOW(x) (((uint32_t)(((uint32_t)(x)) << WWDT_WINDOW_WINDOW_SHIFT)) & WWDT_WINDOW_WINDOW_MASK)
////////////////////////////////////////////////////
// 外设基地址定义
#define WWDT0_BASE (0x5000E000u)
5.
startup_device.s:芯片中断向量表文件,首要含有中断向量表定义(DCD
xx_Handler) ,以及各中断服务程序的弱定义(PUBWEAK)。
Note:该文件因编译器而异。
;;基于IAR的startup_device.s文件
MODULE ?cstartup
;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
PUBLIC __vector_table
PUBLIC __Vectors_End
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 中断向量表定义
DATA
__vector_table
DCD sfe(CSTACK)
DCD Reset_Handler
DCD NMI_Handler
DCD HardFault_Handler
...
DCD SysTick_Handler
; External Interrupts
DCD WDT0_IRQHandler
...
__Vectors_End
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 中断服务程序弱定义
THUMB
PUBWEAK WDT0_IRQHandler
PUBWEAK WDT0_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
WDT0_IRQHandler
LDR R0, =WDT0_DriverIRQHandler
BX R0
WDT0_DriverIRQHandler
B .
END
6.
system_device.c/h:芯片系统起初化文件,首要涵盖全局变量SystemCoreClock定义(提供芯片内核默认工作频率)、SystemInit()函数定义(完成最主题的系统初叶化,比如WDOG开始化,RAM使能等,这有些因芯片设计而异)。
7. device SDK Library:官方提供的芯片外设SDK
driver包文件,有了这一个SDK包可以一向使用片内外设设计协调的施用,而不需要查阅芯片手册里的外设模块寄存器去重写外设驱动。当然并不是每个厂商都有全面的SDK包,那有赖于各厂商对软件服务的保护程度。
// 来自于NXP SDK的WWDT driver API
void WWDT_GetDefaultConfig(wwdt_config_t *config);
void WWDT_Init(WWDT_Type *base, const wwdt_config_t *config);
void WWDT_Deinit(WWDT_Type *base);
void WWDT_ClearStatusFlags(WWDT_Type *base, uint32_t mask);
void WWDT_Refresh(WWDT_Type *base);
(2)假使将上述列表用for循环来实现怎么落实这?
第五类:Created by Developer
第五类公事是开发者自己创造,用于落实开发者自己的嵌入式应用,分为应用系统启动文件,应用类别最先化文件,应用文本。其中使用系统启动和发轫化文件属于main函数在此以前的公文,一般可以通用,大部分开发者并不关注其具体内容,不过了然其过程可以变本加厉对嵌入式系统结构的了然。
8. reset.s:
应用连串复位启动文件,领悟ARM原理的都了解,image前8个字节数据分别是芯片上电的开端SP,
PC,其中PC指向的便是本文件里的Reset_Handler,这是芯片执行的第一个函数入口,该函数根本用于完成应用系统起始化工作,包含应用中断向量表重定向、调用芯片系统初步化、ARM系统寄存器rx清零、起初化应用程序各数据段、初叶化ARM系统暂停、跳转main函数。
// 一段经典的startup code
SECTION .noinit : CODE
THUMB
import SystemInit
import init_data_bss
import main
import CSTACK$$Limit
import init_interrupts
EXTERN __vector_table
REQUIRE __vector_table
#define SCB_BASE (0xE000ED00)
#define SCB_VTOR_OFFSET (0x00000008)
PUBLIC Reset_Handler
EXPORT Reset_Handler
Reset_Handler
// Mask interrupts
cpsid i
// Set VTOR register in SCB first thing we do.
ldr r0,=__vector_table
ldr r1,=SCB_BASE
str r0,[r1, #SCB_VTOR_OFFSET]
// Init the rest of the registers
ldr r2,=0
ldr r3,=0
ldr r4,=0
ldr r5,=0
ldr r6,=0
ldr r7,=0
mov r8,r7
mov r9,r7
mov r10,r7
mov r11,r7
mov r12,r7
// Initialize the stack pointer
ldr r0,=CSTACK$$Limit
mov r13,r0
// Call the CMSIS system init routine
ldr r0,=SystemInit
blx r0
// Init .data and .bss sections
ldr r0,=init_data_bss
blx r0
// Init interrupts
ldr r0,=init_interrupts
blx r0
// Unmask interrupts
cpsie i
// Set argc and argv to NULL before calling main().
ldr r0,=0
ldr r1,=0
ldr r2,=main
blx r2
__done
B __done
END
9.
startup.c:应用连串伊始化文件,该文件里根本包含五个起首化函数,init_data_bss()、
init_interrupts(),data,
bss段数据的起首化是为了保证嵌入式系统中兼有全局变量能有一个开发者指定的初值。由于data,bss段的地方是在链接阶段确定的,所以这里需要配合linker文件才能找到科学的data,bss地点,linker文件是因IDE而异的,所有本文件要想做到通用,必须扩充各IDE条件编译,此处仅以IAR下的兑现为例:
//基于IAR的startup.c文件
#if (defined(__ICCARM__))
#pragma section = ".intvec"
#pragma section = ".data"
#pragma section = ".data_init"
#pragma section = ".bss"
#pragma section = "CodeRelocate"
#pragma section = "CodeRelocateRam"
#endif
void init_data_bss(void)
{
#if defined(__ICCARM__)
uint8_t *data_ram, *data_rom, *data_rom_end;
uint8_t *bss_start, *bss_end;
uint8_t *code_relocate_ram, *code_relocate, *code_relocate_end;
uint32_t n;
// 初始化data段 .data section (initialized data section)
data_ram = __section_begin(".data");
data_rom = __section_begin(".data_init");
data_rom_end = __section_end(".data_init");
n = data_rom_end - data_rom;
if (data_ram != data_rom)
{
while (n--)
{
*data_ram++ = *data_rom++;
}
}
// 初始化bss段 .bss section (zero-initialized data)
bss_start = __section_begin(".bss");
bss_end = __section_end(".bss");
n = bss_end - bss_start;
while (n--)
{
*bss_start++ = 0;
}
// 初始化CodeRelocate段 (执行在RAM中的函数(由IAR指定的__ramfunc修饰的函数)).
code_relocate_ram = __section_begin("CodeRelocateRam");
code_relocate = __section_begin("CodeRelocate");
code_relocate_end = __section_end("CodeRelocate");
n = code_relocate_end - code_relocate;
while (n--)
{
*code_relocate_ram++ = *code_relocate++;
}
#endif
}
void init_interrupts(void)
{
NVIC_ClearEnabledIRQs();
NVIC_ClearAllPendingIRQs();
}
10. application.c/h:
应用文本,此处便是主函数以及各职能函数的汇聚了,嵌入式老驾驶员们,请起首你的演艺~~~
void taskn(void)
{
...
}
int main(void)
{
printf("hello world\r\n");
taskn();
...
return 0;
}
至此,嵌入式开发里的各类来源的source文件豹哥便介绍完毕了,掌声在何地~~~
a = []
for i in range(10):
a.append(i+2)
print (a)
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
注:从地点可以看的出来,python列表解析比python
for循环解析列表的代码量会更少,解析速度会更快,写起来也更酷,自己独立写剧本的话,会这么些的省心。然则在可读性上来看仍旧多使用for循环更好有的。
2.文书和内建函数,open(),file()函数。
当我们耳熟能详了文本的操作了今后,会意识,文件的有始有终存储是很重点的。
(1)怎么样读写文件。
file=open("test.log","w")
注意:test.log是文本的名字和打开形式。”r“表示只读,”w“表示可写,”a“表示可增长,当然这只是里面的两种打开形式。
(2)下边的代码展现,提醒用户输入文件名,然后打开一个文本,并将它的内容体现出来。
filename=input("please input your filename:")
f=open(filename,"w")
for eachline in f:
print(eachline)
f.close()
瞩目:大家又再四遍的在print语句的末端使用逗号来遏制自动生成的换行符。因为在文书中一度给每行文本插足了一个换行符。
3.谬误和特别。
要给你的代码添加错误非凡处理,只要将它们”封装“在try-except语句中。try之后的代码就是您打算管理的代码。except之后的代码就是处理错误的代码。
try:
f=open("filename","r")
for eachline in f:
print(eachline),
f.close()
except IOError e :
print("file open error:",e)
4.函数。
接近于此外语言,python中的函数也用()来调用,函数在调用此前要先定义,假设函数中一贯不return语句,就会活动重回None对象。
5.怎么样定义函数。
def关键字及紧随其后的函数名,再增长该函数需要的多少个函数名组成函数的参数是可选的,这多少个讲话由一个冒号截至(:)与if,while语句的完结模式是平等的。
def add(x):
"apply+operation to arguement"
return (x+x)
6.如何调用函数。
与其它品种的语言同样,都是函数名再增长一对小括号(),括号之间是轻易可选的参数,既是一个参数也未曾小括号也无法省去。注意一下+操作符在非数值类型中是哪些做事的。
>>>add(4.25)
8.5
7.默认函数。
函数的参数是一个默认值,在函数的概念中,参数以赋值的言辞提供。事实上这只是是提供默认参数的语法,他意味着函数调用时只要没有提供这些参数,他就取这么些值作为默认值。
8.类。
雷是面向对象编程的主导,它是不无关全面据和逻辑的积存主题,它提供了创立真实对象的蓝图。由于python并不强求您面向对象的法子编程(与java不同),所以我们可以不学习类,可以通晓一下。在此处就简单的牵线一下。
9.在python中相比较实用用的片段函数。
(1)dir(obj):显示对象的性能。
(2)help(obj):以一种整齐赏心悦目的方法显示对象的文档字符串。
(3)int(obj):将一个目的转换为整型。
(4)len(obj):重返对象的尺寸。
(5)open(obj):打开文件的措施。
(6)range(obj):约束一个巡回中的范围。
(7)input(obj):内建函数。
(8)str(obj):将一个对象转换为字符型。
(9)type(obj):重临对象的品类。