RTLinux和RTOS基本知识

1 HW RTOS
1.1 HW RTOS
RTOS为了实时性,一般都支持中断嵌套,例如FreeRTOS和QNX,但是非实时的ARM Linux不支持中断嵌套,参考本文2.4节。换句话说,强调高优先级中断的确定性时延,那么RTOS一定要支持中断嵌套。

RTOS够不够硬只有一个指标:就是最大关中断时间。RTEMS比μC/OS-II硬,因为μC/OS-II上下文切换的时候必须关中断,而RTEMS上下文切换的时候是开着中断的。

[15th-May-2022]
HW RTOS was designed by Renesas in 2012. HW RTOS module integrates 125MHz ARM Cortex-M3, refer to RZ/N1D, RZ/N1S, RZ/N1L datasheet.
CPU scheduler offload.
TCBs: 0x40080000 - 0x40088000, 32KB
Semaphores + Mutex: 0x40088000 - 0x40088400, 1KB
Interrupt Manager: 0x40088800 - 0x40088C00, 1KB
μC/OS‑III supports HW RTOS feature.

1.2 Linux实时性优化
[21th-May-2022]
首先画一个坐标图,横坐标表示执行的时间,纵坐标表示进程优先级。

硬件中断具有最高优先级,由于Linux内核不支持中断嵌套,所以Linux中的所有中断可以看作具有同一个优先级,中断之下的次优先级是rt_priority = 99的实时线程。

根据这个图可以知道,如果最高优先级的中断中有一个异常,譬如touch或者APL xHCI LTSSM或者SA8155 stmmac Rx overflow因为故障有大量的中断产生,那么就导致rt_priority = 99的实时线程watchdog不能被实时调度,watchdog超时后而导致kernel重启。

2 SoC中断
2.1 ARMv8中断
IPI:inter-processer interrupt 中断号0 - 15
PPI:per processor interrupts 中断号16 - 31
SPI:shared processor interrupts 中断号 32 - 224
SGI:software generated interrupts (SGI)
设备树是用来描述硬件信息的,因此里面不涉及软件中断SGI,在arm-gic.h文件中定义的只有SPI和PPI。
#define GIC_SPI 0
#define GIC_PPI 1

一般设备树中的中断都是SPI,那么interrupts = <0 208 1>是什么意思呢?
interrupts = <X Y Z>
X:GIC_SPI或者GIC_PPI
Y:物理中断号 - 32,SA8155
Z:触发方式
1 = low-to-high edge triggered
2 = high-to-low edge triggered (invalid for SPIs)
4 = active high level-sensitive
8 = active low level-sensitive (invalid for SPIs)

HCR_EL2: Hypervisor Configuration Register, Trapping and emulation就需要配置该寄存器

2.2 临界区开关CPU中断API
arm:local_irq_disable() / local_irq_enable() 在ARM V6以上使用汇编指令CPSID / CPSIE(Current Program Status Interrupt Disable / Enable)用于快速的开关中断,早期版本使用汇编指令mrs和msr去更新cpsr。

x86:local_irq_disable调用汇编指令CLI(clear interrupt-enable flag,IF);local_irq_enable调用汇编指令STI(set interrupt-enable flag,IF)。

arm的cpsid和x86的CLI同时禁止了核间中断(IPI),CPU-x还会用IPI通知CPU-y进行resched,但是CPU-y可能已经禁用了中断而不会响应。

在中断中不能产生调度,在中断返回时才可能发生调度。事实上,早期的内核很大程度上是依赖local_irq_disable来做资源保护,这个看看2.4的内核源码就很清楚了,里面有大量的对local_irq_disable函数的直接调用。

2.3 Linux Kernel中断处理
request_threaded_irq() - 实时中断处理,比较好。

如果成功注册了一个中断(中断号为300,中断名字为oem),那么通过ps命令可以看到该线程
irq/300-oem

中断优化:
echo 1 > /proc/sys/kernel/sched_boost

2.4 ARM Linux不支持中断嵌套
[19th-May-2022]
当ARM处理器收到中断的时候,它进入中断模式,同时ARM处理器的CPSR(Current Program Status Register,arm64 PSTATE)寄存器的IRQ位会被硬件设置为屏蔽IRQ。
Linux内核会在如下2个时候重新开启CPSR对IRQ的响应:
1)从IRQ Handler返回中断底半部的SOFTIRQ
2)从IRQ Handler返回一个线程上下文
从1)可以看出,SOFTIRQ里面是可以响应中断的。

Before 2010, ARM Linux supported nested interrupt through IRQF_DISABLED, IRQF_DISABLED was removed after 2010.

3 Linux内存管理
3.1 free命令
swapoff -a && swapon -a

free -h
显示的cache是指disk cache,也即是磁盘文件在内存中的缓存。
1) Clear PageCache only
# sync; echo 1 > /proc/sys/vm/drop_caches

2) Clear dentries and inodes
# sync; echo 2 > /proc/sys/vm/drop_caches

3) Clear PageCache, dentries and inodes
# sync; echo 3 > /proc/sys/vm/drop_caches

3.2 栈空间
Linux查看修改线程默认栈空间大小(ulimit -s,单位KB),Linux默认是8MB。

3.2.1 kmalloc
用于kmalloc可分配的内存大小范围在32~131027(128k)字节,并且由于它用slab分配器来分配内存的,所以得到的内存大小可能比你申请的要大一些(它向上取2的N次幂整数)。而且如果开启了CONFIG_LARGE_ALLOCS选项,这个值可以更大,可以达到了32M。

3.2.2 malloc
malloc申请的空间大于128KB的话,使用mmap系统调用在stack 和 heap中间的区域(共享内存映射区域)进行虚拟内存分配,其大小应该就是栈底与heap顶之间的空间最大值。

此时mmap()使用MAP_ANONYMOUS,并且不关心文件描述符fd的值;通过strace跟踪进程可以看到大量的带有MAP_ANONYMOUS的mmap()。

dlopen isn't a system call, it's a library function in the libdl library. Only system calls show up in strace.
On Linux and on many other platforms (especially those that use the ELF format for executables), dlopen is implemented by opening the target library with open() and mapping it into memory with mmap(). mmap() is really the critical part here, it's what incorporates the library into the process' address space, so the CPU can execute its code. But you have to open() the file before you can mmap() it!

mmap vs read()/write()/lseek()

3.3 buddy and slab
Buddy APIs:alloc_pages()和__get_free_pages()等。

因为内存初始化的时间比分配和释放时间长好多,slab增加一个类似对象池的特性,slab会缓存已经被“释放”的对象,以便下次重用,不必再初始化。对象用该高速缓存结构kmem_cache描述。通过kmem_cache_create创建。虽然名为高速缓存,但是它不是硬件上的高速缓存,它只是主存上的区域,但是和硬件上的高速缓存高度相关。

3.4 ZONE_HIGHMEM
当内核空间大小是3GB – 4GB时,并不是所有的物理内存都是映射的,而是部分映射,需要时再动态将需要访问的物理内存映射到(3.896GB - 4GB)地址空间。使用CONFIG_HIGHMEM来配置。
vmalloc和kmalloc的区别:
- vmalloc分配的一般为高端内存,只有当内存不够的时候才分配低端内存;kmalloc从低端内存分配
- vmalloc分配的物理地址一般不连续,而kmalloc分配的物理地址连续,两者分配的虚拟地址都是连续的
- vmalloc分配的一般为大块内存,而kmalloc一般分配的为小块内存(不超过128k)

3.5 64位CPU地址空间布局
3.5.1 x86_64地址空间布局
查看物理和虚拟地址位数:/proc/cpuinfo
[19th-May-2022]
14nm Apollo Lake (Gen9, A39X0) was released in September 2016, and uses 40bit physical memory address bus. APL only supports LPDDR3.
- 64bit = 16MegaT
- 用户空间128T:0x0000,0000,0000,0000到0x0000,7fff,ffff,f000(最后12位不是fff,保留了一个页面)
- 内核空间128T:0xffff,8000,0000,0000到0xffff,ffff,ffff,ffff;注意:该地址前4个都是f,这是因为目前实际上只用了64位地址中的48位(高16位是没有用的)
- 从地址0x0000,7fff,ffff,ffff到0xffff,8000,0000,0000中间是一个巨大的空洞,是为以后的扩展预留的

3.5.2 ARM64地址空间布局
[19th-May-2022]
msm8909 is based on A7, it uses 32bit physical memory address bus.
Both 7nm SA8155 and SA8195 use 40bit physical memory address bus.
Samsung 8nm EA9 uses 36bit physical memory address bus.

4 Linux scheduler
4.1 time slice
SCHED_NORMAL time_slice =
    (int)((1 - priority / 140.0) x 290 + 0.5) + 10

time_slice range [10, 300] ms
scheduler_tick()

#include <sched.h>
int sched_rr_get_interval(pid_t pid,
    struct timespec *tp);
SCHED_RR = 100 ms

echo  5 > \
/proc/sys/kernel/sched_rr_timeslice_ms

4.2 ARM big.LITTLE
ARM的big.LITTLE架构的调度器经历了IKS(In Kernel Switcher)-> HMP/GTS(Global Task Scheduler)-> EAS(Energy Aware Scheduler,based on CFS)。

/proc/sys/kernel/sched_downmigrate
这个值是个百分比,任务需求相对cpu能力的百分比。降低此值将会阻止任务迁移到小核上,对性能有利。

/proc/sys/kernel/sched_upmigrate
这个值是个百分比,任务需求相对cpu能力的百分比。提高这个值将会阻止任务往大核迁移,有利于功耗,不利于性能。

echo 1 > /proc/sys/kernel/sched_boost

4.3 进程抢占
在任何情况下使用spin_lock_irq都是安全的。因为它既禁止本地中断,又禁止内核抢占。
spin_lock比spin_lock_irq速度快,但是它并不是任何情况下都是安全的。

举个例子:进程A中调用了spin_lock(&lock)然后进入临界区,此时来了一个中断(interrupt),该中断也运行在和进程A相同的CPU上,并且在该中断处理程序中恰巧也会spin_lock(&lock)试图获取同一个锁。由于是在同一个CPU上被中断,进程A会被设置为TASK_INTERRUPT状态,中断处理程序无法获得锁,会不停的忙等,由于进程A被设置为中断状态,schedule()进程调度就无法再调度进程A运行,这样就导致了死锁!

但是如果该中断处理程序运行在不同的CPU上就不会触发死锁。 因为在不同的CPU上出现中断不会导致进程A的状态被设为TASK_INTERRUPT,只是换出。当中断处理程序忙等被换出后,进程A还是有机会获得CPU,执行并退出临界区。

所以在使用spin_lock时要明确知道该锁不会在中断处理程序中使用。

4.4 select
epoll: CLOCK_MONOTONIC
select: CLOCK_MONOTONIC
so that if you sleep for 10 seconds, and after 5 seconds the system is suspended for an hour, then after it wakes up again the process keeps sleeping for another 5 seconds.
Linux中所有休眠的函数,如果可以被外界的signal所打断,那么其会有一个返回值。

4.5 SA8155 disable cpuidle
i=0
while [ $i -le 7 ]; do
    echo 1 > /sys/devices/system/cpu/cpu$i/cpuidle/state0/disable
    echo 1 > /sys/devices/system/cpu/cpu$i/cpuidle/state1/disable
    i=$((i + 1))
done

5 RTLinux
5.1 prio和rt_priority的区别
- 实时进程的优先级(rt_priority)数字越大则优先级越高,99最高,0最低;而普通进程正好相反,优先级(static_prio)数字越大则优先级越低,100最高,139最低(对应nice值-20 ~ 19)
- 内核调度是按照task_struct中的prio来调度的,prio的值越小,优先级就越高。实时线程的rt_priority转换成prio:prio = MAX_RT_PRIO - 1 - p->rt_priority;普通线程的static_prio转换成prio:prio = static_prio = MAX_RT_PRIO + nice + 20
- 进程创建时的默认优先级是120,对应的nice值为0

5.2 RT-Preempt Patch for Linux kernel
PREEMPT_RT was originally called the Sleeping Spinlocks Patch.
1) Making in-kernel locking-primitives (using spinlocks) preemptible though reimplementation with rtmutexes.
2) Critical sections protected by i.e. spinlock_t and rwlock_t are now preemptible. The creation of non-preemptible sections (in kernel) is still possible with raw_spinlock_t (same APIs like spinlock_t).
3) Implementing priority inheritance for in-kernel spinlocks and semaphores. For more information on priority inversion and priority inheritance please consult Introduction to Priority Inversion.
4) Converting interrupt handlers into preemptible kernel threads: The RT-Preempt patch treats soft interrupt handlers in kernel thread context, which is represented by a task_struct like a common userspace process. However it is also possible to register an IRQ in kernel context.
5) Converting the old Linux timer API into separate infrastructures for high resolution kernel timers plus one for timeouts, leading to userspace POSIX timers with high resolution.

Indicates if the RT Patch is applied.
cat /sys/kernel/realtime

5.3 Linux schedule policy
# For priority, refer to 5.1 of
# RTLinux和RTOS基本知识
# policy
# 0: SCHED_OTHER
# 1: SCHED_FIFO
# 2: SCHED_RR, RTOS scheduler
pid=1
while [ $pid -le 10000 ]; do
    if [ -f /proc/$pid/comm ]; then
        name=$(cat /proc/$pid/comm)
        policy=$(cat \
            /proc/$pid/task/$pid/sched |\
            grep policy)
        prio=$(cat \
            /proc/$pid/task/$pid/sched |\
            grep prio)
        # switch str to list
        list=(${policy})
        # get the policy
        po_str=${list[2]}
        # switch str to list
        list=(${prio})
        # get the priority
        prio_str=${list[2]}
        if [ "$po_str" = "1" ]; then
            echo "$pid $po_str $prio_str $name"
        elif [ "$po_str" = "2" ]; then
            echo "$pid $po_str $prio_str $name"
        fi
    fi
    pid=$((pid + 1))
done

​​​​​​​5.4 aarch64 cyclictest
zcat /proc/config.gz

rt-tests.git
# Linaro build
# CROSS_COMPILE = \
# /path/to/bin/aarch64-linux-gnu-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld

time unit: micro seconds
./cyclictest -p 80 -t 5 -n

6 STM32中断
6.1 STM32中断编号
CMSIS IRQn = NVIC IRQn - 16
1)NVIC IRQn从1开始,所以NVIC中断1(Reset异常)对应CMSIS中断编号-15,NVIC中断16对应CMSIS中断编号0。
2)NVIC IRQn of SysTick等于15。
3)NVIC IRQn of PendSV等于14。

STM32的中断服务程序的名字不能自定义,必须使用官方已经定义好的名字,名字可参考如下的文件。
Drivers\CMSIS\Device\ST\STM32L0xx\Source\Templates\iar\startup_stm32l061xx.s
当然服务程序的具体内容还是自己写,放在stm32f10x_it.c里。

6.2 BASEPRI
FreeRTOS中进入临界区时没有关闭所有中断,而是使用优先级屏蔽寄存器BASEPRI(= configMAX_SYSCALL_INTERRUPT_PRIORITY)关闭了部分中断;这个寄存器最多有9位(由表达优先级的位数决定)。它定义了被屏蔽优先级的阈值。当它被设成某个值后,所有优先级号大于等于此值的中断都被关(优先级号越大,优先级越低)。但若被设成0,则不关闭任何中断,0也是缺省值。

FreeRTOS任务代码中临界段的进入和退出主要是通过操作寄存器BASEPRI实现的。进入临界区BASEPRI关闭了所有大于等于宏定义configMAX_SYSCALL_INTERRUPT_PRIORITY所定义的中断优先级,这样临界段代码就不会被中断干扰到,而且实现任务切换功能的 PendSV 中断和SysTick滴答定时器中断是最低优先级中断,所以此任务在执行临界段代码期间是不会被其它高优先级任务打断的。退出临界段时重新操作BASEPRI寄存器,即打开被关闭的中断(这里我们不考虑不受FreeRTOS 管理的更高优先级中断)。

Cortex-M内核的“中断优先级寄存器”是以最高位(MSB)对齐的。STM32使用了优先级寄存器中的4位,则这4个位位于中断优先级寄存器的bit 4、bit5、bit6、bit7位。剩余的bit0 ~ bit3可以设置成任何值。所以FreeRTOS中的中断优先级计算是有移位操作的。

CMSIS以及不同的微控制器供应商提供了可以设置某个中断优先级的库函数。一些库函数的参数使用最低位对齐,另一些库函数的参数可能使用最高位对齐,所以,使用时应该查阅库函数的应用手册进行正确设置。

可以在FreeRTOSConfig.h中设置宏configMAX_SYSCALL_INTERRUPT_PRIORITY和configKERNEL_INTERRUPT_PRIORITY的值。(关于这两个宏可以参考参数设置一章,网址:http://openmcu.net/post/kernel-config.html)。这两个宏需要根据Cortex-M内核自身的情况进行设置,要以最高有效位对齐。比如某MCU使用中断优先级寄存器中的4位,设置configKERNEL_INTERRUPT_PRIORITY的值为5,则代码为:
#define configKERNEL_INTERRUPT_PRIORITY (5<<(8-4))

对于每一个官方FreeRTOS演示例程,这也是在FreeRTOSConfig.h中要设置宏configKERNEL_INTERRUPT_PRIORITY为最低优先级时,为什么要将它设置为255(1111 1111B)的原因。使用这种方式指定这个值的原因是:FreeRTOS内核是直接在Cortex-M内核硬件上运行的(没有使用第三方接口库函数),要比大多数库函数先运行。现在也有开发第一个Cortex-M库函数计划。

6.3 IPR
typedefstruct
{
    vu32 ISER[2];
    u32 RESERVED0[30];
    vu32 ICER[2];
    u32 RSERVED1[30];
    vu32 ISPR[2];
    u32 RSERVED2[30];
    vu32 ICPR[2];
    u32 RSERVED3[30];
    vu32 IABR[2];
    u32 RSERVED4[30];
    vu32 IPR[15];
} NVIC_TypeDef;

NVIC IPR[15]:Interrupt Priority Registers,中断优先级控制寄存器组。STM32的中断分组与这个寄存器密切相关。因为STM32的中断多达60多个,所以STM32采用中断分组的办法来确定中断的优先级。IPR寄存器由15个32bit的寄存器组成,每个可屏蔽中断占8bit,这样总共可以表示15x4=60个可屏蔽中断。IPR[0]的[31:24],[23:16],[15:8],[7:0]分别对应中断3到0,总共对应60个外部中断。而每个可屏蔽中断占用的8bit并没有全部使用,只用了高4位。这4位又分为抢占优先级和子优先级。这两个优先级要根据SCB->AIRCR(System Control Block,Application Interrupt and Reset Register)中断分组的设置来决定。

简单介绍STM32的中断分组:STM32将中断分为0~4共5个组,该组是由SCB->AIRCR寄存器的bit10:8来定义的。具体优先级的确定和嵌套规则:
(1)只能高抢先优先级的中断可以打断低抢占优先级的中断服务,构成中断嵌套;
(2)当2个(N个)相同抢占优先级的中断出现,他们之间不能构成中断嵌套,但STM32首先响应子优先级高的中断;
(3)当2个(N个)个抢占优先级和子优先级相同的中断出现,STM32首先响应中断通道所对应的中断向量地址低的中断,就是谁先发生谁先被执行。

6.4 SHPRx - System Handler Priority Registers
SHPR1至SHPR3,3个32位寄存器,每8位设置一个中断优先级,共12个可配置的系统中断,8为里面用了高位configPRIO_BITS,其它位写无效,读为0。还有3个中断的优先级系统默认为-3、-2、-1。

6.5 示例代码
/* interrupt priority register */
static int command_dump_ipr(cli_node_t *cmd,
    int argc, char **argv)
{
    const volatile uint8_t
        *const pcInterruptPriorityRegisters =
        (const volatile uint8_t * const)0xE000E3F0;
    uint8_t i;

    console_puts_lite(""CR_LF);
    console_puts_lite(
        "configPRIO_BITS = %d"CR_LF,
        configPRIO_BITS);
    console_puts_lite(
        "configKERNEL_INTERRUPT_PRIORITY = 0x%02x"CR_LF,
        configKERNEL_INTERRUPT_PRIORITY);
    console_puts_lite(
        "configMAX_SYSCALL_INTERRUPT_PRIORITY = 0x%02x"CR_LF,
        configMAX_SYSCALL_INTERRUPT_PRIORITY);
    console_puts_lite(""CR_LF);

    /* (4-7, 8-11, 12-15) */
    console_puts_lite(
        "System Handler Priority Registers"CR_LF);
    for (i = 0; i < 12; i++) {
        console_puts_lite(
            "PRI_%d - 0x%02x"CR_LF,
            (4 + i),
            SCB->SHP[i]);
    }
    console_puts_lite(""CR_LF);

    console_puts_lite(
        "User Interrupt Priority Registers"CR_LF);
    for (i = 16;
        i < (16 + IRQ_NUMBER_MAX);
        i++) {
        console_puts_lite(
            "IRQ%d - 0x%02x"CR_LF,
            (i - 16),
            pcInterruptPriorityRegisters[i]);
    }
    return 0;
}
DECLARE_CONSOLE_COMMAND(
    dump_ipr,
    command_dump_ipr,
    NULL);

6.6 PendSV
PendSV是Pendable SerVice的缩写。STM32中,将中断及状态控制寄存器ICSR(Interrupt control and state register)的第28位置1,即可手动触发PendSV异常。

6.7 中断延迟测量
[10th-May-2022]
利用GPIO模块来测量Cortex-M的中断延迟是最简单的方法,选择两个GPIO,一个配置为输入GPIO_IN,另一个配置为上拉输出GPIO_OUT,初态设为高,开启GPIO_IN的下降沿中断,在GPIO_IN边沿中断ISR里翻转两次GPIO_OUT,然后用示波器测量两个GPIO信号下降沿间隔得出中断延迟时间。
设GPIO_IN下降沿到GPIO_OUT下降沿的时间为t1,GPIO_OUT低电平时间为t2,则中断延时等于t1 - t2。

7 FreeRTOS优先级反转
7.1 优先级反转
优先级反转是指一个低优先级的任务持有一个被高优先级任务所需要的共享资源。高优先任务由于因资源缺乏而处于受阻状态,一直等到低优先级任务释放资源为止。而低优先级获得的CPU时间少,如果此时有优先级处于两者之间的任务,并且不需要那个共享资源,则该中优先级的任务反而超过这两个任务而获得CPU时间。如果高优先级等待资源时不是阻塞等待,而是忙循环,则可能永远无法获得资源,因为此时低优先级进程无法与高优先级进程争夺CPU时间,从而无法执行,进而无法释放资源,造成的后果就是高优先级任务无法获得资源而继续推进。

7.2 解决方案
(1)设置优先级上限,给临界区一个高优先级,进入临界区的进程都将获得这个高优先级,如果其他试图进入临界区的进程的优先级都低于这个高优先级,那么优先级反转就不会发生。

eCos优先级上限(ceiling)例子:
packages/kernel/v3_0/src/sync/mutex.cxx
cyg_bool
Cyg_Mutex::lock(void)
{
    [...]
}

void
Cyg_Mutex::unlock(void)
{
    [...]
}

(2)优先级继承,当一个高优先级进程等待一个低优先级进程持有的资源时,低优先级进程将暂时获得高优先级进程的优先级别,在释放共享资源后,低优先级进程回到原来的优先级别。嵌入式系统FreeRTOS和VxWorks就是采用这种策略。

eCos优先级继承例子:
packages/kernel/v3_0/src/sync/mutex.cxx
cyg_bool
Cyg_Mutex::lock(void)
{
    [...]
}

void
Cyg_Mutex::unlock(void)
{
    [...]
}

FreeRTOS优先级继承例子:
tasks.c
vTaskPriorityInherit() - 需要mutex的高优先级Task,发现mutex被低优先级的Task持有。调整持有mutex的Task优先级等于当前等待mutex的Task优先级,这样持有mutex的低优先级Task获得了运行机会。
xTaskPriorityDisinherit() - 返回原来的优先级

(3)第三种方法就是使用中断禁止,通过禁止中断来保护临界区,采用此种策略的系统只有两种优先级:可抢占优先级和中断禁止优先级。前者为一般进程运行时的优先级,后者为运行于临界区的优先级。火星探路者正是由于在临界区中运行的气象任务被中断发生的通信任务所抢占才导致故障,如果有临界区的禁止中断保护,此一问题也不会发生。

8 Abbreviations
ARM CM4 BASEPRI:优先级屏蔽寄存器最多有9位(由表达优先级的位数决定)。它定义了被屏蔽优先级的阈值。当它被设成某个值后,所有优先级号大于等于此值的中断都被关(优先级号越大,优先级越低)。但若被设成0,则不关闭任何中断,0也是缺省值。FreeRTOS进入临界区时BASEPRI的值等于configMAX_SYSCALL_INTERRUPT_PRIORITY
BFS:Brain Fuck Scheduler,又称脑残调度器
CM4 R13:for MSP & PSP,the tasks are using the PSP(Process Stack Pointer), while the interrupts are using the MSP(Main Stack Pointer)
CMSIS:Cortex-Microcontroller Software Interface Standard
NVIC:Nested Vectors Interrupts Controller
NVIC IPR:Interrupt Priority Registers
PendSV:Pendable 服务是一个中断请求,如果没有其他中断需要响应时,系统将强制执行上下文切换
pi_waiters:priority inheritance,优先级继承
SVCall:SuperVisor Call由SVC指令触发,FreeRTOS用它来启动任务调度
SCHED_RR:Round-Robin,轮流调度算法(实时调度策略)
SHPRx:CM4 System Handler Priority Registers
STM32 AIRC:Application Interrupt and Reset Register
TIF_NEED_RESCHED:Thread Info Flag
Bionic brk():break(堆顶端称作program break)
intercepting:拦截系统调用
ptrace:process trace
pt_regs:ptrace registers(对应命令PTRACE_GETREGS)
strace:system call trace

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值