Giới thiệu Hệ điều hành thời gian thực RTOS
Trang 1CHƯƠNG 2: GIỚI THIỆU VỀ HỆ ĐIỀU HÀNH THỜI GIAN THỰC
FreeRTOS 2.1 KHÁI QUÁT CHUNG :
Hiện nay có rất nhiều hệ điều hành thời gian thực ( RTOS) dành cho phát triển hệ thống nhúng, việc sử dụng còn phụ thuộc vào khả năng đáp ứng của vi của Vi điều khiển đặc biệt là RAM và tốc độ xung clock Những hệ điều hành này được phát triển trên các nền ngôn ngữ lập trình khác nhau, phổ biến nhất là ngôn ngữ C, và cũng có thế là
JAVA….Trong khuông khổ luận văn này chỉ xin được giới thiệu những hệ điệu hành thời gian thực dành cho những hệ thống nhỏ
Hiện tại có nhiều hệ điều hành thời gian thực dành cho các dòng vi điều khiển thông thường, từ Open Source đến có bản quyền
Open source phổ biến như FreeRTOS hay CooCox CoOS, ở đây có xin được giới thiệu về FreeRTOS vì tính phổ biến của nó cũng như đơn giản, dễ sử dụng nhưng vẫn đầy đủ các tính năng của một RTOS
FreeRTOS được nghiên cứu bởi Richard Barry với tên ban đầu là FRTOS07 Mục đích của FreeRTOS là portable( khả năng linh động) , open source ( mã nguồn mở) , mini kernel (là một hệ điều hành thời gian thực nhỏ) mà có thể được thao tác trong chế độ ưu tiên (Pre-emptive) cũng như phối hợp (Cooperative)
FreeRTOS hiệ tại hỗ trợ lên đến 27 kiến trúc vi điều khiển khác nhau khác nhau :
Altera Nios II
ARM7, ARM9, Cortex M3
AVR, PIC, 8051
SH, H8S, PowerPC, x86 Các chức năng chính của FreeRTOS được giới thiệu như sau :
2.1 1 Thời gian thực
Thời gian thực hoặc hoạt động đồng bộ
Trong chế độ đồng bộ thì việc đặt lịch không được thực hiện bởi 1 điểm xác định của timer mà được xử lý qua việc điều khiển từ task này đến task khác bởi cơ chế yielding
2.1.2 Dynamic Scheduling
Thời điểm xắp xếp lại lịch xảy ra sau 1 khoảng thời gian cụ thể (phụ thuộc vào tần số xung clock)
2.1.3 Giải thuật đặc lịch
Là giải thuật có độ ưu tiên cao nhất trước tiên Nếu có nhiều hơn 1 tast có cùng độ ưu tiên cao nhất thì các task sẽ được thực hiện theo kiểu round-robin
2.1.4 Giao tiếp giữa Tasks
Trang 22.1.4.1.1 Queuing:
Inter-process comm được thực hiện bằng queue, thì hầu hết thông tin được truyền bằng giá trị chứ không phải tham chiếu nên vấn đề ràng buộc vê bộ nhớ phải được xét đến
Queue read hoặc write từ bên trong ISR là : non-blocking
Queue read hoặc write với timeout=0 : non-blocking
2.1.4.1.2 Synchroniztion ( Đồng bộ):
FreeRTOS cho phép tạo ra và sử dụng binary semaphore Bản thân Semaphore là 1 trường hợp đặc biệt của queue với chiều dài =1 và kích thước dữ liệu là =0 Vì điều này nên việc lấy và trả semaphore là các thao tác nguyên thủy,
do đó các ngắt sẽ bị vô hiệu hóa và bộ đặt lịch phải bị treo để nhận 1 block trên queue này
2.1.5 Tránh Blocking và Deadlock
Trong FreeRTOS các task hoặc là non-blocking hoặc sẽ bị block với 1 khoảng thời gian cố định Các task mà thức dậy khi hết timeout và vẫn không thể truy nhập tới 1 tài nguyên vì đôi khi lời gọi API tới 1 tài nguyên có thể trả về
“không thành công” (failed)
2.1.6 Xử lý critical Section
Critical Section được xử lý bởi việc vô hiệu hóa tất cả các ngắt Critical section bên trong mỗi task có thể được xếp chồng lên nhau và mỗi task sẽ ghi dấu lại bởi việc tăng giá trị xếp chồng của nó
2.1.7 Treo bộ đặt lịch
Khi dành riêng việc truy nhập tới MCU mà việc MCU bị yêu cầu là không gây nguy hiểm cho thao tác của ISR, bộ đặt lịch có thể bị treo Việc treo này đảm bảo răng tiến trình hiện tại sẽ không được ưu tiên bởi 1 đặt lịch (scheduler)
2.1.8 Cấp phát bộ nhớ
FreeRTOS cung cấp 3 mô hình heap Mô hình đơn giản nhất là việc cấp phát
cố định, phức tạp hơn là mô hình cho phép cấp phát và giải phóng bằng việc sử dụng giải thuật “best fit” và phức tạp nhất là heap_3 cho phép sử dụng malloc và calloc()
2.1.9 Đảo ngược độ ưu tiên
FreeRTOS không thực hiện bất kỳ kỹ thuật nâng cao nào với độ ưu tiên tiến trình như kế thừa độ ưu tiên hay xoay vòng độ ưu tiên để thực hiện đảo ngược độ
ưu tiên
Trang 3Hình 2.1 Cấu trúc của FreeRTOS
2.2 GIỚI THIỆU CÁC HÀM APIs (SERVICE FUNCTIONS):
2.2.1 Các hàm API liên quan đến Task.
2.2.1.1 Tạo và xóa Task:
xTaskCreate
portBASE_TYPE xTaskCreate(
pdTASK_CODE pvTaskCode, const portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters,
unsigned portBASE_TYPE uxPriority, xTaskHandle *pvCreatedTask
);
Mô tả: Tạo một Task và thêm vào danh sách các task sẵn sàng để thực thi
Tham số:
pvTaskCode Pointer to đến hàm hiện thưc cho Task
pcName Tên mô tả cho Task đó ( chỉ dùng cho mục đích debug hệ
thống) Chiều dài tối đa của tên được định nghĩa bằng
Trang 4usStackDepth Là kích thước của Stack đặc trưng cho số lượng biến mà
Task có thể quản lý được
pvParameters Pointer được sử dụng như là tham số của việc tạo Task.
uxPriority Độ ưu tiên của Task
pvCreatedTask Pointer trỏ đến Task được tạo.
Trị trả về: pdPASS nếu như Task được tạo thành công
vTaskDelete
void vTaskDelete( xTaskHandle pxTask );
Mô tả: Xóa một Task từ RTOS realtime management
Tham số:
pxTask poiter đến Task cần xóa
Trị trả về: Không trị
2.2.1.2 Điều khiển Task:
vTaskDelay
void vTaskDelay( portTickType xTicksToDelay );
Mô tả: Delay ( block) Task một khoảng thời gian kể từ lần cuối hàm được gọi ( số ticks mà Task đó bị block)
Tham số:
xTicksToDelay: Số Ticks Task bị block
Trị trả về: Không trị
vTaskDelayUntil
void vTaskDelayUntil(portTickType *pxPreviousWakeTime,
portTickType xTimeIncrement );
Mô tả: Block Task trong một chu kì xác định
Tham số:
pxPreviousWakeTime Pointer đến biến lưu giá trị lần cuối cùng
Task được unclocked Biến này phải được khởi tạo giá trị với giá trị hiện tại cho lần dùng đầu tiên
xTimeIncrement : Là chu kì thời gian Task sẽ đươck uncloked sau
mỗi thời (*pxPreviousWakeTime + xTimeIncrement) Gọi hàm naỳ với mục đích thực thi một Task theo một chu kì nhất định
Trị trả về: Không trị
uxTaskPriorityGet
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
Mô tả:Đọc giá trị độ ưu tiên của Task
Tham số: pxTask : biến Handle của Task cần đọc
Trang 5 Trị trả về: Độ ưu tiên của Task cần gọi.
vTaskPrioritySet
void vTaskPrioritySet( xTaskHandle pxTask, unsigned
portBASE_TYPE uxNewPriority );
Mô tả: Cài đặt độ ưu tiên cho một Task
Tham số:
pxTask : Handle của Task sẽ được set độ ưu tiên Nếu là NULL thì
sẽ set độ ưu tiên của Task đang được gọi ( Task hiện tại)
uxNewPriority : Độ ưu tiên mới cho Task.
Trị trả vể: Không trị
vTaskSuspend
void vTaskSuspend( xTaskHandle pxTaskToSuspend );
Mô tả: Suspend ( xem thêm chương 1) bất kì Task nào mà không quan tâm đến độ ưu tiên của Task đó
Tham số:
pxTaskToSuspend : Handle của Task sẽ bị suspend
Trị trả về: Không trị
vTaskResume
void vTaskResume( xTaskHandle pxTaskToResume );
Mô tả: Resume một Task, sẽ được dùng cùng với xTaskSuspend
Tham số:
pxTaskToResume : Task được Resume:
Trị trả về: Không trị
xTaskResumeFromISR
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume );
Mô tả:Resume một Task từ ISR
Tham số:
pxTaskToResume: Handle Task được Resume
Trị tra về: pdTRUE nếu như trị việc resuming có tác dụng lên context switch, ngược lại là pdFALSE
2.2.1.3 Điều khiển Kernel:
taskENTER_CRITICAL
Trang 6 Đây là một Macro, macro này có tác dụng báo cho Kernel biết là bắt đầu một vùng code được “bảo vệ” để đảm nó được thực thi mà không bị ảnh hường bời ngắt cũng như context Switch
taskEXIT_CRITICAL
macro này có tác dụng báo cho kernel biết đã kết thúc vùng code được “bảo vệ”
taskDISABLE_INTERRUPTS
Macro này có tác dụng DISABLE tất cả các ngắt
taskENABLE_INTERRUPTS
Macro này có tác dụng ENABLE tất cả các Task
2.2.1.4 Các tiện ích khác cho Tasks
xTaskGetCurrentTaskHandle() xTaskGetStackHighWaterMark() xTaskGetTickCount()
xTaskGetTickCountFromISR() xTaskGetSchedulerState() xTaskGetNumberOfTasks() vTaskList()
vTaskStartTrace() ulTaskEndTrace() vTaskGetRunTimeStats() vTaskSetApplicationTag() xTaskCallApplicationTaskHook()
uxTaskGetStackHighWaterMark()
2.2.1 Các hàm APIs liên quan đế Semaphore
vSemaphoreCreateBinary
vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )
Mô tả:
Là một Macro để lạo một semaphore nhị phân
Tham số:
xSemaphore: là biến Handle của việc tạo semaphore, biến này cho biết trạng thái việc tạo semaphore
vSemaphoreCreateCounting
xSemaphoreHandle xSemaphoreCreateCounting( unsignedportBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
Mô tả: Macro tạo một counting semaphore
Tham số:
uxMaxCount Giá trị biến đếm tối đa dó thể đạt được Khi đạt đến giá trị này thì nó không
thể được “given” thêm được nữa
Trang 7uxInitialCount Giá trị biến đếm ban đầu khi khởi tạo semaphore.
Trị trả về: Biến Handle khi tạo semphore
xSemaphoreCreateMutex
xSemaphoreHandle xSemaphoreCreateMutex( void )
Mô tả: Macro tạo mutex semaphore
Trị trả về: Biến Handle của semaphore
xSemaphoreTake
xSemaphoreTake( xSemaphoreHandle xSemaphore, portTickType xBlockTime )
Mô tả: Macro nhận một semaphore, semaphore này phỉ được tạo từ trước qua các lệnh xSemaphoreCreate()
Tham sô:
xSemaphore Là biến Handle của semaphore sẽ được nhận xBlockTime Là một khoảng thời gian chờ Semaphore ở trạng thái sẵn sàng ( available)
Trị trả về: pdTRUE nếu như việc nhận semaphore thành công, ngược lại sẽ là pdFALSE
xSemaphoreGive
xSemaphoreGive( xSemaphoreHandle xSemaphore )
Mô tả: Macro để giải phóng Semaphore, phải được dùng với
xSemaphoreTake
Tham sô: xSemaphore Là một Handle của sempaphore được giải phóng.
Trị trả về: pdTRUE nếu như việc giải phóng thành công, pdFALSE nếu không thành công
2.2.2 Các hàm API liên quan đến Queue
xQueueCreate
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
Mô tả: Tạo một đối tượng Queue, phân bộ nhớ cho Queue và trả về giá trị Handle của Queue
Tham số:
uxQueueLength Số lượng mẫu ( items) tối đa mà Queue có thể chứa được
Trang 8uxItemSize Số byte của mỗi mẫu yêu cầu.
Trị trả về: Handle cho Queue được trả về , Queue không được tạo thành công sẽ trả về giá trị 0
vQueueDelete
void vQueueDelete( xQueueHandle xQueue );
Mô tả: Xóa Queue và giải phóng bộ nhớ
Tham số : xQueue là giá trị biến Handle của Queue
Trị trả vể: Không trị
xQueueSend
portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue,
portTickType xTicksToWait );
Mô tả: Gửi một mẫu ( item) vào Queue
Tham số:
xQueue Biến Handle của Queue mà Item được gửi vào
pvItemToQueue Một pointer đến dữ liệu được đưa vào Queue, kích thước dữ liệu
này được định nghĩa khi Queue được tạo ( biến uxItemSize ) xTicksToWait Là khỏang thời gian mà Task bị khóa để chờ Queue còn trống để
gửi dữ liệu vào
Trị trả về: pdTRUE nếu như gửi dữ liệu vào Queue thành công, ngược lại sẽ trả về mã lỗi
xQueueReceive
portBASE_TYPE xQueueReceive( xQueueHandle xQueue, void *pvBuffer,
portTickType xTicksToWait );.
Mô tả: Nhận một Items từ một Queue nào đó
Tham số:
xQueue Biến Handle của Queue mà Item sẽ được nhận
pvBuffer Một pointer đến một buffer mà dữ liệu được đưa vào từ Queue, kích
buffer phải bằng kích thước của mỗi items trong Queue ( biến
uxItemSize ).
xTicksToWait Là khỏang thời gian mà Task bị khóa để chờ Queue nếu như queue
bị rỗng
Trị trả về: pdTRUE nếu như gửi dữ liệu vào Queue thành công, ngược lại sẽ trả về mã lỗi