当前位置:首页 > 嵌入式 > 嵌入式云IOT技术圈
[导读]前面移植了RT-Thread Nano,其实准确来说那不叫移植,那叫做部署,因为移植的工作官方已经帮我们做好了。 文章链接:小熊派移植RT-Thread Nano 1、引发思考-相关资料检索 在之前的文章提到过,RT-Thread已经提前在main函数以前就把跟硬件配置、系统初始化、启

前面移植了RT-Thread Nano,其实准确来说那不叫移植,那叫做部署,因为移植的工作官方已经帮我们做好了。


文章链接:小熊派移植RT-Thread Nano

1、引发思考-相关资料检索

在之前的文章提到过,RT-Thread已经提前在main函数以前就把跟硬件配置、系统初始化、启动调度器等相关的都做好了,所以我们后来看到的main函数非常简洁,真是让人感觉神清气爽,有继续往下写代码的欲望,如下:

main.c

int main(void)
{
while(1)
{
rt_kprintf("Hello RTT_NANO\n");
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
rt_thread_mdelay(500);
}
}

那具体RT-Thread又是如何实现在main函数执行之前就把所有初始化硬件、时钟的工作都做了呢?跟随官方文档的RT-Thread代码启动流程:

跟代码,最后发现如下代码:

/* re-define main function */
int $Sub$$main(void)
{
rtthread_startup();
return 0;
}

/* the system main thread */
void main_thread_entry(void *parameter)
{
extern int main(void);
extern int $Super$$main(void);

/* RT-Thread components initialization */
rt_components_init();

/* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
$Super$$main(); /* for ARMCC. */
#elif defined(__ICCARM__) || defined(__GNUC__)
main();
#endif
}

平时工作开发中没用到这样的语法,于是只能搜索文档来看看到底是如何实现的,果然在Keil帮助手册中找到了答案:

从文档中得知,Keil MDK编译器用$Sub$$$Super$$这两个符号来扩展了 main 函数,这使得使用$Sub$$main可以在main函数执行之前就预先执行$Sub$$main函数,所以在$Sub$$main函数里就可以完成一些基本的硬件、时钟初始化功能,做完这些工作以后,还是得跳转到main函数去执行往后逻辑的呀,这就需要通过调用$Super$$main来实现了。(注:在Keil MDK编译器中是这样的情况,但在IAR以及GCC环境下有差别,这里不做分析,等后面用到再说)。

既然main函数之前能这么用,是不是换个函数也能这么用呢?这引发我的好奇,于是继续查找文档,在armlink_user_guide手册中找到:

接下来开始做实验,然后我用stm32cubeMX生成一个基本裸机工程,下载到小熊派上来验证是否正确。

2、小熊派上进行实践

2.1 基本功能配置

配置外部时钟、调试串口、调试接口以及LED


最后生成代码。

2.2 编写代码进行验证

首先添加一个串口重定向函数,后面才能使用printf

int fputc(int ch,FILE *file)
{
return HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,1000);
}

接下来结合文档模仿RT-Thread写出以下函数:

void $Sub$$main(void)
{
extern int main(void);
extern int $Super$$main(void);
//初始化HAL
HAL_Init();
//初始化系统时钟
SystemClock_Config();
//初始化GPIO
MX_GPIO_Init();
//初始化串口
MX_USART1_UART_Init();
printf("初始化已完成\n");
//点灯
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
//回到真正的main函数里
$Super$$main();
}

main函数如下:

int main(void)
{
//延时2s
HAL_Delay(2000);
printf("回到main函数中\n");
while(1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(500);
}
}

将程序编译后下载到小熊派开发板中,然后打开串口调试助手可以看到:

由此可见,这是一个很有逼格的技能,以后可以在支持这种扩展符号的编译器下将这种技能应用起来,从而简化代码,接下来我们再往上面这个程序里添加功能:添加Function函数和在它之前运行的$Sub$$Function,然后在main函数里调用Function函数:

void $Sub$$Function(void)
{
extern void Function(void);
extern void $Super$$Function(void);
printf("在Function函数之前调用$Sub$$Function\n");
$Super$$Function();
}

void Function(void)
{
printf("执行Function函数\n");
}

int main(void)
{
//延时2s
HAL_Delay(2000);
printf("回到main函数中\n");
//调用Function函数
Function();
while(1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(500);
}
}

然后编译后将程序下载到小熊派开发板后,通过串口调试助手看到:

至此,我们已经完全弄明白RT-Thread是如何实现在main函数执行之前就把初始化硬件、系统初始化、启动调度器等工作都完成了的基本原理。

3、案例下载

公众号后台回复:main扩展 即可获取本节案例的下载链接。

往期精彩

什么?C/C++面试过不了?因为你还没看过这个!

MCU SPI屏也能跑这么炫酷的特效?来,移植起来秀一秀

推荐三个我工作中经常使用的驱动大全wiki(建议收藏并转发让更多人知道!)

会C/C++就可以开发Linux/Android应用程序?替代传统串口屏的Yoxios了解一下!

觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭