Explorar o código

Merge pull request #18 from mysterywolf/master

add English version
朱天龙 (Armink) %!s(int64=5) %!d(string=hai) anos
pai
achega
e6c2ed4665

+ 28 - 38
README.md

@@ -1,61 +1,51 @@
-# kernel samples
+# kernel samples package
 
-## 1、介绍
+## 1. Introduction
 
-这个软件包包含了内核相关的使用示例代码。
-
-### 1.1 例程说明
+This package contains sample code related to the RT-Thread kernel.
 
 | 文件 | 说明 |
 | ---- | ---- |
-| dynmem_sample.c | 动态堆内存的使用 |
-| event_sample.c  | 事件的使用 |
-| idlehook_sample.c  | 空闲任务钩子的使用 |
-| interrupt_sample.c | 使用开关中断进行线程间同步 |
-| mailbox_sample.c | 邮箱的使用 |
-| memp_sample.c  | 内存池的使用 |
-| msgq_sample.c | 消息队列的使用 |
-| mutex_sample.c  | 互斥量的使用 |
-| priority_inversion.c | 互斥量解决优先级翻转问题 |
-| producer_consumer.c | 生产者消费者模型 |
-| scheduler_hook.c | 调度器钩子的使用 |
-| semaphore_sample.c | 信号量的使用|
-| signal_sample.c  | 信号的使用 |
-| thread_sample.c | 线程的使用 |
-| timer_sample.c  | 定时器的使用 |
-| timeslice_sample.c  | 线程时间片 |
-
-### 1.2 许可证
-
-kernel samples package 遵循 Apache license v2.0 许可,详见 `LICENSE` 文件。
+| dynmem_sample.c | dynamic memory allocation & management |
+| event_sample.c  | event |
+| idlehook_sample.c  | idle thread hook function |
+| interrupt_sample.c | disable / enable interrupt |
+| mailbox_sample.c | mailbox |
+| memp_sample.c  | memory pool |
+| msgq_sample.c | message queue |
+| mutex_sample.c  | mutex |
+| priority_inversion.c | prevent priority inversions |
+| producer_consumer.c | producer & consumer problem |
+| scheduler_hook.c | scheduler hook function |
+| semaphore_sample.c | semaphore |
+| signal_sample.c  | signal |
+| thread_sample.c | thread |
+| timer_sample.c  | timer |
+| timeslice_sample.c  | time-slicing |
 
-### 1.3 依赖
 
-依赖系统内核对应的模块。
 
-## 2、如何打开 kernel samples
+## 2. How to use kernel samples package
 
-使用 kernel samples package 需要在 RT-Thread 的 menuconfig 配置菜单中选择它,具体路径如下:
+You can use [ENV tool](https://www.rt-thread.io/download.html?download=Env) or [RT-Studio IDE](https://www.rt-thread.io/studio.html) to activate this package:
 
 ```
 RT-Thread online packages
     miscellaneous packages --->
         samples: kernel and components samples --->
             a kernel_samples package for rt-thread --->
-
 ```
 
-然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。
 
-## 3、使用 kernel samples
 
-在打开 kernel samples package 后,当进行 BSP 编译时,选择的软件包相关源代码会被加入到 BSP 工程中进行编译。
+## 3. License
+
+This package is an open source software and has been licensed under Apache License Version 2.0.
 
-## 4、注意事项
 
-暂无。
 
-## 5、联系方式 & 感谢
+## 4. Maintained by
 
-* 维护:yangjie11
-* 主页:https://github.com/RT-Thread-packages/kernel-sample.git
+* Yang Jie: https://github.com/yangjie11
+* Meco Man:  https://github.com/mysterywolf
+* https://github.com/RT-Thread-packages/kernel-sample

+ 61 - 0
README_zh.md

@@ -0,0 +1,61 @@
+# kernel samples
+
+## 1、介绍
+
+这个软件包包含了内核相关的使用示例代码。
+
+### 1.1 例程说明
+
+| 文件 | 说明 |
+| ---- | ---- |
+| dynmem_sample.c | 动态堆内存的使用 |
+| event_sample.c  | 事件的使用 |
+| idlehook_sample.c  | 空闲任务钩子的使用 |
+| interrupt_sample.c | 使用开关中断进行线程间同步 |
+| mailbox_sample.c | 邮箱的使用 |
+| memp_sample.c  | 内存池的使用 |
+| msgq_sample.c | 消息队列的使用 |
+| mutex_sample.c  | 互斥量的使用 |
+| priority_inversion.c | 互斥量解决优先级翻转问题 |
+| producer_consumer.c | 生产者消费者模型 |
+| scheduler_hook.c | 调度器钩子的使用 |
+| semaphore_sample.c | 信号量的使用|
+| signal_sample.c  | 信号的使用 |
+| thread_sample.c | 线程的使用 |
+| timer_sample.c  | 定时器的使用 |
+| timeslice_sample.c  | 线程时间片 |
+
+### 1.2 许可证
+
+kernel samples package 遵循 Apache license v2.0 许可,详见 `LICENSE` 文件。
+
+### 1.3 依赖
+
+依赖系统内核对应的模块。
+
+## 2、如何打开 kernel samples
+
+使用 kernel samples package 需要在 RT-Thread 的 menuconfig 配置菜单中选择它,具体路径如下:
+
+```
+RT-Thread online packages
+    miscellaneous packages --->
+        samples: kernel and components samples --->
+            a kernel_samples package for rt-thread --->
+
+```
+
+然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。
+
+## 3、使用 kernel samples
+
+在打开 kernel samples package 后,当进行 BSP 编译时,选择的软件包相关源代码会被加入到 BSP 工程中进行编译。
+
+## 4、注意事项
+
+暂无。
+
+## 5、联系方式 & 感谢
+
+* 维护:yangjie11
+* 主页:https://github.com/RT-Thread-packages/kernel-sample.git

+ 11 - 54
SConscript

@@ -1,58 +1,15 @@
+import os
 from building import *
 
-src   = []
-cwd   = GetCurrentDir()
-include_path = [cwd]
+# get current dir path
+cwd = GetCurrentDir()
 
-# add kernel samples.
-if GetDepend('KERNEL_SAMPLES_USING_THREAD'):
-    src += ['thread_sample.c']
+# traversal subscript
+objs = []
+list = os.listdir(cwd)
+for d in list:
+    path = os.path.join(cwd, d)
+    if os.path.isfile(os.path.join(path, 'SConscript')):
+        objs = objs + SConscript(os.path.join(d, 'SConscript'))
 
-if GetDepend('KERNEL_SAMPLES_USING_SEMAPHORE'):
-    src += ['semaphore_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_MUTEX'):
-    src += ['mutex_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_MAILBOX'):
-    src += ['mailbox_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_EVENT'):
-    src += ['event_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_MESSAGEQUEUE'):
-    src += ['msgq_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_TIMER'):
-    src += ['timer_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_HEAP'):
-    src += ['dynmem_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_MEMPOOL'):
-    src += ['memp_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_IDLEHOOK'):
-    src += ['idlehook_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_SIGNAL'):
-    src += ['signal_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_INTERRUPT'):
-    src += ['interrupt_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_PRI_INVERSION'):
-    src += ['priority_inversion.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_TIME_SLICE'):
-    src += ['timeslice_sample.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_SCHEDULER_HOOK'):
-    src += ['scheduler_hook.c']
-
-if GetDepend('KERNEL_SAMPLES_USING_PRODUCER_CONSUMER'):
-    src += ['producer_consumer.c']
-
-group = DefineGroup('kernel-samples', src, depend = ['PKG_USING_KERNEL_SAMPLES'], CPPPATH = include_path)
-
-Return('group')
+Return('objs')

+ 58 - 0
en/SConscript

@@ -0,0 +1,58 @@
+from building import *
+
+src   = []
+cwd   = GetCurrentDir()
+include_path = [cwd]
+
+# add kernel samples.
+if GetDepend('KERNEL_SAMPLES_USING_THREAD'):
+    src += ['thread_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_SEMAPHORE'):
+    src += ['semaphore_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MUTEX'):
+    src += ['mutex_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MAILBOX'):
+    src += ['mailbox_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_EVENT'):
+    src += ['event_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MESSAGEQUEUE'):
+    src += ['msgq_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_TIMER'):
+    src += ['timer_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_HEAP'):
+    src += ['dynmem_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MEMPOOL'):
+    src += ['memp_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_IDLEHOOK'):
+    src += ['idlehook_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_SIGNAL'):
+    src += ['signal_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_INTERRUPT'):
+    src += ['interrupt_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_PRI_INVERSION'):
+    src += ['priority_inversion.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_TIME_SLICE'):
+    src += ['timeslice_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_SCHEDULER_HOOK'):
+    src += ['scheduler_hook.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_PRODUCER_CONSUMER'):
+    src += ['producer_consumer.c']
+
+group = DefineGroup('kernel-samples', src, depend = ['PKG_USING_KERNEL_SAMPLES_EN'], CPPPATH = include_path)
+
+Return('group')

+ 73 - 0
en/dynmem_sample.c

@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: dynamic memory management
+ * 
+ * This demo creates a dynamic thread to allocate and free memory.
+ * Each time it allocates more memory, and it will end when it can't allocate any memory.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/memory/memory/#memory-management
+ */
+
+#include <rtthread.h>
+
+#define THREAD_PRIORITY      25
+#define THREAD_STACK_SIZE    512
+#define THREAD_TIMESLICE     5
+
+/* thread #1 entry function*/
+void thread1_entry(void *parameter)
+{
+    int i;
+    char *ptr = RT_NULL; /* memory's pointer */
+
+    for (i = 0; ; i++)
+    {
+        /* allocate memory of (1 << i) bytes  */
+        ptr = rt_malloc(1 << i);
+        
+        if (ptr != RT_NULL) 
+        {
+            /* if memory allocated successfully */
+            rt_kprintf("get memory :%d byte\n", (1 << i));
+            rt_free(ptr); /* free memory */
+            rt_kprintf("free memory :%d byte\n", (1 << i));
+            ptr = RT_NULL;
+        }
+        else
+        {
+            rt_kprintf("try to get %d byte memory failed!\n", (1 << i));
+            return;
+        }
+    }
+}
+
+int dynmem_sample(void)
+{
+    rt_thread_t tid = RT_NULL;
+
+    /* create thread #1 */
+    tid = rt_thread_create("thread1",
+                           thread1_entry, RT_NULL,
+                           THREAD_STACK_SIZE,
+                           THREAD_PRIORITY,
+                           THREAD_TIMESLICE);
+    /*start thread #1 */
+    if (tid != RT_NULL)
+        rt_thread_startup(tid); 
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(dynmem_sample, dynmem sample);

+ 128 - 0
en/event_sample.c

@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: event(s)
+ *
+ * This demo creates two threads and one statical event:
+ *    1) thread #1: pend and receive events
+ *    2) thread #2: sent events (Event3 and Event5)
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-sync/thread-sync/#event
+ */
+
+#include <rtthread.h>
+
+#define THREAD_PRIORITY      9
+#define THREAD_TIMESLICE     5
+
+#define EVENT_FLAG3 (1 << 3)
+#define EVENT_FLAG5 (1 << 5)
+
+/* ECB (Event Control Block) */
+static struct rt_event event;
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread1_stack[1024]; /* thread stack 1024 Byte*/
+static struct rt_thread thread1; /* TCB (Thread Control Block) */
+
+/* thread #1 entry function */
+static void thread1_recv_event(void *param)
+{
+    rt_uint32_t e;
+
+    /* 
+        first time to receive event(s):
+        EITHER Event3 OR Event5 happened can resume thread1
+        and then clear conrresponding event(s)' flag
+    */
+    if (rt_event_recv(&event, (EVENT_FLAG3 | EVENT_FLAG5),
+                      RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
+                      RT_WAITING_FOREVER, &e) == RT_EOK)
+    {
+        rt_kprintf("thread1: OR recv event 0x%x\n", e);
+    }
+
+    rt_kprintf("thread1: delay 1s to prepare the second event\n");
+    rt_thread_mdelay(1000);
+
+    /*
+        second time to receive event(s):
+        BOTH Event3 AND Event5 happened can resume thread1
+        and then clear conrresponding event(s)' flag 
+    */
+    if (rt_event_recv(&event, (EVENT_FLAG3 | EVENT_FLAG5),
+                      RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
+                      RT_WAITING_FOREVER, &e) == RT_EOK)
+    {
+        rt_kprintf("thread1: AND recv event 0x%x\n", e);
+    }
+    rt_kprintf("thread1 leave.\n");
+}
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread2_stack[1024]; /* thread stack 1024 Byte*/
+static struct rt_thread thread2; /* TCB (Thread Control Block) */
+
+/* thread #2 entry function */
+static void thread2_send_event(void *param)
+{
+    rt_kprintf("thread2: send event3\n");
+    rt_event_send(&event, EVENT_FLAG3);
+    rt_thread_mdelay(200);
+
+    rt_kprintf("thread2: send event5\n");
+    rt_event_send(&event, EVENT_FLAG5);
+    rt_thread_mdelay(200);
+
+    rt_kprintf("thread2: send event3\n");
+    rt_event_send(&event, EVENT_FLAG3);
+    rt_kprintf("thread2 leave.\n");
+}
+
+int event_sample(void)
+{
+    rt_err_t result;
+
+    /* initiate the event (statically) */
+    result = rt_event_init(&event, "event", RT_IPC_FLAG_FIFO);
+    if (result != RT_EOK)
+    {
+        rt_kprintf("init event failed.\n");
+        return -1;
+    }
+
+    /* initiate the thread #1 (statically) */
+    rt_thread_init(&thread1,
+                   "thread1",
+                   thread1_recv_event,
+                   RT_NULL,
+                   &thread1_stack[0],
+                   sizeof(thread1_stack),
+                   THREAD_PRIORITY - 1, THREAD_TIMESLICE);
+    rt_thread_startup(&thread1); /* start thread #1 */
+
+    /* initiate the thread #2 (statically) */
+    rt_thread_init(&thread2,
+                   "thread2",
+                   thread2_send_event,
+                   RT_NULL,
+                   &thread2_stack[0],
+                   sizeof(thread2_stack),
+                   THREAD_PRIORITY, THREAD_TIMESLICE);
+    rt_thread_startup(&thread2); /* start thread #2 */
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(event_sample, event sample);

+ 87 - 0
en/idlehook_sample.c

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: idle hook
+ *
+ * This demo creates a thread and set an idle thread hook function. The idle
+ * thread hook function will be invoked when thread #1 is delaying.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread/thread/#set-and-delete-idle-hooks
+ *    https://www.rt-thread.io/document/site/thread/thread/#idle-thread
+ */
+
+#include <rtthread.h>
+
+#define THREAD_PRIORITY      20
+#define THREAD_STACK_SIZE    1024
+#define THREAD_TIMESLICE     5
+
+/* thread handler */
+static rt_thread_t tid = RT_NULL;
+
+/* idle thread hook function running number of times */
+volatile static int hook_times = 0;
+
+/* idle thread hook function */
+static void idle_hook()
+{
+    if (0 == (hook_times % 10000))
+    {
+        rt_kprintf("enter idle hook %d times.\n", hook_times);
+    }
+
+    rt_enter_critical();
+    hook_times++;
+    rt_exit_critical();
+}
+
+/* thread entry function */
+static void thread_entry(void *parameter)
+{
+    int i = 5;
+    while (i--)
+    {
+        rt_kprintf("enter thread1.\n");
+        rt_enter_critical();
+        hook_times = 0;
+        rt_exit_critical();
+
+        /* sleep for 500ms */
+        rt_kprintf("thread1 delay 500ms.\n");
+        rt_thread_mdelay(500);
+    }
+    rt_kprintf("delete idle hook.\n");
+
+    /* remove idle thread hook function */
+    rt_thread_idle_delhook(idle_hook);
+    rt_kprintf("thread1 finish.\n");
+}
+
+int idle_hook_sample(void)
+{
+    /* set idle thread hook function */
+    rt_thread_idle_sethook(idle_hook);
+
+    /* create thread #1 */
+    tid = rt_thread_create("thread1",
+                           thread_entry, RT_NULL,
+                           THREAD_STACK_SIZE,
+                           THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (tid != RT_NULL)
+        rt_thread_startup(tid);
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(idle_hook_sample, idle hook sample);

+ 77 - 0
en/interrupt_sample.c

@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: interrupt
+ *
+ * This demo demonstrates how to disable and enable interrupt to access global variable.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/interrupt/interrupt/
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#define THREAD_PRIORITY      20
+#define THREAD_STACK_SIZE    512
+#define THREAD_TIMESLICE     5
+
+/* global variable */
+static volatile rt_uint32_t cnt;
+
+/* thread entry function */
+/* threads #1 and #2 share one entry, but the entry parameter is different */
+static void thread_entry(void *parameter)
+{
+    rt_uint32_t no;
+    rt_uint32_t level;
+
+    no = (rt_uint32_t) parameter;
+    
+    while (1)
+    {
+        /* disable interrupt */
+        level = rt_hw_interrupt_disable();
+        
+        cnt += no; /* critical sections (or critical region) */
+        
+        /* enable interrupt */
+        rt_hw_interrupt_enable(level);
+
+        rt_kprintf("protect thread[%d]'s counter is %d\n", no, cnt);
+        rt_thread_mdelay(no * 10);
+    }
+}
+
+int interrupt_sample(void)
+{
+    rt_thread_t thread;
+
+    /* create thread #1 */
+    thread = rt_thread_create("thread1", thread_entry, (void *)10,
+                              THREAD_STACK_SIZE,
+                              THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (thread != RT_NULL)
+        rt_thread_startup(thread); /* start thread #1 */
+
+    /* create thread #2 */
+    thread = rt_thread_create("thread2", thread_entry, (void *)20,
+                              THREAD_STACK_SIZE,
+                              THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (thread != RT_NULL)
+        rt_thread_startup(thread); /* start thread #2 */
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(interrupt_sample, interrupt sample);

+ 140 - 0
en/mailbox_sample.c

@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: 
+ *
+ * This demo creates two threads and one boxmail (static):
+ *    1) thread #1: receive mails 
+ *    2) thread #2: send mails
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-comm/thread-comm/#mailbox
+ */
+ 
+#include <rtthread.h>
+
+#define THREAD_PRIORITY      10
+#define THREAD_TIMESLICE     5
+
+/* mailbox control block */
+static struct rt_mailbox mb;
+
+/* memory pool for mails storage */
+static char mb_pool[128];
+
+static char mb_str1[] = "I'm a mail!";
+static char mb_str2[] = "this is another mail!";
+static char mb_str3[] = "over";
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread1_stack[1024];
+static struct rt_thread thread1;
+
+/* thread #1 entry function */
+static void thread1_entry(void *parameter)
+{
+    char *str;
+
+    while (1)
+    {
+        rt_kprintf("thread1: try to recv a mail\n");
+
+        /* pend and receive mail(s) from mailbox */
+        if (rt_mb_recv(&mb, (rt_ubase_t *)&str, RT_WAITING_FOREVER) == RT_EOK)
+        {
+            rt_kprintf("thread1: get a mail from mailbox, the content:%s\n", str);
+            if (str == mb_str3)
+                break;
+
+            /* delay for 100ms */
+            rt_thread_mdelay(100);
+        }
+    }
+    /* detach mailbox */
+    rt_mb_detach(&mb);
+}
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread2_stack[1024];
+static struct rt_thread thread2;
+
+/* thread #2 entry function */
+static void thread2_entry(void *parameter)
+{
+    rt_uint8_t count;
+
+    count = 0;
+    while (count < 10)
+    {
+        count ++;
+        if (count & 0x1)
+        {
+            /* send the 'mb_str1' variable's address to the mailbox */
+            rt_mb_send(&mb, (rt_uint32_t)&mb_str1);
+        }
+        else
+        {
+            /* send the 'mb_str2' variable's address to the mailbox */
+            rt_mb_send(&mb, (rt_uint32_t)&mb_str2);
+        }
+
+        /* delay for 200ms */
+        rt_thread_mdelay(200);
+    }
+
+    /* send the 'mb_str3' variable's address to the mailbox */
+    /* to inform thread #1 that thread #2 has finished running */
+    rt_mb_send(&mb, (rt_uint32_t)&mb_str3);
+}
+
+/* mailbox(s) demo */
+int mailbox_sample(void)
+{
+    rt_err_t result;
+
+    /* initiate a mailbox */
+    result = rt_mb_init(&mb,
+                        "mbt",
+                        &mb_pool[0],
+                        sizeof(mb_pool) / sizeof(rt_ubase_t), /* size of mails */
+                        RT_IPC_FLAG_FIFO); 
+    if (result != RT_EOK)
+    {
+        rt_kprintf("init mailbox failed.\n");
+        return -1;
+    }
+
+    /* initiate thread #1 */
+    rt_thread_init(&thread1,
+                   "thread1",
+                   thread1_entry,
+                   RT_NULL,
+                   &thread1_stack[0],
+                   sizeof(thread1_stack),
+                   THREAD_PRIORITY, THREAD_TIMESLICE);
+    rt_thread_startup(&thread1); /* start thread #1 */
+
+    /*initiate thread #2 */
+    rt_thread_init(&thread2,
+                   "thread2",
+                   thread2_entry,
+                   RT_NULL,
+                   &thread2_stack[0],
+                   sizeof(thread2_stack),
+                   THREAD_PRIORITY, THREAD_TIMESLICE);
+    rt_thread_startup(&thread2); /* start thread #2 */
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(mailbox_sample, mailbox sample);

+ 97 - 0
en/memp_sample.c

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+ 
+/*
+ * Demo: memory pool
+ *
+ * This demo creates one memory pool and two threads:
+ *   1) thread #1: allocate memory pool
+ *   2) thread #2: free memory pool
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/memory/memory/#memory-pool
+ */
+ 
+#include <rtthread.h>
+
+static rt_uint8_t *ptr[50];
+static rt_uint8_t mempool[4096];
+static struct rt_mempool mp;
+
+#define THREAD_PRIORITY      25
+#define THREAD_STACK_SIZE    512
+#define THREAD_TIMESLICE     5
+
+/* thread handler */
+static rt_thread_t tid1 = RT_NULL;
+static rt_thread_t tid2 = RT_NULL;
+
+/* thread #1 entry function */
+static void thread1_mp_alloc(void *parameter)
+{
+    int i;
+    for (i = 0 ; i < 50 ; i++)
+    {
+        if (ptr[i] == RT_NULL)
+        {
+            /* allocate memory from the memory pool */
+            ptr[i] = rt_mp_alloc(&mp, RT_WAITING_FOREVER);
+            if (ptr[i] != RT_NULL)
+                rt_kprintf("allocate No.%d\n", i);
+        }
+    }
+}
+
+/* thread #2 entry function */
+static void thread2_mp_release(void *parameter)
+{
+    int i;
+
+    rt_kprintf("thread2 try to release block\n");
+    for (i = 0; i < 50 ; i++)
+    {
+        /* free all memory */
+        if (ptr[i] != RT_NULL)
+        {
+            rt_kprintf("release block %d\n", i);
+            rt_mp_free(ptr[i]);
+            ptr[i] = RT_NULL;
+        }
+    }
+}
+
+int mempool_sample(void)
+{
+    int i;
+    for (i = 0; i < 50; i ++) ptr[i] = RT_NULL;
+
+    /* initiate memory pool */
+    rt_mp_init(&mp, "mp1", &mempool[0], sizeof(mempool), 80);
+
+    /* create thread #1 */
+    tid1 = rt_thread_create("thread1", thread1_mp_alloc, RT_NULL,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (tid1 != RT_NULL)
+        rt_thread_startup(tid1); /* start thread #1 */
+
+    /* create thread #2 */
+    tid2 = rt_thread_create("thread2", thread2_mp_release, RT_NULL,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (tid2 != RT_NULL)
+        rt_thread_startup(tid2); /* start thread #2 */
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(mempool_sample, mempool sample);

+ 153 - 0
en/msgq_sample.c

@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: message queue 
+ *
+ * This demo creates two threads and one message queue:
+ *    1) thread #1: receive message(s) from message queue
+ *    2) thread #2: send normal and urgent messages to message queue
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-comm/thread-comm/#message-queue
+ */
+
+#include <rtthread.h>
+
+#define THREAD_PRIORITY      25
+#define THREAD_TIMESLICE     5
+
+/* message queue control block */
+static struct rt_messagequeue mq;
+/* the memory pool used to place messages in the message queue */
+static rt_uint8_t msg_pool[2048];
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread1_stack[1024];
+static struct rt_thread thread1;
+
+/* thread #1 entry function */
+static void thread1_entry(void *parameter)
+{
+    char buf = 0;
+    rt_uint8_t cnt = 0;
+
+    while (1)
+    {
+        /* pend and receive message(s) from message queue */
+        if (rt_mq_recv(&mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
+        {
+            rt_kprintf("thread1: recv msg from msg queue, the content:%c\n", buf);
+            if (cnt == 19)
+            {
+                break;
+            }
+        }
+        cnt++;
+        
+        /* delay for 50ms */
+        rt_thread_mdelay(50);
+    }
+    rt_kprintf("thread1: detach mq \n");
+    rt_mq_detach(&mq);
+}
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread2_stack[1024];
+static struct rt_thread thread2;
+
+/* thread #2 entry function */
+static void thread2_entry(void *parameter)
+{
+    int result;
+    char buf = 'A';
+    rt_uint8_t cnt = 0;
+
+    while (1)
+    {
+        if (cnt == 8)
+        {
+            /* send one URGENT message to the message queue */
+            result = rt_mq_urgent(&mq, &buf, 1);
+            if (result != RT_EOK)
+            {
+                rt_kprintf("rt_mq_urgent ERR\n");
+            }
+            else
+            {
+                rt_kprintf("thread2: send urgent message - %c\n", buf);
+            }
+        }
+        else if (cnt >= 20) /* exit */
+        {
+            rt_kprintf("message queue stop send, thread2 quit\n");
+            break;
+        }
+        else
+        {
+            /* send one message to the message queue */
+            result = rt_mq_send(&mq, &buf, 1);
+            if (result != RT_EOK)
+            {
+                rt_kprintf("rt_mq_send ERR\n");
+            }
+
+            rt_kprintf("thread2: send message - %c\n", buf);
+        }
+        buf++;
+        cnt++;
+        
+        /* delay for 5ms */
+        rt_thread_mdelay(5);
+    }
+}
+
+int msgq_sample(void)
+{
+    rt_err_t result;
+
+    /* initiate a message queue */
+    result = rt_mq_init(&mq,
+                        "mqt",
+                        &msg_pool[0],               /* msg_pool's address */
+                        1,                          /* the size of each message is 1 byte */
+                        sizeof(msg_pool),           /* The size of the memory pool is the size of msg_pool */
+                        RT_IPC_FLAG_FIFO);
+
+    if (result != RT_EOK)
+    {
+        rt_kprintf("init message queue failed.\n");
+        return -1;
+    }
+
+    rt_thread_init(&thread1,
+                   "thread1",
+                   thread1_entry,
+                   RT_NULL,
+                   &thread1_stack[0],
+                   sizeof(thread1_stack),
+                   THREAD_PRIORITY, THREAD_TIMESLICE);
+    rt_thread_startup(&thread1);
+
+    rt_thread_init(&thread2,
+                   "thread2",
+                   thread2_entry,
+                   RT_NULL,
+                   &thread2_stack[0],
+                   sizeof(thread2_stack),
+                   THREAD_PRIORITY, THREAD_TIMESLICE);
+    rt_thread_startup(&thread2);
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(msgq_sample, msgq sample);

+ 107 - 0
en/mutex_sample.c

@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: mutex(es)
+ *
+ * This demo demonstrates how the mutex manage the shared resource.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-sync/thread-sync/#mutex
+ */
+ 
+#include <rtthread.h>
+
+#define THREAD_PRIORITY         8
+#define THREAD_TIMESLICE        5
+
+/* mutex handler */
+static rt_mutex_t dynamic_mutex = RT_NULL;
+static rt_uint8_t number1, number2 = 0;
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread1_stack[1024];
+static struct rt_thread thread1;
+static void rt_thread_entry1(void *parameter)
+{
+    while (1)
+    {
+        /* pending the mutex */
+        rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
+        
+        /* protect and deal with public variables */
+        number1++;
+        rt_thread_mdelay(10);
+        number2++;
+        
+        /* release the mutex */
+        rt_mutex_release(dynamic_mutex);
+    }
+}
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread2_stack[1024];
+static struct rt_thread thread2;
+static void rt_thread_entry2(void *parameter)
+{
+    while (1)
+    {
+        rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
+        if (number1 != number2)
+        {
+            rt_kprintf("not protect.number1 = %d, mumber2 = %d \n", number1, number2);
+        }
+        else
+        {
+            rt_kprintf("mutex protect ,number1 = mumber2 is %d\n", number1);
+        }
+
+        number1++;
+        number2++;
+        rt_mutex_release(dynamic_mutex);
+
+        if (number1 >= 50)
+            return;
+    }
+}
+
+int mutex_sample(void)
+{
+    /* create mutex */
+    dynamic_mutex = rt_mutex_create("dmutex", RT_IPC_FLAG_FIFO);
+    if (dynamic_mutex == RT_NULL)
+    {
+        rt_kprintf("create dynamic mutex failed.\n");
+        return -1;
+    }
+
+    rt_thread_init(&thread1,
+                   "thread1",
+                   rt_thread_entry1,
+                   RT_NULL,
+                   &thread1_stack[0],
+                   sizeof(thread1_stack),
+                   THREAD_PRIORITY, THREAD_TIMESLICE);
+    rt_thread_startup(&thread1);
+
+    rt_thread_init(&thread2,
+                   "thread2",
+                   rt_thread_entry2,
+                   RT_NULL,
+                   &thread2_stack[0],
+                   sizeof(thread2_stack),
+                   THREAD_PRIORITY - 1, THREAD_TIMESLICE);
+    rt_thread_startup(&thread2);
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(mutex_sample, mutex sample);

+ 146 - 0
en/priority_inversion.c

@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: prevent priority inversions
+ * 
+ * This demo creates 3 threads and 1 mutex to
+ * demonstrate how the mutex prevents priority inversions.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-sync/thread-sync/#mutex
+ */
+ 
+#include <rtthread.h>
+
+/* thread(s) handler */
+static rt_thread_t tid1 = RT_NULL;
+static rt_thread_t tid2 = RT_NULL;
+static rt_thread_t tid3 = RT_NULL;
+static rt_mutex_t mutex = RT_NULL;
+
+#define THREAD_PRIORITY       10
+#define THREAD_STACK_SIZE     512
+#define THREAD_TIMESLICE      5
+
+/* thread #1 entry function */
+static void thread1_entry(void *parameter)
+{
+    /* let the lower priority thread run first */
+    rt_thread_mdelay(100);
+
+    /* at this point, thread #3 holds the mutex and thread #2 is pending on holding the mutex */
+    
+    /* check the priority level of thread #2 and thread #3 */
+    if (tid2->current_priority != tid3->current_priority)
+    {
+        /* failure */
+        rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
+        rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
+        rt_kprintf("test failed.\n");
+        return;
+    }
+    else
+    {
+        rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
+        rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
+        rt_kprintf("test OK.\n");
+    }
+}
+
+/* thread #2 entry function */
+static void thread2_entry(void *parameter)
+{
+    rt_err_t result;
+
+    rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
+
+    /* let the lower priority thread run first */
+    rt_thread_mdelay(50);
+
+    /* 
+     * pending the mutex
+     * At this time, kernel raises the priority of thread #3 to same priority 
+     * as thread #2 
+     */
+    result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
+
+    if (result == RT_EOK)
+    {
+        /* release the mutex */
+        rt_mutex_release(mutex);
+    }
+}
+
+/* thread #3 entry function */
+static void thread3_entry(void *parameter)
+{
+    rt_tick_t tick;
+    rt_err_t result;
+
+    rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
+
+    result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
+    if (result != RT_EOK)
+    {
+        rt_kprintf("thread3 take a mutex, failed.\n");
+    }
+
+    /* delay for 500ms without scheduling */
+    tick = rt_tick_get();
+    while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2)) ;
+
+    /* release the mutex */
+    rt_mutex_release(mutex);
+}
+
+int pri_inversion(void)
+{
+    /* create mutex */
+    mutex = rt_mutex_create("mutex", RT_IPC_FLAG_FIFO);
+    if (mutex == RT_NULL)
+    {
+        rt_kprintf("create dynamic mutex failed.\n");
+        return -1;
+    }
+
+    /* create thread #1 */
+    tid1 = rt_thread_create("thread1",
+                            thread1_entry,
+                            RT_NULL,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY - 1, THREAD_TIMESLICE);
+    if (tid1 != RT_NULL)
+        rt_thread_startup(tid1);
+
+    /* create thread #2 */
+    tid2 = rt_thread_create("thread2",
+                            thread2_entry,
+                            RT_NULL,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (tid2 != RT_NULL)
+        rt_thread_startup(tid2);
+
+    /* create thread #3 */
+    tid3 = rt_thread_create("thread3",
+                            thread3_entry,
+                            RT_NULL,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (tid3 != RT_NULL)
+        rt_thread_startup(tid3);
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(pri_inversion, pri_inversion sample);

+ 128 - 0
en/producer_consumer.c

@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: producer-consumer problem (or bounded-buffer problem)
+ *
+ * this demo creates two threads to demonstrate producer-consumer problem:
+ *     1) producer thread: adds 1 to the variable "cnt" and stores it into the array.
+ *     2) consumer thread: prints out the value and adds it up
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-sync/thread-sync/#semaphores
+ */
+ 
+#include <rtthread.h>
+
+#define THREAD_PRIORITY       6
+#define THREAD_STACK_SIZE     512
+#define THREAD_TIMESLICE      5
+
+/* define the maximum 5 elements can be produced */
+#define MAXSEM 5
+
+rt_uint32_t array[MAXSEM];
+
+/* the pointers of producer and consumer's position in the array */
+static rt_uint32_t set, get;
+
+/* thread handler */
+static rt_thread_t producer_tid = RT_NULL;
+static rt_thread_t consumer_tid = RT_NULL;
+
+struct rt_semaphore sem_lock;
+struct rt_semaphore sem_empty, sem_full;
+
+/* producer thread entry function */
+void producer_thread_entry(void *parameter)
+{
+    int cnt = 0;
+
+    while (cnt < 10)
+    {
+        /* get a "empty" mark */
+        rt_sem_take(&sem_empty, RT_WAITING_FOREVER);
+
+        /* protect the critial section */
+        rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
+        array[set % MAXSEM] = cnt + 1;
+        rt_kprintf("the producer generates a number: %d\n", array[set % MAXSEM]);
+        set++;
+        rt_sem_release(&sem_lock);
+
+        /* release a "full" mark */
+        rt_sem_release(&sem_full);
+        cnt++;
+
+        rt_thread_mdelay(20);
+    }
+
+    rt_kprintf("the producer exit!\n");
+}
+
+/* consumer thread entry function */
+void consumer_thread_entry(void *parameter)
+{
+    rt_uint32_t sum = 0;
+
+    while (1)
+    {
+        /* get a "full" mark */
+        rt_sem_take(&sem_full, RT_WAITING_FOREVER);
+
+        /* protect the critial section */
+        rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
+        sum += array[get % MAXSEM];
+        rt_kprintf("the consumer[%d] get a number: %d\n", (get % MAXSEM), array[get % MAXSEM]);
+        get++;
+        rt_sem_release(&sem_lock);
+
+        /* release a "empty" mark */
+        rt_sem_release(&sem_empty);
+
+        if (get == 10) break;
+
+        rt_thread_mdelay(50);
+    }
+
+    rt_kprintf("the consumer sum is: %d\n", sum);
+    rt_kprintf("the consumer exit!\n");
+}
+
+int producer_consumer(void)
+{
+    set = 0;
+    get = 0;
+
+    rt_sem_init(&sem_lock, "lock",     1,      RT_IPC_FLAG_FIFO);
+    rt_sem_init(&sem_empty, "empty",   MAXSEM, RT_IPC_FLAG_FIFO);
+    rt_sem_init(&sem_full, "full",     0,      RT_IPC_FLAG_FIFO);
+
+    producer_tid = rt_thread_create("producer",
+                                    producer_thread_entry, RT_NULL,
+                                    THREAD_STACK_SIZE,
+                                    THREAD_PRIORITY - 1, THREAD_TIMESLICE);
+    if (producer_tid != RT_NULL)
+        rt_thread_startup(producer_tid);
+
+    
+    consumer_tid = rt_thread_create("consumer",
+                                    consumer_thread_entry, RT_NULL,
+                                    THREAD_STACK_SIZE,
+                                    THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (consumer_tid != RT_NULL)
+        rt_thread_startup(consumer_tid);
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(producer_consumer, producer_consumer sample);

+ 75 - 0
en/scheduler_hook.c

@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: scheduler hook
+ *
+ * This demo sets a scheduler hook function and prints context-switching information.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread/thread/#set-the-scheduler-hook 
+ */
+
+#include <rtthread.h>
+
+#define THREAD_STACK_SIZE   1024
+#define THREAD_PRIORITY     20
+#define THREAD_TIMESLICE    10
+
+/* counter for each thread */
+volatile rt_uint32_t count[2];
+
+/* thread entry function */
+/* threads #1 and #2 share one entry, but the entry parameter is different */
+static void thread_entry(void *parameter)
+{
+    rt_uint32_t value;
+
+    value = (rt_uint32_t)parameter;
+    while (1)
+    {
+        rt_kprintf("thread %d is running\n", value);
+        rt_thread_mdelay(1000);
+    }
+}
+
+/* thread(s) handler */
+static rt_thread_t tid1 = RT_NULL;
+static rt_thread_t tid2 = RT_NULL;
+
+static void hook_of_scheduler(struct rt_thread *from, struct rt_thread *to)
+{
+    rt_kprintf("from: %s -->  to: %s \n", from->name, to->name);
+}
+
+int scheduler_hook(void)
+{
+    /* set a scheduler hook function */
+    rt_scheduler_sethook(hook_of_scheduler);
+
+    tid1 = rt_thread_create("thread1",
+                            thread_entry, (void *)1,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (tid1 != RT_NULL)
+        rt_thread_startup(tid1);
+
+    tid2 = rt_thread_create("thread2",
+                            thread_entry, (void *)2,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY, THREAD_TIMESLICE - 5);
+    if (tid2 != RT_NULL)
+        rt_thread_startup(tid2);
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(scheduler_hook, scheduler_hook sample);

+ 116 - 0
en/semaphore_sample.c

@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: semaphore
+ * This demo creates one semaphore and two threads:
+ *    1) thread #1: release the semaphore
+ *    2) thread #2: receive the semaphore
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-sync/thread-sync/#semaphores
+ */
+ 
+#include <rtthread.h>
+
+#define THREAD_PRIORITY         25
+#define THREAD_TIMESLICE        5
+
+/* semaphore handler */
+static rt_sem_t dynamic_sem = RT_NULL;
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread1_stack[1024];
+static struct rt_thread thread1;
+static void rt_thread1_entry(void *parameter)
+{
+    static rt_uint8_t count = 0;
+
+    while (1)
+    {
+        if (count <= 100)
+        {
+            count++;
+        }
+        else
+            return;
+
+        /* count release semaphore every 10 counts */
+        if (0 == (count % 10))
+        {
+            rt_kprintf("thread1 release a dynamic semaphore.\n");
+            rt_sem_release(dynamic_sem);
+        }
+    }
+}
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread2_stack[1024];
+static struct rt_thread thread2;
+static void rt_thread2_entry(void *parameter)
+{
+    static rt_err_t result;
+    static rt_uint8_t number = 0;
+    while (1)
+    {
+        /* permanently wait for the semaphore; once obtain the semaphore, perform the number self-add operation */
+        result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER);
+        if (result != RT_EOK)
+        {
+            rt_kprintf("thread2 take a dynamic semaphore, failed.\n");
+            rt_sem_delete(dynamic_sem);
+            return;
+        }
+        else
+        {
+            number++;
+            rt_kprintf("thread2 take a dynamic semaphore. number = %d\n", number);
+        }
+    }
+}
+
+int semaphore_sample()
+{
+    /* create semaphtore and its initial value is 0 */
+    dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO);
+    if (dynamic_sem == RT_NULL)
+    {
+        rt_kprintf("create dynamic semaphore failed.\n");
+        return -1;
+    }
+    else
+    {
+        rt_kprintf("create done. dynamic semaphore value = 0.\n");
+    }
+
+    rt_thread_init(&thread1,
+                   "thread1",
+                   rt_thread1_entry,
+                   RT_NULL,
+                   &thread1_stack[0],
+                   sizeof(thread1_stack),
+                   THREAD_PRIORITY, THREAD_TIMESLICE);
+    rt_thread_startup(&thread1);
+
+    rt_thread_init(&thread2,
+                   "thread2",
+                   rt_thread2_entry,
+                   RT_NULL,
+                   &thread2_stack[0],
+                   sizeof(thread2_stack),
+                   THREAD_PRIORITY - 1, THREAD_TIMESLICE);
+    rt_thread_startup(&thread2);
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(semaphore_sample, semaphore sample);

+ 75 - 0
en/signal_sample.c

@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: signal
+ *
+ * This demo creates one thread. When the signal is installed, the signal 
+ * processing mode is set to custom processing. The processing function of 
+ * the signal is defined to be thread1_signal_handler(). After the thread is 
+ * running and the signal is installed, a signal is sent to this thread. 
+ * This thread will receive the signal and print the message.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread-comm/thread-comm/#signal
+ */
+ 
+#include <rtthread.h>
+
+#define THREAD_PRIORITY         25
+#define THREAD_STACK_SIZE       512
+#define THREAD_TIMESLICE        5
+
+static rt_thread_t tid1 = RT_NULL;
+
+/* callback function of thread #1's signal */
+void thread1_signal_handler(int sig)
+{
+    rt_kprintf("thread1 received signal %d\n", sig);
+}
+
+/* thread #1 entry function */
+static void thread1_entry(void *parameter)
+{
+    int cnt = 0;
+
+    /* install signal*/
+    rt_signal_install(SIGUSR1, thread1_signal_handler);
+    rt_signal_unmask(SIGUSR1);
+
+    while (cnt < 10)
+    {
+        rt_kprintf("thread1 count : %d\n", cnt);
+        cnt++;
+        rt_thread_mdelay(100);
+    }
+}
+
+int signal_sample(void)
+{
+    tid1 = rt_thread_create("thread1",
+                            thread1_entry, RT_NULL,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY, THREAD_TIMESLICE);
+
+    if (tid1 != RT_NULL)
+        rt_thread_startup(tid1);
+
+    rt_thread_mdelay(300);
+
+    /* send the signal "SIGUSR1" to thread #1 */
+    rt_thread_kill(tid1, SIGUSR1);
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(signal_sample, signal sample);

+ 92 - 0
en/thread_sample.c

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/* 
+ * Demo: thread(s)
+ *
+ * This demo creates two threads: 
+ *    1) create thread #1 dynamically, and delete automatically when the thread #1 finished;
+ *    2) create thread #2 statically, and print counting numbers continuously.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread/thread/
+ */
+ 
+#include <rtthread.h>
+
+#define THREAD_PRIORITY         25
+#define THREAD_STACK_SIZE       512
+#define THREAD_TIMESLICE        5
+
+/* thread handler */
+static rt_thread_t tid1 = RT_NULL;
+
+/* thread #1 entry function */
+static void thread1_entry(void *parameter)
+{
+    rt_uint32_t count = 0;
+
+    while (1)
+    {
+        /* thread #1 occupies low priority and prints counting numbers continuously */
+        rt_kprintf("thread1 count: %d\n", count ++);
+        rt_thread_mdelay(500);
+    }
+}
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread2_stack[1024];
+static struct rt_thread thread2;
+
+/* thread #2 entry function */
+static void thread2_entry(void *param)
+{
+    rt_uint32_t count = 0;
+
+    /* thread #2 occupies higher priority than that of thread #1 */
+    for (count = 0; count < 10 ; count++)
+    {
+        /* thread #2 prints counting numbers */
+        rt_kprintf("thread2 count: %d\n", count);
+    }
+    rt_kprintf("thread2 exit\n");
+
+    /* RT-Thread allows thread entry function to return directly */
+    /* thread #2 will be deleted automatically by idle thread once it finishes */
+}
+
+int thread_sample(void)
+{
+    /* create thread #1 dynamically */
+    tid1 = rt_thread_create("thread1",
+                            thread1_entry, RT_NULL,
+                            THREAD_STACK_SIZE,
+                            THREAD_PRIORITY, THREAD_TIMESLICE);
+
+    /* start thread #1 */
+    if (tid1 != RT_NULL)
+        rt_thread_startup(tid1);
+
+    /* create thread #2 statically */
+    rt_thread_init(&thread2,
+                   "thread2",
+                   thread2_entry,
+                   RT_NULL,
+                   &thread2_stack[0],
+                   sizeof(thread2_stack),
+                   THREAD_PRIORITY - 1, THREAD_TIMESLICE);
+    rt_thread_startup(&thread2); /* start thread #2 */
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(thread_sample, thread sample);

+ 72 - 0
en/timer_sample.c

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: timer(s)
+ *
+ * This demo creates two dynamic timers:
+ *    1) timer #1: one-shot mode timer
+ *    2) timer #2: periodic mode timer
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/timer/timer/#timer-management
+ */
+
+#include <rtthread.h>
+
+/* timer handle */
+static rt_timer_t timer1;
+static rt_timer_t timer2;
+static int cnt = 0;
+
+/* timer #1 timeout callback function */
+static void timeout1(void *parameter)
+{
+    rt_kprintf("periodic timer is timeout %d\n", cnt);
+
+    if (cnt++ >= 9)
+    {
+        rt_timer_stop(timer1);
+        rt_kprintf("periodic timer was stopped! \n");
+    }
+}
+
+/* timer #2 timeout callback function */
+static void timeout2(void *parameter)
+{
+    rt_kprintf("one shot timer is timeout\n");
+}
+
+int timer_sample(void)
+{
+    /* create timer #1, periodic mode */
+    timer1 = rt_timer_create("timer1", timeout1,
+                             RT_NULL, 10,
+                             RT_TIMER_FLAG_PERIODIC);
+
+    /* start timer #1 */
+    if (timer1 != RT_NULL)
+        rt_timer_start(timer1);
+
+    /* create timer #2, one-shot mode */
+    timer2 = rt_timer_create("timer2", timeout2,
+                             RT_NULL,  30,
+                             RT_TIMER_FLAG_ONE_SHOT);
+
+    /* start timer #2 */
+    if (timer2 != RT_NULL)
+        rt_timer_start(timer2);
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(timer_sample, timer sample);

+ 72 - 0
en/timeslice_sample.c

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: Time-Slicing (or Round-Robin Scheduling)
+ * 
+ * This demo creates two threads to show how Time-Slicing works.
+ *
+ * read more:
+ *    https://www.rt-thread.io/document/site/thread/thread/#time-slice
+ */
+
+#include <rtthread.h>
+
+#define THREAD_STACK_SIZE   1024
+#define THREAD_PRIORITY     20
+#define THREAD_TIMESLICE    10
+
+/* thread entry function */
+/* threads #1 and #2 share one entry, but the entry parameter is different */
+static void thread_entry(void *parameter)
+{
+    rt_uint32_t value;
+    rt_uint32_t count = 0;
+
+    value = (rt_uint32_t)parameter;
+    while (1)
+    {
+        if (0 == (count % 5))
+        {
+            rt_kprintf("thread %d is running ,thread %d count = %d\n", value, value, count);
+
+            if (count > 200)
+                return;
+        }
+        count++;
+    }
+}
+
+int timeslice_sample(void)
+{
+    rt_thread_t tid = RT_NULL; /* thread handle */
+    
+    /* create thread #1 */
+    tid = rt_thread_create("thread1",
+                           thread_entry, (void *)1,
+                           THREAD_STACK_SIZE,
+                           THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (tid != RT_NULL)
+        rt_thread_startup(tid); /* start thread #1 */
+
+    /* create thread #2 */
+    tid = rt_thread_create("thread2",
+                           thread_entry, (void *)2,
+                           THREAD_STACK_SIZE,
+                           THREAD_PRIORITY, THREAD_TIMESLICE - 5);
+    if (tid != RT_NULL)
+        rt_thread_startup(tid); /* start thread #2 */
+
+    return 0;
+}
+
+/* export the msh command */
+MSH_CMD_EXPORT(timeslice_sample, timeslice sample);

+ 58 - 0
zh/SConscript

@@ -0,0 +1,58 @@
+from building import *
+
+src   = []
+cwd   = GetCurrentDir()
+include_path = [cwd]
+
+# add kernel samples.
+if GetDepend('KERNEL_SAMPLES_USING_THREAD'):
+    src += ['thread_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_SEMAPHORE'):
+    src += ['semaphore_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MUTEX'):
+    src += ['mutex_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MAILBOX'):
+    src += ['mailbox_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_EVENT'):
+    src += ['event_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MESSAGEQUEUE'):
+    src += ['msgq_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_TIMER'):
+    src += ['timer_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_HEAP'):
+    src += ['dynmem_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_MEMPOOL'):
+    src += ['memp_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_IDLEHOOK'):
+    src += ['idlehook_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_SIGNAL'):
+    src += ['signal_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_INTERRUPT'):
+    src += ['interrupt_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_PRI_INVERSION'):
+    src += ['priority_inversion.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_TIME_SLICE'):
+    src += ['timeslice_sample.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_SCHEDULER_HOOK'):
+    src += ['scheduler_hook.c']
+
+if GetDepend('KERNEL_SAMPLES_USING_PRODUCER_CONSUMER'):
+    src += ['producer_consumer.c']
+
+group = DefineGroup('kernel-samples', src, depend = ['PKG_USING_KERNEL_SAMPLES_ZH'], CPPPATH = include_path)
+
+Return('group')

+ 0 - 0
dynmem_sample.c → zh/dynmem_sample.c


+ 0 - 0
event_sample.c → zh/event_sample.c


+ 0 - 0
idlehook_sample.c → zh/idlehook_sample.c


+ 0 - 0
interrupt_sample.c → zh/interrupt_sample.c


+ 0 - 0
mailbox_sample.c → zh/mailbox_sample.c


+ 0 - 0
memp_sample.c → zh/memp_sample.c


+ 0 - 0
msgq_sample.c → zh/msgq_sample.c


+ 0 - 0
mutex_sample.c → zh/mutex_sample.c


+ 0 - 0
priority_inversion.c → zh/priority_inversion.c


+ 0 - 0
producer_consumer.c → zh/producer_consumer.c


+ 0 - 0
scheduler_hook.c → zh/scheduler_hook.c


+ 0 - 0
semaphore_sample.c → zh/semaphore_sample.c


+ 0 - 0
signal_sample.c → zh/signal_sample.c


+ 0 - 0
thread_sample.c → zh/thread_sample.c


+ 0 - 0
timer_sample.c → zh/timer_sample.c


+ 0 - 0
timeslice_sample.c → zh/timeslice_sample.c