操作系统:为啥要引入操作系统,个人的理解是为了实时性(即及时的响应性)。

  没有操作系统下多个任务都只能以前后台的方式排队执行,对某个任务的输入不能得到及时的响应;虽然后台有中断,但不能把所有的任务都放在后台的中断里;操作系统的引入解决了实时性的问题,tick的调度使得任务看上去是在并行执行,因此对输入的响应是及时的,不会被其他任务迟滞。

Nuttx 特性:

1)同优先级的线程,如果是FIFO的调度策略则没有时间片的概念,不主动让出不会切换;如果是RR的调度策略,则就按时间片,时间到了强制切换。

2)优先级值越大,优先级越高,0为IDLE线程,与FreeRTOS同,与rtthread反。

3)类型rt-thread最低优先级的中断也可以抢占最高优先级的线程。

4)线程间同步用mutex或rwlock,不建议使用调度器开关和中断开关。

5)内核版本下优先使用nx开的API,kthread等同task创建的是进程,pthread创建的是线程。

6)优先级翻转是指高中低三个线程,低的持有资源,高的获取资源,中的会一直抢占低的执行,导致低的放不出资源,导致中的在执行而高的在挂起,中的和高的发生了执行翻转。

7)系统没有main()函数,只有一个完整的工程才有唯一的一个main()函数作为整个工程的总入口,在main()里调用硬件初始化和系统启动函数,比如nuttx的nx_start(),Freertos的    vTaskStartScheduler(),rt-thread的rtthread_startup(),之后具体一个功能的总入口也会有个main(),但这个main()会被链接(改名)为XXX_main(),被总入口的main()去调用,从而进入模块;shell比如bash,nsh,rt-shell,接受命令输入,命令是个被调函数的函数名或者编译后模块的名称代号,在shell中输入这个代号就会执行这个函数/模块。

 

1. #include <nuttx/config.h> 包含的就是nuttx路径下的.config文件,.只是为了隐藏文件,make的时候会把.config文件中开启的配置变成config.h文件,放在nuttx/include/nuttx下。

2. 在具体处理器下添加新功能,需要在app/example/下添加支持代码和src/自己写的Kconfig。其所用到的诸如SPI等底层驱动已经存在,只需要在Kconfig中打开即可,支持代码中实现中间层和应用层。

3. sim:hello 表示在sim的板下有个hello的应用,之所以有是因为在sim/configs/下存在hello的文件夹,在hello文件夹下存在能使hello应用跑起来的最原始配置文件defconfig。每次make distclean后nutt/.config就会消失,此时打开的make menuconfig为原始的defconfig的配置。此时可以在打开的menuconfig中选择新的配置,之后保存+make就会生成新的.config和include/config.h,但不会修改defconfig。Kconfig文件中的项为menuconfig和代码中以CONFIG_开头的宏的原型,即如果Kconfig中存在STM32_SPI1的项,如果在menuconfig中选中后,在Kconfig中就会由n变为y,同时代码中CONFIG_STM32_SPI1的宏会被使能。(代码中CONFIG_XXX的宏的原型为Kconfig中的XXX,要增/删CONFIG_ 在Kconfig和代码中匹配搜索)。如果想要添加一个配置XXY就要在Kconfig中手动添加XXY的项,这样menuconfig中就会多出XXY此项。

4. 路径下的软链接是为了添加头文件,Kconfig,Make.deks等提供方便。

5. Makefile只在最接近源码的地方存在,其下层再无Kconfig/Make.defs

6. undefined reference 的错误解法:1.在提示的错误所在文件的头中尾和错误所在行的上方依次添加错误,看是否编译;2.在函数定义所在文件对应的.h文件中添加函数声明,同时在定义文件中include上述.h文件,之后在调用的地方添加extern的函数引用声明。3.文件是否被编译,看是否存在对应文件的.o。4.生成的.o再重新编译时是否被删除(如未删须手删)。

7. git status 和git diff的差异来自当前工作区与最后一次commit之后本地仓库的不同。如果commit后push则本地仓库全同于远程仓库,如没有push则2者不同。

8. 编译不过时 删除标记为 :自动生成的 Kconfig文件,等同于手动干了distclean干的事。

9. 都是makefile在作妖,把不用的makefile变为makefile.txt,删除.kconfig,kconfig等文件。

10. 提示undefined reference时,删除所有.o文件, 同时查看定义该函数的源文件是否编译为.o,必须有!!!

11. #include 的起始路径不是.c文件所在的路径,而是编译此.c文件所对应的Makfile文件CFLAGS指到的最后一级路径!!!

12. 应用主入口内写while(1)会卡shell,无法输入;但是在主入口内建个任务,在任务内跑while(1)就不会卡shell了。

13. Kconfig文件会决定menuconfig的配置项,而整个工程是否编译是由工程的Make.def是否被包含所决定的,具体工程内的某个文件由Makefile决定是否编译。上层的Kconfig通过source包含下层的Kconfig,上层的Make.def通过添加CONFIGURED_APPS去包含下层的Makke.def。

14. 可重入(公共代码段)中被调的函数中不能出现谁都可以操作一个全局/静态变量的操作,可以各操作各对应的栈变量。

15. 何为阻塞,即不执行,阻塞分为长期阻塞和定时阻塞,在一直都获取不到所要等的东西时,如果超时时间是-1/ffffffff则只会在首次调用时才会执行一次阻塞函数;如果超时时间为具体值,则每到一次超时时间就执行一次阻塞函数。

16. fifo中入数据时in标签向前环回涨,等于out标签时,表示满fifo都是数据,但这样无法和空fifo区别;一般的做法是in++等于out的时候,out会自加1,表示有满fifo-1个未读的数据,自动丢弃最早的未读的1B数据;而出数时的out标签等于in标签时表示FIFO为空,in标签不会自加。

17. 任意一个.c有且仅能出现在一个Makefile中,如果同名的.c出现在不同的Makefile中就会出现重复定义的问题(比如.c中含有可重入的函数时)

18. 对消息队列/文件等的打开操作返回的(int)fd属于任务资源,不能被跨任务访问;一切在任务task内创建的东西都只能被此任务使用,其余的任务访问不到的 >>>切记<<<

19. 协议栈是指协议的集合,它描述了数据从应用层到底层硬件,再从底层硬件到应用层的传输过程,每一层都有自己专属的协议去描述,上下层间是彼此包含的关系,即从上到下一层一层往上包,从下到上一层一层往下剥,c/s两端同层间虽然是不直连的,但是他们的协议一样,等同于同层间的透传。

20. 蓝牙的Host和Controller分模块的最初设计理念是想让这两个模块单独运行在两颗不同的芯片甚至系统上,之间通过硬件通信端口(串口,USB)使用HCI协议进行连接和通信;现在虽然有不少芯片把Host和Controller模块都放在了一颗芯片上,但是基本还是遵循这样的层次结构,只是将HCI协议从硬件通信端口换成了软件端口。

21. boot0所决定的启动位置需要和中断向量表配合工作,即需要把中断向量表按offset的顺序放在boot0指定的启动区域的开始位置。

22. 单片机上的存储有SRAM和FLASH两种,类似pc上的内存和磁盘,两者均支持读写操作但是sram要比flash快的多。程序编译之后会有text,ro,rw(.data),zi(.bss)这4种文件,编译之后会把他们都存在flash中(相当于是个临时的保存位置),上电之后会把他们从falsh中搬到sram中,所以同一个rw的变量应该会有2个地址,一个是存到flash中的地址,一个是存到sram中的地址。两块区域各有各的存储排布顺序,比如flash中从08000000开始先存MSP,之后是中断向量表,这以后是RO,TEXT,RW(后几者的顺序确定)。但是这些数据搬到sram中又有自己的排布,先是RO,rw再是zi,(text待定)之后是堆栈。

23. SRAM会有多个区域,每一个区域由于其所处地址对应总线的特性,会决定该区域所能存放的数据类型,即虽然text和RO-RW-ZI段都能放到SRAM中,但是text段是指令,RO-RW-ZI段是数据,故text段不能放到总线类型是数据的SRAM区域中,RO-RW-ZI段也同理。

24. 所谓软件中断,是指该中断可通过软件的配置实现中断的触发,(软件可以模拟所有中断)

25. c/s两端的连接,本质上就是双方为此服务在彼此的内存中开辟空间,各自执行对应的内核代码。

26. 系统中类似信号量互斥锁等组件都是全局可共享的,即类似全局变量一样,所有的进程(task)均可访问其成员,这也是实现组件功能的必要条件;而进程中打开的诸如文件等要素则依赖系统特性,有的全局唯一,大家均可访问,有的则专属于创建进程。

27. include过来的诸如stdio.h是来自于编译工具链诸如gcc当中.

28. sem_wait 与sem_trywait的区别是前者会一直等,会阻塞,高优先级释放后,低优先级能立马被唤醒去执行;而后者只是去获取一下,如果在获取的瞬间能拿到则执行,如果过去的瞬间没拿到,即使之后马上就释放了,这里也会跳过,又被别的线程获取了,会导致用try的线程可能会很久也拿不到。

29. 出现硬件中断hard-fault的原因:(1)sram大小定义不对;(2)线程分配内存太小;(3)野指针,即指针取的地址超过了预定义的,访问了不该访问的,常见的数组越界;(4)使用还未初始化的外设或组件;(5)

30. 因为数据指针是附着在消息上发送的,所以必须要用calloc申请空间,让消息一直带着数据指针,而不能用函数内的局部数组和指针,因为他们在函数调用完后就会释放,这样在释放消息时就会出现rt_free的错误

31. 正常内存中存储是大端序即低字节在前,对于U8不影响,但对于u16和u32会有影响,比如0x5AA5在内存和flash中都是0xA55A。所以须转化为小端序即高字节在前。

#define XIAODUAN(VAL) ((((u16)(VAL) & 0xFF00) >> 8) | (((u16)(VAL) & 0x00FF) << 8))

32. 表达式的值和类型取决于表达式中左值的数据类型,即 a+b的值会强制转为a的类型

 

 

 

 

 

 

posted on 2023-02-13 10:49  lance9527  阅读(816)  评论(0编辑  收藏  举报