---
# System prepended metadata

title: 作業系統工程-期末Project報告

---

# 作業系統工程-期末Project報告
# timer (計時器）
### 計時器(timer)概述
一個作業系統之所以能運作，仰賴著某種計時的機制，通常會借助硬體振盪器產生週期性訊號，並透過軟體計數。

timer的作用跟鬧鐘是相似的:
* 指定時間:
    * 啟動timer跟Callback Function 兩者之間被稱為period。
* 指定類型:
    * One-shot timers
    * Auto-reload timers 
* 制定任務:
    * 指定Callback Function

Timer會有2種狀態：
* 運行(Running、Active)
* 停用(Dormant)


計時器適合用於有大量需要延時執行或週期性執行的任務，雖然可以透過分別建立task，但這樣會比用timer做會消耗多一些資源。

使用過程：先初始化timer。
### 程式碼個人解析與理解(此處程式碼移植於FreeRTOS)
```c=
typedef struct tmrTimerControl
{
	const char				*pcTimerName;		
	/*計時器名稱，kernel其實沒有使用，僅方便debug用*/
	ListItem_t				xTimerListItem;		
	/*所有kernel特性用於事件管理的標準連結串列項。*/
	TickType_t				xTimerPeriodInTicks;
	/*計時器的時間和頻率。 */
	UBaseType_t				uxAutoReload;		
	/*如果計時器在過期後應該自動重啟，則設定為pdTRUE。
	如果計時器實際上是一次性計時器，則設定為pdFALSE*/
	void 					*pvTimerID;			
	/*標識計時器的ID。這允許在對多個計時器使用相同回撥時標識計時器。*/
	TimerCallbackFunction_t	pxCallbackFunction;	
	/*計時器定時時間到之後呼叫這個函式 */
} xTIMER;
```
這是FreeRTOS的計時器(timer)的資料結構。
```c=
typedef struct tmrTimerParameters{
	TickType_t     xMessageValue;	/*可以選的值，是一系列命令 */
	Timer_t        *pxTimer;	/*具體是哪一個計時器 */
} TimerParameter_t;

typedef struct tmrCallbackParameters{
	PendedFunction_t	pxCallbackFunction;	/* 會被執行的callbackFunction*/
	void *pvParameter1;	
	uint32_t ulParameter2;
} CallbackParameters_t;

/* 包含這兩種訊息型別以及識別符號的結構用於確定哪個訊息型別是有效的，
一個是執行計時器start 、reset、stop型別操作的，一個是執行回撥函式的 */
typedef struct tmrTimerQueueMessage{
	BaseType_t    xMessageID;	/*被發送到timer task的命令 */
	union{
		TimerParameter_t xTimerParameters;
		/*如果這個巨集不是1的話，不要加入下面這個結構每一位會讓這個結構變得很大*/
		#if( INCLUDE_xTimerPendFunctionCall == 1 )
			CallbackParameters_t xCallbackParameters;
		#endif 
	}u;
}DaemonTaskMessage_t;
```
這是timer接收指令的格式，包含開啟關閉timer，以及執行callback Function。
### timer程式碼分析
FreeRTOS的軟體timer是用task去實做的，
在vTaskStartScheduler啟動排程器的函式中，如果是使能configUSE_TIMERS計時器開啟巨集的話，就會執行xTimerCreateTimerTask計時器任務建立函式，計時器任務會自動執行，不需要使用者去建立
這是簡化的vTaskStartScheduler：
```c=
void vTaskStartScheduler( void ){
#if ( configUSE_TIMERS == 1 ){
		if(xReturn == pdPASS){
			xReturn = xTimerCreateTimerTask();
		}
        else{
			mtCOVERAGE_TEST_MARKER();
		}
	}
#endif /* configUSE_TIMERS */
}
````
### 建立timer
```c=
TimerHandle_t xTimerCreate(	
        const char * const pcTimerName,
        const TickType_t xTimerPeriodInTicks,
        const UBaseType_t uxAutoReload,
        void * const pvTimerID,
        TimerCallbackFunction_t pxCallbackFunction
);
					
TimerHandle_t xTimerCreateStatic(	
        const char * const pcTimerName,
        const TickType_t xTimerPeriodInTicks,
        const UBaseType_t uxAutoReload,
        void * const pvTimerID,
        TimerCallbackFunction_t pxCallbackFunction,
        StaticTimer_t *pxTimerBuffer 
);
```
Timer有分為動態timer跟靜態timer:
Timer_t的結構是動態分配的，還是靜態的。
```C=
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );
```
若timer為動態timer，不需要使用時就可以把他刪除。
### 結論
從timer在OS中的地位可以發現，OS中不能沒有timer，如果沒有timer控制，可能會有task塞住的問題，或者會因為太多task而拖累整個OS效率。

### 學期總結
這學期我學到了RISCV的編譯方法，以及如何去編譯一個程式，還有Makefile的含意及作用，還有硬體的暫存器的工作方式，最後就是其實很多OS的系統都是最基礎的資料結構來實現的，熟練資料結構的使用及設計，該好好複習一下資料結構了。
## 引用
* http://wiki.csie.ncku.edu.tw/embedded/freertos
* http://rtos.100ask.org/freeRTOS%E6%95%99%E7%A8%8B/index.html


