分享到plurk 分享到twitter 分享到facebook

版本 687b397d1f40624ffeb6dc9b3c253412ce72673d

nuttx

組員

  • 翁振育
  • 黃亮穎
  • 蘇偉嘉
  • 李英碩

hackpad : https://stm32f429.hackpad.com/NuttX–hqco2YSgAcJ

Nuttx 參考應用

  • PX4 autopilot<http://pixhawk.org/dev/nuttx/start>_

NuttX 架構

* 可混用task跟thread。 * 支援FPU。 * 可混用FIFO跟RR。

與平台相關

Run Nuttx on STM32F429-Disco

(1) 從 https://github.com/deadbeefcafe/nuttx-stm32f4disc-bb 複製Nuttx到workspace
(2) cd workspace/nuttx-stm32f4disc-bb/nuttx/tools
(3) ./configure.sh stm32f429i-disco/nsh
(4) cd ..
(5) make CROSSDEV=arm-none-eabi-
(6) st-flash write nuttx.bin 0x8000000
(7) sudo screen /dev/ttyUSB0 115200 8n1

設定相關應用程式與功能

at stm32f429i-disco/nsh/defconfig
120 CONFIG_ARCH_FPU=n
465 CONFIG_RTC=y
466 CONFIG_RTC_DATETIME=y
653 CONFIG_EXAMPLES_HELLO=y
676 CONFIG_EXAMPLES_OSTEST=y

Task Control Interfaces

  • task_create : 產生一個activates的新task,並回傳系統指派的pid
  • task_init : 將task的TCB初始化,但並不activate task
  • task_activate : activate task,否則scheduler沒辦法執行它
  • task_delete : 將task關掉,並deallocate它的TCB與stack
  • task_exit : 關掉目前在運行的task,不能在user mode被呼叫

Task state

include/nuttx/sched.h

.. code-block:: c

enum tstate_e { TSTATE_TASK_INVALID = 0, /* INVALID - The TCB is uninitialized / TSTATE_TASK_PENDING, / READY_TO_RUN - Pending preemption unlock / TSTATE_TASK_READYTORUN, / READY-TO-RUN - But not running / TSTATE_TASK_RUNNING, / READY_TO_RUN - And running / TSTATE_TASK_INACTIVE, / BLOCKED - Initialized but not yet activated / TSTATE_WAIT_SEM, / BLOCKED - Waiting for a semaphore / #ifndef CONFIG_DISABLE_SIGNALS TSTATE_WAIT_SIG, / BLOCKED - Waiting for a signal / #endif #ifndef CONFIG_DISABLE_MQUEUE TSTATE_WAIT_MQNOTEMPTY, / BLOCKED - Waiting for a MQ to become not empty. / TSTATE_WAIT_MQNOTFULL, / BLOCKED - Waiting for a MQ to become not full. / #endif #ifdef CONFIG_PAGING TSTATE_WAIT_PAGEFILL, / BLOCKED - Waiting for page fill / #endif NUM_TASK_STATES / Must be last */ };

Task list

sched/os_internal.h

.. code-block:: c

typedef struct tasklist_s tasklist_t;

extern volatile dq_queue_t g_pendingtasks; extern volatile dq_queue_t g_waitingforsemaphore; #ifndef CONFIG_DISABLE_SIGNALS extern volatile dq_queue_t g_waitingforsignal; #endif #ifndef CONFIG_DISABLE_MQUEUE extern volatile dq_queue_t g_waitingformqnotempty; #endif #ifndef CONFIG_DISABLE_MQUEUE extern volatile dq_queue_t g_waitingformqnotfull; #endif #ifdef CONFIG_PAGING extern volatile dq_queue_t g_waitingforfill; #endif extern volatile dq_queue_t g_inactivetasks; extern volatile sq_queue_t g_delayed_kufree; #if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) extern volatile sq_queue_t g_delayed_kfree; #endif extern volatile pid_t g_lastpid; extern pidhash_t g_pidhash[CONFIG_MAX_TASKS]; extern const tasklist_t g_tasklisttable[NUM_TASK_STATES];

TCB

include/nuttx/sched.h

.. code-block:: c

struct tcb_s { /* Fields used to support list management *************************************/ FAR struct tcb_s flink; / Doubly linked list / FAR struct tcb_s blink;

/* Task Management Fields *****************************************************/

pid_t pid; /* This is the ID of the thread */

start_t start; /* Thread start function / entry_t entry; / Entry Point into the thread / uint8_t sched_priority; / Current priority of the thread */

uint8_t task_state; /* Current state of the thread / uint16_t flags; / Misc. general status flags / int16_t lockcount; / 0=preemptable (not-locked) */

#if CONFIG_RR_INTERVAL > 0 int timeslice; /* RR timeslice interval remaining */ #endif

/* Stack-Related Fields *******************************************************/

#ifndef CONFIG_CUSTOM_STACK size_t adj_stack_size; /* Stack size after adjustment / / for hardware, processor, etc. / / (for debug purposes only) / FAR void stack_alloc_ptr; /* Pointer to allocated stack / / Need to deallocate stack / FAR void adj_stack_ptr; /* Adjusted stack_alloc_ptr for HW / / The initial stack pointer value */ #endif

/* POSIX Semaphore Control Fields *********************************************/

sem_t waitsem; / Semaphore ID waiting on */

/* POSIX Signal Control Fields ************************************************/

#ifndef CONFIG_DISABLE_SIGNALS sigset_t sigprocmask; /* Signals that are blocked / sigset_t sigwaitmask; / Waiting for pending signals / sq_queue_t sigactionq; / List of actions for signals / sq_queue_t sigpendactionq; / List of pending signal actions / sq_queue_t sigpostedq; / List of posted signals / siginfo_t sigunbinfo; / Signal info when task unblocked */ #endif

/* POSIX Named Message Queue Fields *******************************************/

#ifndef CONFIG_DISABLE_MQUEUE FAR msgq_t msgwaitq; / Waiting for this message queue */ #endif

/* The form and content of these fields are processor-specific. */

struct xcptcontext xcp; /* Interrupt register save area */

#if CONFIG_TASK_NAME_SIZE > 0 char name[CONFIG_TASK_NAME_SIZE]; /* Task name */ #endif : : : : : : };

Register

.. image:: /ARM_register.jpg

Communication

Scheduling

include/sys/types.h

.. code-block:: c

/* HPUX-like MIN/MAX value */

#define PRIOR_RR_MIN 0 #define PRIOR_RR_MAX 255 #define PRIOR_FIFO_MIN 0 #define PRIOR_FIFO_MAX 255 #define PRIOR_OTHER_MIN 0 /* Not use / #define PRIOR_OTHER_MAX 255 / Not use */

/* Scheduling Priorities. NOTE: Only the idle task can take * the true minimum priority. */

#define SCHED_PRIORITY_MAX 255 #define SCHED_PRIORITY_DEFAULT 100 #define SCHED_PRIORITY_MIN 1 #define SCHED_PRIORITY_IDLE 0

1. RR 時間間隔是 20 ticks 做一次 context switch。
觀看每個設定time slice的相關檔案其運算是皆為 timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK
在 nuttx/include/nuttx/config.h 中
CONFIG_RR_INTERVAL = 200
MSEC_PER_TICK = 10
2. 若要禁止 context switch,可用sched_lock()
此區禁止 context switch
sched_unlock()用在修改scheduler和priority。
3. 若要先將 timer interrupt 暫停,可用saved_state = irqsave();
此區暫停 timer interrupt
irqrestore(saved_state);
用在修改 scheduler。
注意:timer interrupt 跟 context switch 是不同系統。
4. Nuttx 只有兩個 scheduler policy,其 tcb->timeslice = 0 則表示FIFO, 非0則為RR。

Timer interrupt

/nuttx/arch/arm/src/stm32/stm32_vectors.S

processor exception

.. code-block:: c

.word	IDLE_STACK			/* Vector  0: Reset stack pointer */
.word	__start				/* Vector  1: Reset vector */
.word	stm32_nmi			/* Vector  2: Non-Maskable Interrupt (NMI) */
.word	stm32_hardfault		/* Vector  3: Hard fault */
.word	stm32_mpu			/* Vector  4: Memory management (MPU) */
.word	stm32_busfault		/* Vector  5: Bus fault */
.word	stm32_usagefault	/* Vector  6: Usage fault */
.word	stm32_reserved		/* Vector  7: Reserved */
.word	stm32_reserved		/* Vector  8: Reserved */
.word	stm32_reserved		/* Vector  9: Reserved */
.word	stm32_reserved		/* Vector 10: Reserved */
.word	stm32_svcall		/* Vector 11: SVC call */
.word	stm32_dbgmonitor	/* Vector 12: Debug monitor */
.word	stm32_reserved		/* Vector 13: Reserved */
.word	stm32_pendsv		/* Vector 14: Pendable system service request */
.word	stm32_systick		/* Vector 15: System tick */

/nuttx/arch/arm/src/stm32/stm32_timerisr.c (in line 109 )

.. code-block:: c

int up_timerisr(int irq, uint32_t regs) { / Process timer interrupt */ sched_process_timer(); return 0; }

Interrupt handler

IRQ numbers

.. code-block:: c

#define STM32_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG) / / Vector 0: Reset stack pointer value / / Vector 1: Reset (not handler as an IRQ) / #define STM32_IRQ_NMI (2) / Vector 2: Non-Maskable Interrupt (NMI) / #define STM32_IRQ_HARDFAULT (3) / Vector 3: Hard fault / #define STM32_IRQ_MEMFAULT (4) / Vector 4: Memory management (MPU) / #define STM32_IRQ_BUSFAULT (5) / Vector 5: Bus fault / #define STM32_IRQ_USAGEFAULT (6) / Vector 6: Usage fault / #define STM32_IRQ_SVCALL (11) / Vector 11: SVC call / #define STM32_IRQ_DBGMONITOR (12) / Vector 12: Debug Monitor / / Vector 13: Reserved / #define STM32_IRQ_PENDSV (14) / Vector 14: Pendable system service request / #define STM32_IRQ_SYSTICK (15) / Vector 15: System tick */

測試環境架設

硬體驅動原理

  • UART<embedded/USART>_
  • FPU (Floating Point Unit)

效能表現

參考資料

  • https://github.com/deadbeefcafe/nuttx-stm32f4disc-bb
  • http://bibliodigital.itcr.ac.cr/xmlui/bitstream/handle/2238/3051/FinalReport.pdf