RTT移植STM32之创建进程
目录
1.RTT系统启动
2.创建自己的进程
1.RTT系统启动
RTT系统将main函数重定义在$Sub$$main(void)中,即程序运行顺序如下:
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
int $Sub$$main(void)
{
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
int rtthread_startup(void)
{
rt_hw_interrupt_disable();
/* board level initialization
* NOTE: please initialize heap inside board initialization.
*/
rt_hw_board_init();
/* show RT-Thread version */
rt_show_version();
/* timer system initialization */
rt_system_timer_init();
/* scheduler system initialization */
rt_system_scheduler_init();
#ifdef RT_USING_SIGNALS
/* signal system initialization */
rt_system_signal_init();
#endif
/* create init_thread */
rt_application_init();
/* timer thread initialization */
rt_system_timer_thread_init();
/* idle thread initialization */
rt_thread_idle_init();
/* start scheduler */
rt_system_scheduler_start();
/* never reach here */
return 0;
}
rtthread_startup函数中 rt_hw_board_init()在boardc中,是对板子硬件的初始化,程序如下
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#define STM32_SRAM_SIZE 64
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
void rt_hw_board_init()
{
/* System Clock Update */
RCC_Configuration();
GPIO_InitTypeDef gpioInit;
//打开GPIOB的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);
//LED上拉连接GPIOB 12引脚,所以设置如下,推挽输出,Pin12,2MHz输出速度
gpioInit.GPIO_Mode=GPIO_Mode_Out_PP;
gpioInit.GPIO_Pin=GPIO_Pin_5;
gpioInit.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&gpioInit);
GPIO_Init(GPIOE,&gpioInit);
gpioInit.GPIO_Mode=GPIO_Mode_Out_PP;
gpioInit.GPIO_Pin=GPIO_Pin_12;
gpioInit.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&gpioInit);
/* System Tick Configuration */
_SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND) ;
/* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
//rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
rt_system_heap_init(HEAP_BEGIN, (void *)STM32_SRAM_END);
#endif
}
其中rt_system_heap_init(HEAP_BEGIN, (void *)STM32_SRAM_END)是对堆heap的初始化,HEAP_BEGIN是从
Image$$RW_IRAM1$$ZI$$Limit
开始,到指定大小后结束。
然后回到rtthread_startup()对RTT系统定时器,调度器,信号量等功能初始化,再调用rt_application_init()创建main()进程以回到用户自己的main()中,后面开启调度器,进入main()函数中。rt_application_init()程序如下:
oid rt_application_init(void)
{
rt_thread_t tid;
#ifdef RT_USING_HEAP
tid = rt_thread_create("main", main_thread_entry, RT_NULL,
RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(tid != RT_NULL);
#else
rt_err_t result;
tid = &main_thread;
result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(result == RT_EOK);
/* if not define RT_USING_HEAP, using to eliminate the warning */
(void)result;
#endif
rt_thread_startup(tid);
}
2.创建自己的进程
在main()可以先对模块功能初始化,然后创建进程。main()函数运行完自己会把自己(注销?)挂起,反正不会运行自己了。程序如下:
/***************************************************************************************
备注:
*
***************************************************************************************/
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "w5500.h"
#include "24c02.h"
#include "spi.h"
#include "cd4051.h"
#include "adc.h"
#include "bsp_485.h"
#include "ioinput.h"
#include <string.h>
#include "led.h"
#include "oled.h"
#include "HT16K33.h"
#include "display.h"
#include "bsp_adc.h"
#include "pt100.h"
#include <stdbool.h>
#include "rtthread.h"
//#include "application.h"
extern float Tem[8];
extern u8 number[20];
extern unsigned char Read_W5500_1Byte(unsigned short reg);
u8 flag_usart =0 ; //串口1接收标志位
u8 key[6];
extern __IO uint16_t ADC_ConvertedValue[4];
float ADC_ConvertedValueLocal[4];
void AD2(void);
void VibAndTem(void);
static rt_thread_t thread1=RT_NULL;
static rt_thread_t thread2=RT_NULL;
static rt_thread_t thread3=RT_NULL;
static rt_thread_t thread4=RT_NULL;
static rt_thread_t thread5=RT_NULL;
static rt_thread_t thread6=RT_NULL;
static void thread1_entry (void *parameter);
static void thread2_entry (void *parameter);
static void thread3_entry (void *parameter);
static void thread4_entry (void *parameter);
static void thread5_entry (void *parameter);
static void thread6_entry (void *parameter);
/* 定时器的控制块 */
static rt_timer_t timer1;
static rt_timer_t timer2;
u8 cnt;
u8 Y_num[8];
u8 R_num[8];
/* 定时器1超时函数 */
static void timeout1(void *parameter)
{
// if ( thread3 != RT_NULL)
rt_thread_resume (thread3);
rt_schedule();
/* 运行第10次,停止周期定时器 */
/* if (cnt++ >= 9)
{
rt_timer_stop(timer1);
rt_kprintf("periodic timer was stopped! \n");
}
*/
}
/* 定时器2超时函数 */
static void timeout2(void *parameter)
{
rt_thread_resume (thread6);
rt_schedule();
}
int timer_sample(void)
{
/* 创建定时器1 周期定时器 */
timer1 = rt_timer_create("timer1", timeout1,
RT_NULL, 10,
RT_TIMER_FLAG_PERIODIC);
/* 启动定时器1 */
if (timer1 != RT_NULL)
rt_timer_start(timer1);
/* 创建定时器2 周期定时器 */
timer2 = rt_timer_create("timer2", timeout2,
RT_NULL, 10,
RT_TIMER_FLAG_PERIODIC);
/* 启动定时器1 */
if (timer2 != RT_NULL)
// rt_timer_start(timer2);
return 0;
}
static void thread1_entry(void* parameter)
{
while(1)
WEB();
}
static void thread2_entry(void* parameter)
{
while(1){
//点亮LED
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
//延时0.5s
rt_thread_delay(RT_TICK_PER_SECOND);
//关闭LED
GPIO_SetBits(GPIOB,GPIO_Pin_12);
//延时0.5s
rt_thread_delay(RT_TICK_PER_SECOND);
cnt++;
// analogArry[1]=cnt;
// Tem[0]=(float)cnt;
}
}
static void thread3_entry(void* parameter)
{
while(1)
{
VibAndTem();
DISPLAYfloat(Tem[0],Tem[1],Tem[2],Tem[3],Tem[4],Tem[5],Tem[6],Tem[7]);
rt_thread_suspend(thread3);
rt_thread_resume (thread6);
rt_schedule();
}
}
static void thread4_entry(void* parameter)
{
while(1){
AD();
}
}
static void thread5_entry(void* parameter)
{
while(1){
AD2();
}
}
static void thread6_entry(void* parameter)
{
while(1)
{
u8 y_num[8]={1,1,1,1};
u8 r_num[8]={0,0,0,0,1,1,1,1};
display_led(y_num,r_num);
rt_thread_suspend(thread6);
rt_schedule();
}
}
int rt_application_init1()
{
thread1 = rt_thread_create("thread1",
thread1_entry,
RT_NULL,
512, 10, 10);
if (thread1 != RT_NULL)
rt_thread_startup(thread1);
//进程2初始化
thread2 = rt_thread_create("thread2",
thread2_entry,
RT_NULL,
512, 10, 10);
if ( thread2 != RT_NULL)
rt_thread_startup(thread2);
//进程3初始化
thread3 = rt_thread_create("thread3",
thread3_entry,
RT_NULL,
1024, 8, 20);
if ( thread3 != RT_NULL)
rt_thread_startup(thread3);
//进程4初始化
thread4 = rt_thread_create("thread4",
thread4_entry,
RT_NULL,
1024, 10, 10);
if ( thread4 != RT_NULL)
rt_thread_startup(thread4);
//进程5初始化
thread5 = rt_thread_create("thread5",
thread5_entry,
RT_NULL,
512, 10, 10);
if ( thread5 != RT_NULL)
rt_thread_startup(thread5);
thread6 = rt_thread_create("thread6",
thread6_entry,
RT_NULL,
512, 7, 10);
if ( thread6 != RT_NULL)
rt_thread_startup(thread6);
return 0;
}
/*******************************************************************************
* 函数名 : main
* 描述 : 主函数,用户程序从main函数开始运行
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
int main(void)
{
I2C_INIT(); //IIC初始化
uart_lora_init();
Load_Net_Parameters(); //装载网络参数
System_Initialization(); //STM32系统初始化函数(初始化STM32时钟及外设)
W5500_Hardware_Reset(); //硬件复位W5500
W5500_Initialization(); //W5500初始货配置
InitCD4051(); //4051初始化
bsp_InitSPIBus(); //SPI初始化
InitTM7705(); //ADC初始化
TM7705_CalibSelf(1); /*自校准,?180ms */
TM7705_CalibSelf(2); /*自校准,?180ms */
//Lora_config();
ADC1_Init();
DISPLAY_INIT();
rt_application_init1();
timer_sample();
rt_schedule();
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Io_Init();//IO初始化
// RFS_GPIO_init();//恢复出厂设置按键初始化函数
//Modbus_Init();//modbus初始化
//RS485_Init();//测试
TIM4_Init();
// Timer5_enable(99);
//while(1)
//{
// //AD();
// VibAndTem();
// //AD2();
// //DISPLAY(1,2,3,4,5,6,7,8);
//
//}
//
}
void VibAndTem(void)
{
uint16_t Tem_ADC[6];
float V1,V2,R1,R2;
//AD();
Tem_ADC[0]=(analogArry[0]<<8)|analogArry[1];
Tem_ADC[1]=(analogArry[2]<<8)|analogArry[3];
Tem_ADC[2]=(analogArry[4]<<8)|analogArry[5];
Tem_ADC[3]=(analogArry[6]<<8)|analogArry[7];
Tem_ADC[4]=(analogArry[8]<<8)|analogArry[9];
Tem_ADC[5]=(analogArry[10]<<8)|analogArry[11];
V1 =(float) (Tem_ADC[4])/65535*2.5/51;
V2 =(float) (Tem_ADC[5])/65535*2.5/51;
R1=(V1*14000+2000)/(20-V1*7);
R2=(V2*14000+2000)/(20-V2*7);
//Tem[4]=CalculateTemperature(R1);
// Tem[5]=CalculateTemperature(R2);
Tem[0]=(float) (Tem_ADC[0])/65535*1000/50;
Tem[1]=(float) (Tem_ADC[1])/65535*1000/50;
Tem[2]=(float) (Tem_ADC[2])/65535*1000/50;
Tem[3]=(float) (Tem_ADC[3])/65535*1000/50;
}
void AD2(void)
{ u8 i;
uint16_t My_ADC[4][30];
for(i=0;i<30;i++)
{
My_ADC[0][i]=ADC_ConvertedValue[0];
My_ADC[1][i]=ADC_ConvertedValue[1];
My_ADC[2][i]=ADC_ConvertedValue[2];
My_ADC[3][i]=ADC_ConvertedValue[3];
}
ADC_ConvertedValueLocal[0] =(float) GetDelExtremeAndAverage(My_ADC[0],30,5,5)/4096*3;
ADC_ConvertedValueLocal[1] =(float) GetDelExtremeAndAverage(My_ADC[1],30,5,5)/4096*3;
ADC_ConvertedValueLocal[2] =(float) GetDelExtremeAndAverage(My_ADC[2],30,5,5)/4096*3;
ADC_ConvertedValueLocal[3] =(float) GetDelExtremeAndAverage(My_ADC[3],30,5,5)/4096*3;
}
在这个程序中创建了两个定时器,6个线程。定时器2暂时没用,定时器1用于启动线程3进行数码管扫描;进程1进行网络通讯;进程2控制继电器;进程3进行计算和显示;进程4进行AD7705读取;进程5进行STM32自带AD读取;进程6进行LED灯显示。其中,LED灯显示与数码管显示冲突,两个进程不可以同时运行,因此让进程3调度进程6。
————————————————
RTT移植STM32之创建进程相关推荐
- Linux下创建进程简介
在博文https://blog.csdn.net/fengbingchun/article/details/108940548中简单介绍了Windows下通过函数CreateProcess创建进程的过 ...
- Windows下创建进程简介
正在执行的应用程序称为进程,进程不仅仅是指令和数据,它还有状态.状态是保存在处理器寄存器中的一组值,如当前执行指令的地址.保存在内存中的值,以及唯一定义进程在任一时刻任务的所有其他值.进程与应用程序的 ...
- 从创建进程到进入 main 函数,发生了什么?
作者 | 轩辕之风O 来源 | 编程技术宇宙(ID:xuanyuancoding) 头图 | CSDN 下载自东方IC 前几天,读者群里有小伙伴提问:从进程创建后,到底是怎么进入我写的 main 函 ...
- 小实验:用创建进程()打开计算器,然后关闭进程句柄。再用打开进程(进程ID),使用两次,得到两个进程句柄。实验目的:这两个进程句柄都能控制这个进程吗?通过该试验加深对句柄的理解!!...
小实验:用创建进程()打开计算器,然后关闭进程句柄.再用打开进程(进程ID),使用两次,得到两个进程句柄.实验目的:这两个进程句柄都能控制这个进程吗? .版本 2 .程序集 窗口程序集1 .子程序 _ ...
- 使用Native API 创建进程
使用 Native API 创建进程 最近几个星期一直在研究这个题目.因为关于方面的资料比较多(可以看下面的参考文章),所以开始时以为很快就结束了.谁知道真正动起手来才发现有很多要考虑的地方,不过还好 ...
- python之multiprocessing创建进程
python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. multiprocessing创建多进程在windows和linux系统下的 ...
- 遍历创建进程、创建线程、加载模块的回调函数
今天我们首先来看一下最简单的,关于遍历PspCreateProcessNotifyRoutine数组,PspLoadImageNotifyRoutine也同理 这两个数组保存了两组函数地址,它们将在有 ...
- linux创建进程读共享写复制,Linux下进程的创建、执行和终止
1)进程的创建和执行 许多操作系统提供的都是产生进程的机制,也就是说,首先在新的地址空间里创建进程.读入可执行文件,后再开始执行.Linux中进程的创建很特别,它把上述步骤分解到两个单独的函数中去执行 ...
- 循环中fork创建进程的个数
linux下创建进程的系统调用是fork.其定义如下 #include <sys/types.h> #include <unistd.h> pid_t fork(); 在循环中 ...
- 【Linux 内核】进程管理 ( 进程状态 | 进程创建 | 进程终止 | 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 )
文章目录 一.进程状态 二.进程创建 三.进程终止 ( 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 ) 一.进程状态 Linux 进 ...
最新文章
- UVa 11000 - Bee
- Codeforces Global Round 4 题解
- 来吧!我教你画真正的流程图
- Java黑皮书课后题第10章:*10.19(Mersenne素数)
- 简化路径Python解法
- Docker 第四章 访问容器
- 初阶和高阶产品之间的核心差距
- DCL 管理用户 mysql
- 05 ansible剧本编写
- 第二章--电商设计表-商品模块--mysql电商项目设计
- Coding the Matrix Week 1 The vector 作业
- android联系人源码分析,android 联系人源码分析 新字段的添加流程
- 以教务管理的成绩单查询为例,SSM整合开发过程详解(spring、springmvc、mybatis)
- mysql flush tables_MySQL 清理缓存—flush tablesFlush tables的影响
- 攻防世界Web新手区题解
- VTK读取序列DCM格式医学图像
- echarts自定义主题构建
- 贪心算法——区间选点问题
- 搜一下导航完整程序源码+亲测可用
- IDEA登录账户报错:Certificate used to sign the license is not signed by JetBrains root certificate