RT-Thread简介
1.关键词
国产,嵌入式操作系统
RT-Thread:内核,网络,fs,gui
开发环境:MDK 5.14,stm32f103芯片数据
2.rt-thread启动
int $$Sub$$main()
{
rt_hw_interrupt_disable();
rthread_startup();
return 0;
}
rtthread_startup()
---rt_hw_board_init() 硬件平台初始化
---rt_show_version()
---rt_system_timer_init()
---rt_system_schduler_init()
---rt_system_signal_init()
---rt_application_init()
------rt_thread_create/rt_thread_init("main", main_thread_entry) 创建用户main
()执行线程
---rt_system_timer_thread_init()
---rt_thread_idle_init()
---rt_system_schduler_start() 启动调度器,系统开始执行起来
裸机启动:
SystemInit()=》Main()
linux启动:
bootloader:如u-boot,以svc模式,实模式启动,解决“无中生有”问题,没有什么
就建立临时的,反正后面内核还要更新数据。arm把默认的0x00000000作为reset入口
,初始化CP15,lowlevel_init=>(C代码)
_main:board_init_f,board_init_r=>main_loop=>boot_os[].
u-boot同样可以初始化需要的设备,驱动设备工作,所以u-boot就是一个在裸机上执
行的小系统,这点和SystemInit, RT-Thead的初始化类似。
内核启动step1:
此为汇编部分,编译时候定好了内核加载的物理地址,u-boot在do_bootm_linux中解
析images,得到内核image的入口地址赋值给*kernel_entry(0, machid, bootargs),
执行kernel_entry跳转,移交控制权限。
进入kenel入口,要求(arm)【1.mmu off; 2.D-cache off, I-Cache off; 3.
r0=0,r1=machine nr,r2=atages 、dtb pointer】
在第一阶段结束时使能mmu, __enable_mmu=>__turn_mmu_on, 跳转到r13存的地
址位置(r13之前加载的是__mmap_switched)=》__mmap_switched=》
start_kernel, 进入第二阶段
内核启动step2:
build_all_zonelists()
setup_log_buf()
trap_init()
mm_init()
sched_init()
init_IRQ()
init_timers()
softirq_init()
time_init()
perf_event_init()
profile_init()
anon_vma_init()
fork_init()
uts_ns_init()
cgroup_init()
acpi_subsystem_init()
arch_call_rest_init()
---rest_init()
------kernel_init, 内核第一线程
----------kernel_init_freeable,这里会等kthreadd创建,等待kthread_done发出才会
执行
-------------workqueue_init=》create_worker=》kthread_create_on_node
("kworker%s")
-------------do_basic_setup=》【driver_init();do_ctors();do_initcalls()】
----------run_init_process,用户空间第一个进程
------kthreadd,内核第二个线程
3. 动态内存分配
rt_system_heap_init(heap_begin, heap_end)
既可以使用空闲的片内空间,也可以使用片外ram
rt_malloc() rt_free()
rt_realloc() 改变原来申请分配的大小,重新分配
rt_calloc(count, size), 从内存堆中分配连续内存地址的多个内存块
4. 线程
RT-Thread的基本单位称线程,我理解对应于Linux的进程概念
线程组成:线程函数,线程控制块(struct rt_thread),线程堆栈
创建线程:
rt_thread_init(struct rt_thread*, name, void(*entry)(), stack_start, stack_size,
prio, tick) == 静态线程
rt_thread_create(name, void(*entry)(),stack_size, prio, tick) == 动态线程
rt_thread_startup()--将线程放到等待队列
Linux创建内核线程也分两个api
第一种方式:kernel_thread()=>_do_fork(), 内核在建立第一个好第二个内核线程是适
用这种方式
第二种方式:建立一个struct kthread_create_info create, 将create挂在
kthread_create_list这个全局链表,kthreadd会再运行时去按照链表一个个建立内核线
程,kthreadd最终还是调用kernel_thread()创建线程
5.线程状态
初始状态=》就绪状态=》运行状态=》挂起状态=》关闭状态
GPIO框架:
rt_pin_mode(pin, mode)
rt_pin_write(rt_base_t pin, value) PIN_HIGH PIN_LOW
rt_pin_read(pin)
rt_thread_delay(tick) rt_thread_mdelay(ms) rt_thread_sleep(tick)
线程栈大小设置:先设置大一点,然后list_thread查看使用率,使用率到底max的
70%~75%比较合适
6.时间调度
RT-Thread支持最大256个优先级, stm32默认支持32个优先级
优先级抢占调度
时间片轮训调度
Linux的调度
RT-Linux的调度
7.空闲线程、钩子函数
rt_thread_idle_sethook(void(*hook)(void)) == 钩子函数不能被挂起,因为idle一直
处于就绪态
rt_thread_idle_delhook(void(*hook)(void))
rt_scheduler_sethook(void(*hook)(sturct rt_thread *from, *to))
8 临界区保护
禁止调度 关中断 信号量 互斥量
禁止调度:
rt_enter_critical()
rt_exit_critical()
关中断
level = rt_hw_interrupt_disable()
rt_hw_interrupt_enable(level)
信号量:
rt_sem_init() rt_sem_detach()
rt_sem_create() rt_sem_delete()
rt_sem_take()/rt_sem_trytake() rt_sem_release
互斥量、互斥锁
rt_mutex_init() rt_mutex_detach()
rt_mutex_create rt_mutex_delete()
rt_mutex_take() rt_mutex_release()
9. 优先级翻转
优先级继承
10.事件集工作机制
用32bit无符号整型,一个bit代表一个事件,
逻辑或---独立型同步
逻辑与---关联型同步
struct rt_event {
struct rt_ips_object parent;
rt_unint32_t set;
}
rt_event_init() rt_event_detach()
rt_event_create() rt_event_delete()
rt_event_send()
rt_event_recv()
11. IPC机制邮箱
struct rt_mailbox
携带4字节内容,一个指针的大小
消息队列
12 定时器
HARD_TIMER 中断上下文
SOFTTIMER 系统timer线程上下文
struct rt_timer{}
13 内存池
内存管理方式
rt_mp_alooc(mp, time)