Một RTOS không phải phù hợp với mọi ứng dụng. RTOS có thể không là một giải pháp tốt nếu thiết bị phải thực hiện những ngắt ở tốc độ rất cao như trong hệ thống điều khiển động cơ mức thấp hoặc khi hệ thống đơn giản không cần đến các chức năng phức tạp của RTOS. Trong hệ thống mà bộ xử lý càng gần với việc điều khiển phần cứng mức bit thì càng ít nhu cầu sử dụng RTOS trong hệ thống.
Một RTOS thường được sử dụng khi hệ thống cần đến tài nguyên chia sẻ, cần phân bổ bộ nhớ. Nói chung trong những hệ thống phức tạp nhưng các tác vụ có thể được lập lịch trong khoảng thời gian của bộ định thời (tích tắc) thì dùng RTOS có thể có ý nghĩa. Thậm chí trong những hệ thống đơn giản, một RTOS có thể được sử dụng để cấu trúc sự hoạt động của mã. RTOS cũng hữu dụng khi chúng ta cần sử dụng những tài nguyên cơ bản (ổ đĩa, màn hình hiển thị, …).
RTOS thường được sử dụng khi các tác vụ được lập lịch tuần tự không thể đảm bảo được những công việc có mức ưu tiên cao nhất sẽ được thực hiện trước. Sử dụng
lập lịch ưu tiên, RTOS có thể đảm bảo những chức năng quan trọng sẽ được thực hiện đúng giờ.
Hầu hết RTOS đều có khả năng cấu hình được, chúng ta bắt đầu với hạt nhân cơ bản và thêm những đặc trưng cần thiết cho hệ thống của mình. Nếu hệ thống có sử dụng các ổ đĩa, giao tiếp mạng, chúng ta có thể thêm mô-đun bao gồm các driver và mô-đun TCP/IP của RTOS.
Khi cân nhắc sử dụng một RTOS, hãy xem xét cả đến chi phí của nó. Một số RTOS có phí mua một lần, trong khi những cái khác có cả phí cho mỗi sản phẩm sản xuất ra. Chúng ta có thể trả phí bản quyền theo cách: trả mức phí cơ bản cho nhân hệ điều hành và trả thêm phí cho mỗi mô-đun thêm vào.
Sự phân chia giữa một RTOS và nhân là không rõ ràng. Nói chung một nhân thì nhỏ hơn so với RTOS tương ứng và nó không cung cấp đầy đủ các đặc trưng của RTOS đầy đủ. Phần nhân có thể cung cấp các chức năng lập lịch và quản lý phù hợp với những hệ thống nhúng nhỏ.
Sử dụng RTOS cũng đồng nghĩa với tốn kém bộ nhớ hơn do từng tác vụ đều có ngăn xếp riêng của nó. Một số RTOS được liên kết vào mã chương trình, trong khi những cái khác lại hoạt động giống như hệ điều hành của PC. RTOS được nạp từ một thiết bị lưu trữ và chương trình của chúng ta thực thi như là một ứng dụng. Việc lựa chọn RTOS nào có thể ảnh hưởng lớn đến các thiết bị phần cứng vì cần phải có những tài nguyên cơ bản mà RTOS đó yêu cầu.
Các chuẩn truyền thông cũng rất quan trọng. Nhiều RTOS bây giờ hỗ trợ TCP/IP. Nếu sử dụng một chuẩn giao tiếp như vậy chúng ta có thể liên lạc với bất kỳ hệ thống khác sử dụng cùng chuẩn giao thức đó mà không liên quan đến sử dụng hệ điều hành gì.
Sử dụng một RTOS trên bộ vi điều khiển có thể có một số khó khăn sau: không gian mã chương trình có giới hạn, con trỏ ngăn xếp có thể được thực hiện trong phần cứng (làm cho ngăn xếp tác vụ không thể thực hiện) và bộ nhớ RAM rất giới hạn. RTOS cho vi điều khiển thường là những nhân rất cơ bản, không có nhiều đặc trưng thêm vào.
3.9 Ƣu nhƣợc điểm của hệ điều hành thời gian thực
Nhân thời gian thực (còn được gọi là hệ điều hành thời gian thực - RTOS) giúp cho dễ dàng thiết kế và mở rộng các ứng dụng thời gian thực, có thể thêm mới các chức năng mà không yêu cầu phải thay đổi nhiều tới phần mềm. Tác dụng của RTOS làm đơn giản hoá quá trình thiết kế bằng việc chia nhỏ mã ứng dụng thành các tác vụ riêng biệt. Với một hệ RTOS ưu tiên, mọi sự kiện yêu cầu thời gian khẩn cấp đều được bắt giữ nhanh chóng và hiệu quả. RTOS giúp cho việc quản lý tài nguyên được tốt hơn với các dịch vụ hệ thống như semaphore, mailbox, queue ...
Tuy nhiên cũng phải cân nhắc khi sử dụng RTOS vì một số chi phí: nhân, yêu cầu thêm ROM/RAM, chiếm CPU từ 2 – 4 %.
Hiện tại có trên 80 hệ RTOS thương mại cho các vi xử lý 8 bit, 16 và 32 bit. Một vài RTOS là các hệ điều hành hoàn chỉnh, không chỉ bao gồm nhân thời gian thực mà còn có các mô-đun quản lý I/O, hệ thống giao diện, hệ thống file, ...
3.10 Hệ điều hành thời gian thực µC/OS
Trong phần này, luận văn sẽ trình bày những vấn đề chính trong cấu trúc nhân
thời gian thực µC/OS. Một hệ điều hành thời gian thực rất nhỏ (khoảng hơn 5000 dòng
mã lệnh) [17], nhưng hiện đã được áp dụng và triển khai thành công vào rất nhiều dự án có yêu cầu khắt khe về đáp ứng thời gian (như các hệ thống trong hàng không, y tế …). Nhằm nắm bắt được những vấn đề cơ bản trong việc thiết kế xây dựng hệ thống nhúng theo kiến trúc thời gian thực và thực hiện phần thực nghiệm trong quá trình nghiên cứu vì nhân của nó cũng khá nhỏ và miễn phí cho mục đích giáo dục. Ngoài ra trên thị trường còn có rất nhiều hệ điều hành thời gian thực nổi tiếng khác như: QNX, VxWorks, Embedded Linux, Window CE…Các phần trình bày chính là:
Cách quản lý truy cập tới miền găng của µC/OS
Cấu trúc và trạng thái của tác vụ
Cách viết hàm xử lý ngắt
Cách quản lý nhịp đồng hồ
Khởi động hệ thống µC/OS
Khởi động hệ thống đa nhiệm
a. Các miền găng
Cũng giống như các nhân thời gian thực khác, µC/OS cũng vô hiệu hoá các
ngắt khi chương trình thực thi miền găng. Do ảnh hưởng tới vấn đề đáp ứng các ngắt
nên thời gian vô hiệu hoá các ngắt là một vấn đề quan trọng. µC/OS duy trì thời gian
vô hiệu hoá ngắt đến mức tối thiểu, nhưng thời gian này còn tuỳ thuộc nhiều vào kiến trúc vi xử lý và chất lượng mã được sinh bởi chương trình dịch. Mọi vi xử lý đều cung cấp các chỉ thị để vô hiệu/hữu hiệu hoá các ngắt và chương trình dịch C phải có cơ chế thực thi các chỉ thị này bằng ngôn ngữ C hoặc Assembly (đối với một số trình biên
dịch). Trong µC/OS, hai macro được định nghĩa để vô hiệu/hữu hiệu các ngắt đó là
OS_ENTER_CRITICAL() và OS_EXIT_CRITICAL(). Các macro có thể khác nhau tuỳ theo từng vi xử lý. Chính vì thế, chúng được viết trong file cấu hình dành riêng cho vi xử lý trong OS_CPU.H (khi thực hiện porting).
b. Các tác vụ
Một tác vụ là một hàm lặp vô hạn. Nó giống như những hàm khác trong C chứa
đối số và một kiểu trả về nhưng không bao giờ trả về giá trị (hình 3.6). µC/OS có thể
quản lý tới 64 tác vụ (phiên bản µC/OS-II), trong đó có 2 tác vụ hệ thống, 4 tác vụ từ
OS_LOWEST_PRIO tới OS_LOWEST_PRIO-3. Người dùng có thể quản lý 56 tác vụ. Mỗi tác vụ được gán một mức ưu tiên duy nhất từ 0 tới OS_LOWEST_PRIO-2. Vì
nhân theo kiểu lập lịch ưu tiên nên µC/OS luôn chọn tác vụ có độ ưu tiên cao nhất để
Hình 3.6 Cấu trúc một tác vụ
Để µC/OS quản lý các tác vụ của ứng dụng, bước đầu tiên là phải tạo các tác
vụ. Trong µC/OS hàm OSTaskCreate() và OSTaskCreateEx() (phiên bản II) thực hiện
điều này.
c. Các trạng thái của tác vụ
Các tác vụ có thể nhận 1 trong 5 trạng thái: DORMANT, READY, RUNNING, WAITING FOR AN EVENT hoặc INTERRUPTED.
DORMANT: Tác vụ nằm trong bộ nhớ (ROM hoặc RAM) nhưng không sẵn
sàng cho µC/OS do chưa được tạo.
READY: Khi một tác vụ được tạo nó được đặt trạng thái là READY.
RUNNING: Tác vụ đang có sự phục vụ của CPU.
WAITING FOR AN EVENT: Đang chờ sự kiện.
INTERRUPTED: Ngắt xuất hiện khi đang thực hiện tác vụ và CPU đang thực
thi thủ tục ngắt.
Trạng thái DORMANT tương ứng với tác vụ đã nằm trong chương trình nhưng
chưa nằm trong quản lý của µC/OS. Khi µC/OS gọi hàm OSTaskCreate() hoặc
OSTaskCreateEx() thì tác vụ trên mới thực sự được quản lý bởi hệ điều hành và chuyển sang trạng thái READY. Tác vụ có thể được tạo bất cứ lúc nào, khi tạo tác vụ mới được gán quyền ưu tiên cao hơn thì nó sẽ chiểm ngay quyền điều khiển của CPU.
Tác vụ có thể trở về trạng thái DORMANT khi nó bị xoá khỏi µC/OS bằng
OSTaskDel().
Quá trình đa nhiệm được bắt đầu khi gọi OSStart(). Sau đó OSStart() sẽ chọn tác vụ có trạng thái READY và có độ ưu tiên cao nhất để chuyển sang trạng thái RUNNING.
Một tác vụ đang chạy có thể tự trì hoãn chính nó bằng cách gọi OSTimeDly(). Trong khi trì hoãn, tác vụ khác nếu có quyền ưu tiên cao hơn vẫn có quyền chiếm CPU. Khi thời gian trì hoãn kết thúc, OSTimeTick() sẽ khôi phục trạng thái RUNNING cho tác vụ.
Tác vụ đang chạy cũng có thể đợi sự xuất hiện của sự kiện bằng việc gọi OSSemPend(), OSMBoxPend() hoặc OSQPend(), tác vụ chuyển sang trạng thái WAITING. Khi tác vụ đợi một sự kiện, tác vụ có độ ưu tiên cao nhất tiếp theo được quyền sử dụng CPU. Khi sự kiện xuất hiện, tác vụ lại chuyển sang trạng thái READY. Sự xuất hiện của sự kiện có thể được báo bởi một tác vụ khác hoặc bằng ISR. Tác vụ
đang chạy luôn có thể bị ngắt trừ khi µC/OS vô hiệu hoá các ngắt. Khi đó, tác vụ trong
trạng thái ISR. Khi ngắt xuất hiện, tác vụ bị tạm dừng, ISR chiếm quyền điều khiển
CPU. Khi tất cả các tác vụ đều đợi sự kiện, µC/OS sẽ thực hiện tác vụ OSTaskIdle().
d. Khối điều khiển tác vụ
Khi tác vụ được tạo, nó được gán một khối điều khiển tác vụ (TCB). µC/OS sử
dụng TCB để duy trì trạng thái của tác vụ khi nó được thực thi theo kiểu lập lịch ưu tiên. Khi tác vụ được khôi phục quyền điều khiển CPU (sau khi kết thúc ngắt), trạng thái thực thi của tác vụ được khôi phục nhờ TCB. Tất cả TCB được lưu trú trong RAM.
e. Lập lịch tác vụ
µC/OS sử dụng bộ lập lịch tác vụ được thực hiện bởi hàm OSSched(), nó luôn
chọn tác vụ có độ ưu tiên cao nhất để thực thi. Đối với lập lịch mức ISR sẽ được quản lý bởi hàm OSIntExit() (lập lịch sau khi thoát khỏi ngắt).
Thời gian để lập lịch các tác vụ luôn là hằng số cho dù số tác vụ được tạo là bao nhiêu. Nếu ứng dụng gọi OSSchedLock() hoặc xuất hiện ngắt (điều kiện OSIntNesting>0), tác vụ lập lịch sẽ kết thúc. Khi bộ lập lịch tìm thấy tác vụ có độ ưu tiên cao nhất, OSSched() sẽ kiểm tra xem tác vụ có độ ưu tiên cao nhất có phải là tác vụ hiện thời hay không, điều này để tránh lãng phí một bước chuyển ngữ cảnh.
f. Các ngắt trong µC/OS
µC/OS yêu cầu dịch vụ ngắt ISR viết bằng hợp ngữ. Đỗi với những trình biên
dịch C hỗ trợ nhúng mã hợp ngữ inline thì có thể viết dịch vụ ngắt bằng hợp ngữ ngay trong mã C.
Giả mã cho ISR như sau:
Hình 3.8 Hàm dịch vụ ngắt trong µC/OS
Trong đoạn mã trên, việc tăng trực tiếp OSIntNesting nhanh hơn nhiều so với việc gọi hàm OSIntEnter() vì trong hàm OSIntEnter() hệ thống còn phải thực hiện việc vô hiệu hoá các ngắt khác.
g. Nhịp đồng hồ
µC/OS yêu cầu cung cấp một đồng hồ thời gian để thực thi các chức năng liên
quan đến đo thời gian mà các dịch vụ cần đến. Một tích tắc cần xuất hiện 10 đến 100 lần trong một giây.
Trong µC/OS, người phát triển phải cho phép các ngắt thời gian xảy ra sau khi
khởi động hệ thống đa nhiệm (Sau khi gọi hàm OSStart()). Không được cho phép ngắt
thời gian xảy ra giữa hai lời gọi: OSInit() và OSStart() vì trong trường hợp đó µC/OS
sẽ trong trạng thái không được định nghĩa và hệ thống dễ gây ra lỗi.
Nhịp đồng hồ trong µC/OS được phục vụ bởi việc gọi hàm OSTimeTick() từ
một ngắt đồng hồ. Mã cho ngắt đồng hồ phải được viết bằng hợp ngữ vì nó phải truy cập trực tiếp đến các thanh ghi. Trong trường hợp không viết được ISR cho ngắt đồng hồ, người phát triển có thể gọi trực tiếp hàm OSTimeTick() từ mức tác vụ. Để làm điều này, trước tiên tạo một tác vụ có độ ưu tiên cao hơn các tác vụ hiện có trong ứng dụng, ngắt thời gian cần báo hiệu cho tác vụ này thông qua semaphore hoặc mailbox. Tác vụ này được gọi là Tick Task.
h. Khởi động hệ thống µC/OS
Khởi tạo hệ thống µC/OS bằng cách gọi hàm OSInit() trước khi gọi bất cứ dịch
vụ nào. OSInit() sẽ khởi tạo mọi biến và cấu trúc dữ liệu của µC/OS. Nó cũng khởi tạo
tác vụ OSTaskIdle() với độ ưu tiên không đổi là OS_LOWEST_PRIO. Khởi động hệ
thống đa nhiệm µC/OS bằng cách gọi hàm OSStart(). Trước khi bắt đầu gọi hàm này
i. Porting µC/OS
Porting µC/OS có nghĩa là cấu hình µC/OS để gắn nó với một vi xử lý xác định.
Hầu hết µC/OS được viết bằng C chuẩn trong đó có sử dụng các kiểu dữ liệu có khả
năng chuyển giữa các môi trường khác nhau, các bộ dịch khác nhau. µC/OS được thiết
kế có tính khả chuyển cao nên việc porting trên các vi xử lý khác nhau là khá dễ dàng.
Một vi xử lý có thể chạy µC/OS nếu nó thoả mãn các yêu cầu sau:
Có trình biên dịch C cho loại vi xử lý này.
Cho phép vô hiệu/hữu hiệu hoá các ngắt từ C.
Vi xử lý phải hỗ trợ ngắt và cần cung cấp một ngắt xuất hiện trong khoảng thời
gian đều đặn (10 đến 100Hz).
Vi xử lý phải hỗ trợ một ngăn xếp phần cứng và cho phép lưu các thông tin trên
ngăn xếp đó (có thể tới nhiều Kbyte).
Vi xử lý phải có các chỉ thị để tải, lưu con trỏ ngăn xếp và các thanh ghi CPU
khác trên ngăn xếp hoặc trong bộ nhớ.
CHƢƠNG 4: CÁC CÁCH TIẾP CẬN VỚI BÀI TOÁN NHẬN DẠNG CHỮ NÔM
4.1 Nhận dạng chữ Nôm bằng mạng nơ-ron
4.1.1 Áp dụng mạng nơ-ron trong nhận dạng chữ Nôm
Với những kết quả ban đầu đạt được cùng với nhóm nghiên cứu về nhận dạng
chữ Nôm tại trường Đại học Công nghệ, Luận văn cũng đưa ra cách tiếp cận sử du ̣ng
mạng nơ-ron để thực nghiệm với bài toán nhận dạng chữ Nôm vì một số lý do chính
sau: Thứ nhất , tốc độ nhâ ̣n da ̣ng của mạng nơ -ron nhanh vì sau khi học thì việc xác
định một ký tự giống ký tự nào nhất chỉ là việc nhân ma trận . Hơn nữa việc này có thể làm song song trên mỗi nút trong cùng mô ̣t tầng [30]. Thứ hai là khối lượng dữ liệu lưu trữ để nhận dạng nhỏ - chỉ cần lưu trữ mảng trọng số đã xác định trong quá trình huấn luyê ̣n ma ̣ng mà không cần lưu trữ tâ ̣p dữ liê ̣u mẫu chuẩn và tâ ̣p dữ liê ̣u ra chuẩn. Thứ ba là ta có thể dễ dàng điều chỉnh tốc đô ̣ nhâ ̣n da ̣ng hay đô ̣ chính xác bằng viê ̣c thay đổi số tầng ẩn và số nút trên mỗi tầng . Tăng số tầng và số nút trên mỗi tầng sẽ tăng đô ̣ chính xác nhưng la ̣i giảm tốc đô ̣ nhâ ̣n da ̣ng . Lý do cuối cùng là dựa trên các phương pháp đã áp dụng có kết quả tốt về nhâ ̣n da ̣ng chữ tượng hình Trung Quốc và Nhâ ̣t Bản [31].
Có nhiều mạng nơ-ron có thể áp dụng vào bài toán nhâ ̣n dạng, ở đây ta áp dụng mạng Perceptron đa tầng v ì những ưu điểm của mạng này trong bài toán nhận dạng chữ Latin [12]. Tuy nhiên tôi và nhóm nghiên cứu đã phân tích và điều chỉnh các