Try   HackMD

作業系統工程-Presentation

Table Of Content

tags: 作業系統工程 Operating System Programming note, 110-1, 2021


IPC application

  • 若在底部抓球時偵測到卡球的情況,透過增加步進馬達轉力,此時就能從下方推球。
    • By Signal
    • Signal
      • Operation of Signal
        • Image Not Showing Possible Reasons
          • The image file may be corrupted
          • The server hosting the image is unavailable
          • The image path is incorrect
          • The image format is not supported
          Learn More →
        • rt_signal_mask
        • 信號阻塞,也可以理解為屏蔽信號。
          若該信號被阻塞,則該信號將不會遞達給安裝此信號的線程,也不會引發 soft interrupt。
#include <rtthread.h> #define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 512 #define THREAD_TIMESLICE 5 static rt_thread_t tid1 = RT_NULL; // thread 1 的信號處裡函数 void thread1_signal_handler(int sig) { rt_kprintf("thread1 received signal %d\n", sig); return; } // kernal 中,在 signal.c 也有預設的 signal_handler // //static void _signal_default_handler(int signo) //{ // LOG_I("handled signo[%d] with default action.", signo); // return ; //} // // thread 1 的入口函数 static void thread1_entry(void *parameter) { int cnt = 0; // set up signal rt_signal_install(SIGUSR1, thread1_signal_handler); rt_signal_unmask(SIGUSR1); while(/*不斷的去偵測卡球的情況有沒有發生*/) { rt_thread_kill(tid2, SIGUSR1); // 若發現有卡球的情況發生,就發送信號 SIGUSR1 给 thread 2 去處理 } } /* thread 2 的入口函数 */ static void thread2_entry(void *parameter) { int cnt = 0; // set up signal rt_signal_install(SIGUSR1, thread1_signal_handler); rt_signal_unmask(SIGUSR1); /* 增加底部馬達的轉動力度 */ /// Code } int _sample(void) { // 產生thread 1 tid1 = rt_thread_create("thread1", thread1_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIO, THREAD_TIMESLICE); if (tid1 != RT_NULL) rt_thread_startup(tid1); // 產生thread 2 tid2 = rt_thread_create("thread2", thread2_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIO, THREAD_TIMESLICE); if (tid2 != RT_NULL) rt_thread_startup(tid2); return 0; } // 导出到 msh 命令列表中 MSH_CMD_EXPORT(signal_sample, signal sample);
  • 若偵測到的錯誤訊息不僅限於「在底部抓球時的卡球情況」,可用 mailbox 的 priority 方法將 error 放進 mailbox ,再針對他的 priority 進行各個處理。
    • By Mailbox
#include <rtthread.h> #define THREAD_PRIORITY 10 #define THREAD_TIMESLICE 5 static struct rt_mailbox mb; /* 用於放 mail 的 memory pool */ static char mb_pool[128]; static char mb_str1[] = "type 1 error"; static char mb_str2[] = "type 2 error"; static char mb_str3[] = "over"; ALIGN(RT_ALIGN_SIZE) static char thread1_stack[1024]; static struct rt_thread thread1; /* thread 1 入口 */ static void thread1_entry(void *parameter) { char *str; while (1) { rt_kprintf("thread1: try to recv a mail\n"); // 從 mailbox 中收 mail if (rt_mb_recv(&mb, (rt_uint32_t *)&str, RT_WAITING_FOREVER) == RT_EOK) { rt_kprintf("thread1: get a mail from mailbox, the content:%s\n", str); if (str == mb_str1) { // call 對應得 function 處理對應的 error } else if (str == mb_str2) { // call 對應得 function 處理對應的 error } else if (str == mb_str3) break; // delay 100ms rt_thread_mdelay(100); } } // 讓 mailbox 上的 object 脫離 rt_mb_detach(&mb); } ALIGN(RT_ALIGN_SIZE) static char thread2_stack[1024]; static struct rt_thread thread2; // thread 2 入口 // 負責發送 mail (各種 error type)到 mailbox rt_uint8_t _error_type; static void thread2_entry(void *parameter) { while (_error_type < 10) { _error_type ++; if (_error_type & 0x1) { /* 發送 mb_str1 地址到 mailbox 中 */ rt_mb_send(&mb, (rt_uint32_t)&mb_str1); } else { /* 發送 mb_str2 地址到 mailbox 中 */ rt_mb_send(&mb, (rt_uint32_t)&mb_str2); } /* delay 200ms */ rt_thread_mdelay(200); } // thread 3 代表運行結束的字串 // 發送 mail 告诉 thread 1,thread 2 已经運行结束 rt_mb_send(&mb, (rt_uint32_t)&mb_str3); } int mailbox_sample(void) { rt_err_t result; // 初始化 mailbox // 名稱是 mbt, mailbox 用到的 memory pool 是 mb_pool, mailbox 中的郵件數目,因为一封 mail 為 4 bytes, 用 PRIORITY 的方式做 processes waiting result = rt_mb_init(&mb, "mbt", &mb_pool[0], sizeof(mb_pool)/4, RT_IPC_FLAG_PRIO); if (result != RT_EOK) { rt_kprintf("init mailbox failed.\n"); return -1; } //初始化 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); //初始化 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); return 0; }

PWM application

int main(void) { /*int count = 1; while (count++) { LOG_D("Hello RT-Thread!"); rt_thread_mdelay(1000); }*/ rt_uint32_t period, pulse, dir; period = 500000; // 周期为0.5ms,单位为纳秒ns dir = 1; // PWM脉冲宽度值的增减方向 pulse = 0; // PWM脉冲宽度值,单位为纳秒ns // 找 device pwm_dev = (struct rt_device_pwm *) rt_device_find(PWM_DEV_NAME); if (pwm_dev == RT_NULL) { rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME); return RT_ERROR; } // 设置PWM周期和脉冲宽度默认值 rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse); // 使能设备 rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL); int count = 0; while (count < 10) { rt_thread_mdelay(1000); if (dir) { pulse += 5000; // 从0值开始每次增加5000ns } else { pulse -= 5000; // 从最大值开始每次减少5000ns } if (pulse >= period) { dir = 0; } if (0 == pulse) { dir = 1; } // 设置PWM周期和脉冲宽度 rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse); count++; } return RT_EOK; }

timer application

​​​​> RT-Thread 中,時鐘節拍的長度可以根據RT_TICK_PER_SECOND 的定義來調整,等於1/RT_TICK_PER_SECOND 秒。

clock application

​​​​> # Semaphone/ mutex application