在STM32上模拟Linux自动初始化过程

Linux中有很多编程思想可以学习,很多大佬把这些思想、机制运用到单片机的编程上,STM32 模拟Linux kernel自动初始化流程。


通常我们写程序都是按照这个套路,一个函数一个函数按照顺序逻辑一个一个的执行下去。

4821496f55fff436720f161fdbbab61c.png

如果逻辑非常复杂,涉及的模块比较多,那么这种顺序执行的代码就会比较臃肿,各模块耦合非常紧密。Linux kernel 中,有各种外设驱动,想按照一个顺序逻辑执行下去,几乎是不可能的。

而kenrel 代码能有这么大的代码量,大而不乱,把各层次,各模块有效的分离,而大量的代码又有逻辑的组织在一起,和这个initcall 有至关重要的作用。

通过模仿这种方式,最后把图片中main函数代码清空,分离这种逻辑,又实现同样的功能。

如何能实现这样的功能了,需要一些背景知识:

1,程序代码的组织

2,链接脚本相关的知识。

3,函数指针的应用。

648acfcad45779c867fc14b8a75cc1c6.png

代码的组织,如图片需要知道变量a,b及函数指针 f,f2是存放在程序的哪些段中,可以去看一下这篇stm32 启动代码 实现|C语言,上述的a,f都是存放在bss 段中,b,f2是存放在data段中,因为已经给定了初始值,而实现这个intcall会把需要自动初始化的数据放到一个自定义的段中去,如.initcall。

如何放到特定的段中了,就需要用到了attribute((section)) 关键字来改变的数据存放段了。

目前的程序编译出来用到了这些个段,除了.isr_vector也是添加的,其他都是编译器默认的。

053fca1226e6c0d0579bd13f8c073e57.png

先加段代码:

6d423d15521ebb87f4cc7ef28b35dcac.png

当然这还不够,还需要告诉连接器(LD) 要把 .initcall 段也链接到程序中,所以也需要这段修改。

7980a5061981668b1ba14850c7bafe4a.png

这段按8字节对齐,定义两个全局变量,及按0-5顺序的链接这些数据,这样的两处修改,再来看一下程序各段的情况。

如图片:

612f624f911c7dc4f6edde59ab8e06de.png

已经多出红色框框为.initcalls段,这段总共是8个字节,从0x80005a8除开始。

在来看一下具体的这一段的情况,用readelf 工具。

44eaf208530b3964b7748142b793572f.png

和上面的size工具是匹配的,而绿色框框的地址就是SystemInit(0x08000231,小端模式。)

f8b8685590b5f6899d2e9f8d0a74a745.png

所以通过attribute及修改链接脚本,就把函数指针变量放到了.initcall 段中。

那么如何来调用这个函数了,和之前的初始化data段数据类似,遍历这个段,然后取出这个函数地址,然后强制把段中的地址,转成函数指针,再直接调用即可。

7568fad376f440385c635aec1f3434a1.pnga0d8987e23da815f334bbeaf0c04732c.png

实现的这张图片,就是从.initcall段中取出函数地址,然后直接调用,非常容易把函数的地址及这个函数指针变量的地址搞混。

代码这么修改,需要自动初始化函数的确是可以调到了,但是每次都写这么长长的一段static initcall_t __ attribute__(( __ used__,__ section__(".initcall.0.init"))),就是不舒服. linux kernel中通过宏来修改。

这个也一样。

736d0bb3a2add29fab8052a76eb7ed1d.png

添加 按照程序逻辑顺序执行的一些宏

0,low_level_init 比如放始化系统基本时钟

1,arch_init 比如放CPU架构d如初始化NVIC的一些初始化。

2,dev_init 外设模块初始化,比 i2c, flash, spi等。

3,board_init 做具体硬件板及的一些设置。

4,os_init 操作系统的一些设置如,文件系统,网络协议栈等。

5,app_init 最后跑用户程序。

把自己的程序也做一下修改,用宏代替。这样子掉调用do_initcalls 就会按照0,1-到5的顺序执行了。

7bb04d1953006edfee1bf951b6066699.png5caabe1e3eed3ce99bf63d5a1226c6be.png

最后在来看一下initcall 段:

4a6b27b8c525f8957dd6acca6bb09f0c.png6863f1b1d7f6ae1643df2eb0f9e0ceee.png46986b7e38d815200c8b86ca24b472e7.png40dace7c31340cd3f2954208eb65eaf4.png

这样只要在需要自动初始化函数加上类似于dev_init(),app_init() 就可以了,就会自动调用到,而不需要main 函数中一个一个的顺序执行。

比如i2c控制的初始化放到dev_init 中,下面挂了很多i2c的从设备,只要分别给个从设备用app_init 初始化就行,即使来了一个新的,也用这app_init初始化就行,也不需要更改原来的,高度的分离模块间的耦合度。

这样模拟Linux kenerl 初始化验证成功,最后上库。

原文来源于:

https://gitee.com/android_life/stm32_freertos_opensource/tree/master/bareos/initcall

版权归原作者或平台所有,仅供学习参考与学术研究,如有侵权,麻烦联系删除~感谢

d1a5f6158429adbb4b9406e14a60c28b.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464070.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

日志配置(springboot、mybatis、Lombok)

Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J, Log4J2和Logback。每种Logger都可以通过配置使用控制台或者文件输出日志内容 SLF4J——Simple Logging Faca…

先知

他这样说爱情:Love gives naught but itself and takes naught but from itself.Love possesses not nor would it be possessed.For love is sufficient unto love.转载于:https://www.cnblogs.com/belial/archive/2007/09/23/903433.html

TCP与UDP的选择--结合QQ来说明

TCP与UDP的选择如果比较UDP包和TCP包的结构,很明显UDP包不具备TCP包复杂的可靠性与控制机制。与TCP协议相同,UDP的源端口数和目的端口数也都支持一台 主机上的多个应用。一个16位的UDP包包含了一个字节长的头部和数据的长度,校验码域使其可以…

Xampp修改数据库默认用户root的密码

Xampp数据库默认用户root,密码为空,修改密码的位置:xampp/passwords.txt转载于:https://www.cnblogs.com/testlife/archive/2012/02/08/2342438.html

1.6元的蓝牙芯片,你能想得到?

前不久喵了个咪在群里发了一个1.6元的SOP8蓝牙芯片的信息,引起了大家的热烈讨论,我当然也按捺不住鸡冻的心情,立马下单买了几片。淘宝连接:KT6368Ahttps://item.taobao.com/item.htm?spma1z09.2.0.0.74a52e8dTpp1my&id630430…

pyplot交互地画多个plot

下面的代码,可以无阻碍地show 5个figure,相当于开启了ipython的interactive 模式 具体参见stackoverflow: in matplotlib, is there a way to pop up a figure asynchronously? 1 #!/usr/bin/python2 import pylab as plb3 import matplotlib.pyplot as…

又是一年中秋节,好想举杯邀明月

世事一场大梦,人生几度新凉。夜来风叶已鸣廊,看取眉间鬓上。 酒贱常愁客少,月明多被云妨。中秋谁与共孤光,把盏凄然北望。 简策写虚名, 蝼蚁侵枯骨。千古光阴一霎时,且进杯中物。 二十四年过去&#xff…

UDT内部代码分析

一. 报文发送 1.CSndQueue::worker中调用CChannel::sendto发送数据报文。 2.CSndQueue::sendto中调用CChannel::sendto发送其他报文, 种类较多主要有: 1)CUDT::connect中调用CSndQueue::sendto发送建立连接请求。 2) CUDT::sendCtrl中调用CSndQueue::sendto发送控制报文。 …

ADC采样效应及相关影响解剖

在前述文章,BUCK电路模拟补偿器的数字化过程 ,我们讨论了模拟补偿器的数字化,事实上,数字化过程的第一个重要的环节就是ADC对反馈量的采样,本文就重点探讨一下由于ADC采样频率带来的一些问题,进而讨论一下相…

2012.2.9日晚亚马逊的一个错误链接截图

1现在时间 2 问题链接 http://www.amazon.cn/%E5%81%A5%E8%BA%AB%E5%99%A8%E6%A2%B0/b/refsa_menu_sef7?ieUTF8&node42787071 3 点击后结果 http://www.amazon.cn/gp/product/B0073RWUQA/refs9_hps_bw_g200_ir05?pf_rd_mA1AJ19PSB66TGU&pf_rd_scenter-5&pf_rd_r0…

Kotlin 的 Array 转 List

Kotlin 的 Array 转 List array.toList() as List<T> 1Kotlin 的 Array 转 ArrayList array.toList() as ArrayList<String>转载于:https://www.cnblogs.com/weizhxa/p/10068944.html

[转]关于sizeof()的一些思考

关键字&#xff1a;sizeof&#xff0c;字节对齐&#xff0c;多继承&#xff0c;虚拟继承&#xff0c;成员函数指针 前向声明&#xff1a; sizeof&#xff0c;一个其貌不扬的家伙&#xff0c;引无数菜鸟竟折腰&#xff0c;小虾我当初也没少犯迷糊&#xff0c;秉着“辛苦我一个…

RCF的优势--分布式应用

RCF(远程调用框架)是一个可以移植的C进程间通信框架&#xff0c;使用C语言特性&#xff0c;提供了一个简单高效的编写分布式C软件的途径。RCF利用编译时多态清晰分开了接口和实现. 和传统的RPC框架如CORBA,DCOM,.NETRemoting,WCF,WS-*,等所支持的面向对象方式不一样&#xff0c…

深漂结束

早上起来看了勇士和凯尔特人的比赛&#xff0c;勇士还不能适应凯尔特人的防守&#xff0c;除了防守之外&#xff0c;凯尔特人这场比赛的三分球着实太高了。说到篮球&#xff0c;突然想起一个刚离开深圳去惠州工作的朋友。上周二中午&#xff0c;吃饭的时候我打开手机&#xff0…

RS 学习笔记 3-1

3-1 fence climb onto/jump off salad towel napkin ladder 转载于:https://blog.51cto.com/mingii/776041

JS的八大数据类型

js中的数据类型&#xff0c;包括基本数据类型&#xff08;Number,String,Boolean, Undefined,Null&#xff09;和 复杂&#xff08;引用&#xff09;数据类型&#xff08;Object,Array,Function&#xff09; 基本数据类型 基本数据类型指的是简单的数据段 &#xff08;Number,S…

嵌入式软件是这样debug的

【单步调试】【多线程调试】调试过多线程的都懂的。【断点调试】【递归调试】调试过递归代码的都有这种耳鸣目眩的感觉。【老旧代码调试】对于早期已经缝缝补补的庞大软件代码进行调试&#xff0c;还不如推倒重来。【生产中代码调试】【用户等待调试结果】【掩耳盗铃式调试】【…

可以直接在C++里面写类似RSL的shader了

可以直接在C里面写类似RSL的shader了 今天我搞定了一个新技术 可以直接在C里面写类似RSL的shader了 我简要介绍一下这个新技术&#xff0c;我还在考虑是否要在我们的项目中应用 这个技术的优势是可以借助现有的C编译器&#xff0c;将shader直接编译成机器码执行&#xff0c;这样…

UDT中select异常

转载&#xff1a;http://blog.csdn.net/seebit/article/details/6050428 select, selectEx的参数采用了stl的容器&#xff0c;在DLL方式下&#xff0c;会发生异常。 select传入的容器内的对象在DLL内部发生释放操作时&#xff0c;会抛出异常&#xff0c;因为主程序和DLL申请的内…

iOS中有两种支持机制:Notification和KVO(Key-Value Observing)

KVO是iOS中的一个核心概念&#xff0c;简单理解就是&#xff1a;关注Model某个数据&#xff08;Key&#xff09;的对象可以注册为监听器&#xff0c;一旦Model某个Key的Value发生变化&#xff0c;就会广播给所有的监听器&#xff08;http://blog.chinabyte.com/a/1557371.html&…