Thông báo

Collapse
No announcement yet.

Lập trình đa nhiệm cho vi điều khiển

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Lập trình đa nhiệm cho vi điều khiển

    Các kiến thức cơ bản về hệ thống nhúng đã được bác Võ Duy Thành viết khá đầy đủ. Em đây cũng xin góp một bài .Về lập trình hệ thống nhúng cho vi điều khiển thì đây không còn là điều lạ trên thế giới và ở việt nam nhưn đối với các anh em SV thì việc này còn khá mới mẻ do quan điểm lập trình của chúng ta từ trước tới giờ chỉ có hai loại chính là :Lập trình tuyến tính và lập trình có cấu trúc.

    Lập trình đa nhiệm cho hệ thống nhúng khác với lập trình có cấu trúc và lập trình tuyến tính là.Chúng không thực hiện một khối lệnh một cách liên tục (hàm) mà khối lệnh đó được chia nhỏ và thức hiện sen kẽ với các đoạn lệnh trong các khối lệnh khác.Về cấu trúc chương trình thì lập trình đa nhiệm không có một chương trình chính (hay hàm main trong C) mà chúng chia thành các task.Các task này được đặt trong bộ nhớ ,và có một câu hoỉ được đặt ra là vậy thì các task này sẽ hoạt động như thế nào ?Đúng vậy chúng phải có một chương trình để điều khiển chúng và có tên rất quen thuộc là Kernel.Kernet có nhiệm vụ quản lý sự hoạt động của các task bao gồm các công việc : Phân hạch thời gian,quản lý tài nguyên …



    Như vậy để có thể xây dựng được một hệ thống đa nhiệm trên VĐK thì các bạn cần có những yêu cầu gì về phần cứng và phần mềm?



    Về phần cứng:

    Một điều không thể thiết đó là một bộ timer tích hợp trong VĐK.Nó có nhiệm vụ tạo đơn vị thời gian.(Có nghĩa là một chu kì hoạt động của hệ thống được chia nhỏ thành các đơn vị thời gian).Bộ nhớ chương trình đủ lớn để chứa các mã lệnh .Ngoài mã lệnh của các task cong mã lệnh của Kernel .Bộ nhớ RAM cũng là một vấn đề rất hạn chế của VĐK vì mỗi lần chuyển ngữ cảnh thì toàn bộ ngữ cảnh của một Task được lưu vào một ngăn xếp trong RAM.Chúng ta có càng nhiều task thì cần cành nhiều ngăng xếp kiểu này (Các bạn đừng nhầm ngăn xếp này với ngăn xếp cứng nhé ! đây là ngăng xếp do phần mềm chúng ta phải tạo ra)Cụ thể chúng là bao nhiêu thì tùy vào các ứng dụng mà các bạn mới có thể xác định được.

    Về phần mềm:

    Các bạn hiện gời có hai công cụ để lập trình cho VĐK đó là ngôn ngữ bậc thấp (Assembly) và ngôn ngữ bậc cao (C ,basic…,nhưng tôi chỉ dùng C) và ở hai ngôn ngữ này các bạn đều có thể lập trình đa nhiệm cho VĐK được.

    Với Assembly đây là ngôn ngữ mà các bạn có thể làm mọi chuyên được với VĐK nhưng thực sự nó chỉ dành cho những người quá chuyên nghiệp.Để lập trình đa nhiệm cho VĐK bằng ngôn ngữ này thì các bạn phải bắt đẩu từ con số 0 !!! bạn phải xây dụng toàn bộ Kernel cho ứng dụng của bạn và nó chỉ phù hợp với các ứng dụng rất nhỏ (Đối với tôi và không giám nói tới các cao nhân).Nếu bạn nào đam mê có thể đọc quyển sách :”Real time system and programming languages” Có gần như tất cả các thuật toán tối ưu để các bạn có thể xây dựng Kernel. Song thế mạnh của Assembly là bạn có thể xác định được chính xác thời gian mà một task của bạn thực hiện và tất nhiên điều đó đồng nghĩa với việc hệ thống của các bạn sẽ tố ưu.(Thế mạnh của Assembly mà).

    Với C và các ngôn ngữ bậc cao khác thì sao nhỉ ?bạn đã được cung cấp một Kernel rồi và vấn đề của các bạn là sử dụng chúng mà thôi .Nếu như phần mềm các bạn sử dụng mà chưa có thì các bạn vào các trang Web của bản hãng để mua về !!!(Vấn đề là mất tiền) tôi xin thí dụ như để viết cho 8051 Keil C có một nhân đó là RTX51.Với AVR là ….Trời tôi quên mất rồi vì hôm trước chỉ xem trên Web thôi họ không cho free nên không có (!!! Bác nào có thì share cho em nhé)

    Vấn đề sd nhân RTX51 thì cũng không có gì khó cả .Các bạn có thể xem phần hướng dẫn của Keil C là có hết.Tôi xin tóm tắt đôi chut :

    Các cú pháp của chương trình C thì hoàn toàn không có gì khác cả chỉ có khác về mặt cấu trúc.Các bạn không cần hàm “main” mà thay vào đó là hàm khởi tạo các task

    Ví dụ :

    void init (void) _task_ 0 { /* sau khi Reset chương trình sẽ chạy từ đây */

    os_create_task (1); /* Bắt đầu task 0 hoạt động */

    os_create_task (2); /* task 1 hoạt động */

    os_create_task (3); /* */

    os_delete_task (0); /*dừng khởi tạo các task */

    }

    Các bạn sẽ nói chẳg khác gì các chương trình C khác cả nhưng sự thật là cúng sẽ được thực hiện “đồng thời” và chỉ có thời điểm mỗi task bắt đầu là khác nhau mà thôi.

    Và các bạn khai báo các task “như”(theo nghĩa hình thức) các chương trình con mà các bạn cần thực hiện.

    Ví dụ:

    void readADC (void) _task_ 1

    {



    // nội dung



    }

    ….Vậy Task này có mã hiệu là 1 và là tham số cho hàm

    os_create_task (mã hiệu của task muốn khởi tạo.);

    Sau đay tôi xin gửi tới các bạn một chương trình mẫu của Keil C rất hay và cụ thể để các bạn tham khảo:

  • #2
    các bạn có thể tham khảo !

    Ví dụ của Keil và Help !

    Comment


    • #3
      Rất cảm ơn bài viết của bác VTC, em thấy rất thú vị. Hồi xưa bên dien dan dien tu có bác OD, bây giờ có bác VTC. Rất mong bác VTC phổ biến kiến thức.

      Về phần em, sẽ cố gắng thử lên mạng moi cái thư viện của Keil về RTOS.
      Bác VTC tiếp tục nhé.

      Comment


      • #4
        Bác VTC tiếp tục đi, em rất khoái cái này, mong bác góp phổ biến kiến thức cho bà con

        Comment


        • #5
          Lập trình đa nhiệm cho VĐK dùng Assembly

          Chào các bạn !

          Hôm trước tôi đã nói sơ về lập trình đa nhiệm cho VĐK và hướng dẫn chó các bạn dùng Keil C .Hôm nay tôi sẽ hướng dẫn cho các bạn các sử dụng Asembly (vì nó không mất tiền , và có tư duy trong sáng để các bạn hiểu hơn về lập trình đa nhiệm cho VĐK) .

          Do tôi không có nhiều thời gian và cũng không thể nói hết tất cả được với các bạn nên tôi chỉ có thể giới thiệu cho các bạn những gì trung nhất và một ví dụ cụ thể đơn giản nhất và phần còn lại đi sâu thì các bạn phải tự tìm hiểu từ các tài liệu tôi đã giới thiệu ở bài viết trước cho các bạn.

          Vậy để lập trình đa nhiệm được cho VĐK bằng Assembly thì bạn cần những gì ?Trước hết bạn phải là người đã lập trình thành thạo Assembly cho VĐK (đây là điều khiên quyết).Bạn hiểu sâu sắc về cấu trúc phần cứng mà VĐK của bạn sử dụng. Cụ thể là :Bạn cần nắm được cách mà ngăn xếp của bạn hoạt động như thế nào.Làm thế nào để bạn có thể quản lý được ngăn xếp và bộ nhớ một cách hợp lý.



          Các khái niệm cơ bản các bạn cần nắm được:

          1.Ngữ cảnh:Là trạng thái tại một thời điểm nào đó của hệ thống bao gồm giá trị của các thanh ghi chung,thanh ghi tích lũy và thanh ghi trạng thái cùng thanh ghi chương trình(con trỏ chương trình PC)

          2.Chuyển ngữ cảnh :Là hoạt động chuyển quyền sử dụng CPU từ task này sang task khác,Nó bao gồm các công việc:Lưu ngữ cảnh đang thực hiện(Lư PC,PSW,B,A,Rn,DPTR với 8051 và các thanh ghi tương tự với AVR…)và khôi phục trạng thái của ngữ cảnh mới(Khôi phục các thanh ghi trên).

          3.Task:Với Assembly thì task hoàn toàn là một đoạn mã lệnh đơn thuần và khác với cách nhìn của các phương pháp lập trình trước của các bạn.Task gồm tên task và kết thúc của một task là một lệnh nhảy vô điều kiện trở về đầu chương trình.

          Ví dụ:

          ReadADC:

          ;ReadADC là tên của task và chính xác hơn nó là một nhãn.

          ;đọang mã lệnh

          Ljmp ReadADC

          ;lệnh nhả về đầu của task kết thúc một chu kỳ của task

          4.Tài nguyên: Tài nguyên bao gồm các thiết bị ngoại vi như bộ nhớ ,các Port,ADC ,DAC(Được ghép thêm)…

          5.Ưu tiên: Là phương thức mà ta gán cho các task các quyền ưu tiên sử dụng CUP và tài nguyên.



          Bài viết này tôi không tham vọng nói được hết những gì mà các nhà kinh điển đã viết và những gì tôi ngộ được.Tôi chỉ có thể hướng dẫn các bạn cách thiết kế cho một chương trình đa nhiệm đơn giản không có tranh chấp tài nguyên ,không có ưu tiên (các task bình đẳng).

          Chúng ta sẽ bắt đầu với một ví dụ nhé:

          Lập trình cho 8051 với hai công việc là đọc cổng P1 và đưa dữ liệu ra cổng P2

          Như vậy với tư duy lập trình cấu trúc hoặc lập trình tuyến tính thì các bạn sẽ lấy dữ liệu từ ADC (cổng P1) sau đó sẽ chuyển ra cổng P2(DAC).

          Với tư duy lập trình đa nhiệm các bạn có thể thiết kế 2 task với task1 lấy dữ liệu và task2 chuyển dữ liệu ra cổng P2 (Ở đây tôi lấy ví dụ đơn giản cho các bạn dễ hiểu còn nếu bài toán thế này thì tất nhiên là dùng phương pháp lập trình tuyến tính thì hiệu quả hơn)

          Cấu trúc của chương trình hoàn toàn như một chương trình Assembly bình thường.

          Chúng ta sẽ sử dung timer 0 để là xung nhịp chia thời gian đơn vị.Và mỗi lần ngắt của timer là một lần chuyển ngữ cảnh (chuyển giữa các task).Như vậy chúng ta có 2 task đồng nghĩa với 2 vùng nhớ làm ngăn xếp để lưu trạng thái(ngũ cảnh).Một vùng để lưu dữ liệu dùng chung cho các task.Và các vùng nhớ này bạn caanf chú ý và bảo vệ không được phá hủy trong các task đặc biệt là các ngăn xếp vì điều đó sẽ làm hỏng toàn bộ chương trình hay cụ thể là CPU sẽ chạy loạn xạ các lệnh lên (Đây cũng là điểm yếu của Assembly-bạn phải tự quản lý tất cả).

          Bước 1:Thiết kế Kernel hay viết chương trình cho ngắt timer 0(hoặc timer nào đó mà bạn chọn)Kernel này là một nhân cơ bản nhất chỉ có hai nhiệm vụ:Định thời và chuyển các ngữ cảnh.Phần định thời ở đây ta sẽ chọn thời gian là sau 10uS sẽ ngắt một lần (chuyển ngữ cảnh)như vậy ta chọn timer0 chế độ tự load và giá trị các thanh ghi sẽ được thiết lập ở chương trình khi khởi tạo.Để chuyển ngữ cảnh và khôi phục ngữ cảnh bạn cần có một biến để nhận ra task đang thực hiện để quyết định chuyển sang một task nào đó khác.

          Comment


          • #6
            Int_Timer0:

            ;Lưu ngữ cảnh đang thực hiện

            Push psw

            Push acc

            Push b

            Push dpl

            Push dph

            Push r7

            Push r5

            Push r4

            Push r3

            Push r2

            Push r1

            Push r0

            Mov a,cpc

            Cjne a,#2 exits

            Mov stack2,sp;lưu gữ ngăn xếp

            Sjmp exits

            Mov stack1,sp

            Exits:

            ;Lưu xong ngữ cảnh

            ;Xác định task để trả lại ngữ cảnh

            Mov a,cpc

            ;cpc là biến trạng thái lư giữ tên của task đabg chạy (0,1,2,3…)

            Cjne a,#0 task0_run

            Mov cpc,#2 ;tăng con trỏ trạng thái lên 2 để báo task 2 đang ;chạy

            ;đây là lần chạy đầu tiên của task1 ngay sau khi khởi động

            Mov psw,#0

            Mov a,0

            Mov dptr,#task2

            Mov sp,stack2

            ;với stack2 là một ô nhớ lưu vị trí khởi tạo đầu của ngăn xếp ;cho task2 và được khởi tạo khi bắt đầu chạy

            Push dpl

            Push dph

            ;Lưu vị trí của task2

            Sjmp exit

            task0_run: Cjne a,#1,task2_run

            ;nếu cpc =1 thì task1 đang chạy

            ;khôi phục lại task2

            Mov sp,Stack2 ;trở lại ngăn xếp của task2 ở đây thì stack2 lại là ;đỉnh ngăn xếp rồi

            Pop r0

            Pop r1

            Pop r2

            Pop r3

            Pop r4

            Pop r5

            Pop r6

            Pop r7

            Pop dph

            Pop dpl

            Pop b

            Pop acc

            Pop psw

            Inc pcp;tăng con trỏ chương trình lên 2 (task2 chiếm CPU)

            Sjmp exit

            ;đây là trường hợp cpc=2

            ;task2 đang chiếm CPU thì bị ngắt

            ;khôi phục lại task1

            Mov sp,stack1

            Pop r0

            Pop r1

            Pop r2

            Pop r3

            Pop r4

            Pop r5

            Pop r6

            Pop r7

            Pop dph

            Pop dpl

            Pop b

            Pop acc

            Pop psw

            Mov cpc,#1

            ;task1 chạy

            Exit:

            Reti



            Chương trình mẫu (để các bạn tham khảo vì lâu rồi không viết cho 8051 đôi chút cũng sai):

            Stack1 equ 07FH ;bien trang thai

            Stack2 equ 07EH ;bien trang thai

            Cpc equ 07DH ;bien trang thai

            GenralR equ 07EH ;bien du lieu dung chung

            Org 00h

            Ljmp start

            Org 00BH

            Ljmp int_timer0 ;ngat int0

            Org 0030H

            Start:

            ;đoạn khởi tạo chương trình

            Mov psw,#00

            ;cấm các ngắt

            ;thiết lập timer 1 chế độ tự load và tính toán sao cho sau 10uS thì ngắt ;một lần phần này các bạn tự viết.

            Mov Stack1,#0h

            Mov Stack2,#03Fh

            Mov SP,#02Fh

            Mov cpc,#0 ;khởi tạo con trỏ task

            ;cho phép ngắt

            Task1:

            ;Lấy dữ liệu từ ADC (P1) đưa vào thanh ghi GenaralR

            Ljmp task1 ;kết thúc task

            Task2:

            ;lấy dữ liệu từ thanh ghi GenaralR dưa ra DAC qua Port P2

            Ljmp task2;Kết thúc task 2

            Int_timer0:

            ;nội dung như trên

            ;Hết chương trình.

            Chú ý rất quan trọng:Nếu như trong các task các bạn muốn sử dụng ngăn xếp thì cács bạn cần phải sửa lại Kernel cho phù hợp.(điều này giành cho các bạn)và đặc biệt các biến trạng thái thì các bạn không được thay đổi trong các task.Để đặt mức ưu tiên và SD chung tài nguyên thì các bạn cần có các biến trạng thái tương ứng để lưu trạng thái đã bị chiếm của tài nguyên và mức ưu tiên của các task.(Ở đây chưa tính đến thời gian tới hạn của một task ).Các thuật toán các bạn đọc tại cuốn sách mà bài viết trước tôi đã nói tới.

            AVR hay các vi điều khiển khác thì nguyên tắc tương tự (Trừ PIC có ngăn xếp riêng thì hơi khác.Mong bạn nào viết nhiều cho PIC thì cùng chia sẻ với anh em.)

            Chúc các bạn thành công !

            TB:Nhân tiện đây xin hỏi bác nào biết chỗ nào ở Hà nội làm mạch in 2 lớp rẻ không ???và còn AVR nữa tôi muốn mua mấy con làm đồ án mà đắt quá trời !!!

            Comment


            • #7
              Sheduler

              Chào các bạn !

              Bài viết trước tôi đã giới thiệu cho các bạn về lập trình đa nhiệm cho VĐK bằng assembly nhưng phương pháp đó là thuật toán đa nhiệm theo khung thời gian (time-slice) và đây cũng là thuật toán mà Keil C sử dụng.

              Nhưng đó chưa hẳn là lập trình thời gian thực vì các bạn chưa hề biết được thời gian mà tiến trình đó thực hiện và không biết được rằng tiến trình đó có kết thúc trước thời gian cho phép hay không.

              Định nghĩa hệ thời gian thực là các phản ứng của hệ thống phải “đủ nhanh” để đáp ứng được với sự thay đổi của đầu vào.”Đủ nhanh” có nghĩa là gì? Đối với một lập trình viên thì đủ nhanh có nghĩa là bạn phải biết trước được khoảng thời gian giới hạn mà sự khiện đó đặt ra (ví như :các bạn cần điều chỉnh sự thay đổi nhiệt độ của một nồi cơm điện trong khoảng thời gian cho phép là 2 s nếu không cơm của bạn sẽ bị cháy) và chương trình của bạn cũng phải lập trình sao cho chương trình xử lý và điều khiển nhiệt độ phải chạy sao cho chúng kết thúc chu kì trước 2 s. Và một điểm không thể nói tới :bạn có các công việc và không phải công việc nào cũng quan trọng như nhau ví như trong máy giặt :các bạn có các công viêc như quét bàn phím, hiển thị chỉ dẫn,thông báo,điều khiển quá trình giặt … vậy thì việc gì quan trọng hơn chắc chán là khi mà người ta sư dụng đến bàn phím thì việc hiển thị là việc rất quan trọng ,nhưng khi mà bàn phím không được sử dụng thì việc điều khiển là việc quan trọng hơn.Và một việc không thể không nói tới đó là khi mà các bạn có các tiến trình dùng chung tài nguyên thì sẽ như thế nào?

              Một phương pháp được sử dụng trên mọi hệ điều hành đa nhiệm đó là phương pháp lập lịch (sheduling)

              1.Sheduling là gì?

              Một Sheduler tương tự như một hệ thống time-slice nhưng nó theo dõi các task và điều khiển quyền sử dụng CPU ,tài nguyên của các task,theo các thuật toán đã định trước.

              2.Các loại cấu trúc của Sheduler

              Sheduler có 3 cấu trúc chính:

              + Theo mức ưu tiên

              +Theo deadline (thời gian hạn chế).

              +Theo điều kiện thực tế.



              Hôm nay tôi sẽ giới thiệu cho các bạn phương pháp lập lich theo cấu trúc mức ưu tiên (có chia sẻ tài nguyên).

              Thực sự mà nói đây là một phần rất khó và rất thú vị đòi hỏi các bạn cần phải tính toán thực tế và trên lý thuyết trước khi lập trình và trong khi lập trình.Và quá trình vận hành cần được kiểm định kĩ lưỡng.

              Bài toán đặt ra:

              Tôi có 3 task T1,T2,T3 và trên hệ thống có 3 loại tài nguyên A,B,C và 3

              Task
              Mức ưu tiên
              Trình tự thực hiện
              Thời gian bẳt đầu

              T1
              3
              ABNC
              2

              T2
              2
              AACNN
              1

              T3
              1
              BANC
              0


              Tôi xin giải thích đôi chút:

              Chúng ta sẽ chia chu kì thực hiện thành các đơn vị thời gian và mỗi task sẽ thực hiện trong một số đơn vị thời gian nào đó.Ví dụ Task T1 cần 5 đơn vị thời gian và lần lượt thực hiện :tại đơn vị thời gian thứ nhất T1 dùng tài nguyên A,đơn vị thứ 2 dùng tài nguyên A,đơn vị thời gian thứ 3 dùng tài nguyên B ,đơn vị thời gian thứ 4 chỉ dùng CPU và không dùng tài nguyên nào khác.

              Hoàn toàn tương tự với các Task 2,3.

              Mức ưu tiên :do các bạn gán cho chúng với T1 mức ưu tiên cao nhất…

              Thời gian bắt đầu là thời gian bắt đầu được chạy của một task.

              Các nguyên tắc:

              Nguyên tắc dùng chung tài nguyên: Khi tài nguyên đã bị một task nào đó chiếm thì task cần sử dụng phải đợi cho tới khi mà tài nguyên đó được giải phóng thì mới được sử dụng.

              Nguyên tắc về mức cùng mức ưu tiên: Khi hai task cùng mức ưu tiên thì task nào đang chạy sẽ tiếp tục được chạy.



              Phân hạchtheo mức ưu tiên thì có nhiều thuật toán nhưng tôi sẽ giới thiệu cho các bạn một thuật toán đoen giản nhất và các thuật toán còn lại các bạn phải tự nghiên cứu.Đó là phân hạch theo mức ưu tiên cố định.





              Như vậy Task3 sẽ chạy trước và sau 1 đơn vị thời gian task 2bắt đầu chạy có mức ưu tiên cao hơn lênh được chạy .Đến điểm 2 thì task1 được khởi động có mức ưu tiên cao nhất nhưng tài nguyên A đã bị task 2 chiếm vì vậy task2 tiếp tục thực hiện cho tới khi giải phóng tài nguyên A và khi đó task1 chạy cho tới hết task1 và nhường lại quyền cho task2 rồi task 3






              Biểu đò phân hạch (Tôi vẽ hơi xấu hì hì !!!)

              Như vậy các bạn đã tính toán được cách phân hạch theo thuật toán này.

              Để lập trình thì các bạn cần bắt đầu từ đâu ?

              Tôi sẽ hướng dẫn các bạn : (Phần này rất khó và các trình dịch C cho VĐK mà tôi biết (Keil C,GccAVR,CodevisionAVR)không hỗ trợ,các bạn tự phải xây dưng bằng Assembly)

              1.Các bước tiến hành thiết kế và tính toán viết lệnh cho Kernel:

              Bước 1:

              Xác định số task và nhiệm vụ của từng task.

              Bước 2:

              Viết lưu đồ thuật toán cho task và xác định thời điẻm chiếm tài nguyên nào đó của mỗi task.

              Ở bước này có thể bạn phải viết mã lệnh cụ thể cho một task và tính tương đối chính xác thời điểm và thời gian chiếm tài nguyên của mỗi task.

              Bước 3:

              Tính toán để chọn thời gian dơn vị cho sheduling .

              Bước 4:

              Lập bản như ở ví dụ trên (bạn được quyền gán mức ưu tiên cho tiến trình nào mà bạn cảm thấy cần thiết)

              Bước 5:

              Vẽ biểu đồ phân hạch như trên.

              Bước 6:

              Viết nhân Kernel



              Một ví dụ cụ thể nhé:

              Lấy số liệu

              VĐK

              Đối tựong khiển

              Gửi dữ liệu lên mạng


              Từ sơ đồ các bạn thấy đấy : VĐK lấy số liệu từ các thiết bị đo (các thông số về đối tượng đièu khiển sau đó tính toán từ các số liệu đó theo luật điều khiển nào đó (như PIDchẳng hạn…) sâu đó đưa ra quyết định điều khiển.Và đồng thời chúng sẽ gửi kết quả đo này lên mạng truyền thông công nghiệp chẳng hạn.

              Như vậy chúng ta có 3 tiến trình:

              T1: Lấy số liệu (nhiệt độ ,áp suất,độ ẩm)đưa vào vùng nhớ nào đó (ví như có địa chỉ từ 0x40 đến 0x45 chẳn hạn)

              T2: Tính toán một số các số liệu thu được từ bộ nhớ(nhiệt độ và áp suất thu được kết quả và kết quả đó được đem điều khiển nhiệt độ của đối tượng) và xuất tín hiệu điều khiển

              T3: Gửi kết quả đo lên mạng công nghiệp (kết quả từ bộ nhớ trên)

              Và tài nguên dùng chung ở đây là :Các ô nhớ lưu khết quả đo là tài nguyên này bị cạnh tranh khi các task muốn sử dụng(tại sao lại như vậy,có nghĩa là khi mà ta đang tính toán ra các tham số điều khiển thì ta không được phép ghi số liệu vào các thanh ghi chứa số liệu của nhiệt độ và áp suất; nếu như số liệu mới được ghi vào một trong hai thông số trên thì hậu quả thế nào chắc các bạn đã biết !!!)

              Vậy ta xác định được một tài nguyên dùng chung của 3 task là vùng nhớ dữ liệu(và đây là tài nguyên xung đột).

              (Chú ý :Tài nguyên dùng chung có hai loại:loại sử dụng cạnh tranh (xung đột),và loại chia sẻ)

              Gọi đây là tài nguyên A.

              Giả thiết rằng T1 có 4 việc là lấy dữ liệu từ 4 vào : kênh 1 đo nhiệt độ,kênh 2 đo áp suất (các yết tố cần thiết cho điều khiển)và kênh 3 đo độ ẩm và kênh 4 đo cái gì đó…

              Viết mã lệnh cho task1:

              Task1:

              ……

              ……

              ……

              Endtask1

              Chú ý khi một task kết thúc không giống như hôm trước (các bạn dùng phân chia thời gian đề đặn) với phương pháp này các bạn khi mà kết thúc một task thì phải thông báo cho Kernel biết và gọi nhân kernel (Thông báo bằng cách nào nhỉ???các bạn cần thiết lập một biến lưu trạng thái của task .Vậy gọi Kernel thế nào nhỉ ??? Rất đơn giản tạo ra ngắt thời gian bằng cách set bit ngắt của timer mà bạn dùng làm định thời cho nhân Kernel).

              Ví dụ:

              Macro Endtask

              Setb End_task ;set bit trạng thái

              Setb TF0 ;Set bit tràn Timer 0

              Endmacro

              Comment


              • #8
                Ngắt trong lập trình đa nhiệm !!!

                Phần này viết chỉ đối với thuật toán chia thời gian như bài “Lập trình đa nhiệm cho VĐK “mà tôi viết hôm trước.



                Để lập trình đa nhiệm dùng ngắt chúng ta có hai phương pháp:

                Phương pháp 1: Bất cộng tác nói các khác ngắt này có mức ưu tiên cao nhất (cao hơn mức ưu tiên của ngắ xung nhịp của Kernel.)như vậy thì phương pháp này hoàn toàn giống như các bạn dùng ngắt thông thường.Phương pháp này có điểm mạnh là dễ lập trình bạn chỉ cần thiết lập sao cho ngắt này có mức ưu tiên cao hơn ngắt thời gian của Kernel và viết một chương trình phục vụ ngắt như truyền thống các bạn viết.Nhưng chú ý các bạn cần lưu lại ngữ cảnh và phục hồi ngữ cảnh trước khi ngắt kết thúc(chúng ta thường dung phương pháp này khi mà các thông báo ngắt có tầm quan trọng rất cao đôi với hệ thống.)

                Phương pháp 2:Phương pháp công tác .Đây là phương pháp mà ngắt được xem như là một task thông thường khác.Chỉ khác là Task này chỉ được khởi động khi có cờ báo ngắt và sẽ kết thúc hoạt động khi mà hết chương trình phục vu ngắt. Phương pháp này cũng giống như phương pháp 1 ở điểm nó cũng có một chương trình phục vu ngắt nhưng chương trình này chỉ có một nhiệm vụ là báo cho Kernel biết ngắt đó cần được phục vụ (và có thể cấm chính nó để khi phục vụ xong sẽ được cho phép trở lại.)(Chú ý : Hạn chế ngắt trong ngắt vì do chúng ta cần nhiều ngăn xếp để lưu ngữ cảnh vì thế ngắt trong ngắt sẽ làm cho tràn bộ nhớ !!!)

                Rủi ro trong phương pháp này là :Nếu như ngắt này có mức ưu tiên thấp hơn ngắt thời gian của hệ thống (ngắt xung nhịp Kernel) mà chúng lại xuất hiện khi mà ngắt hệ thống đó đânghọt động thì chúng sẽ bị bỏ qua vì vậy các bạn chú ý điều này.Một điểm chú ý khác là chương trình phục vụ của ngắt này gồm 2 phần : phần 1 là chương trình phục vụ ngắt như các ngắt khác và phần 2 là task của nó.



                Như vậy thì hai phương pháp này đề có các điểm mạnh yếu khác nhau và trong một hệ thống lớn thì người ta thường dùng cả hai phương pháp.Ví dụ như :Scan bàn phím thì ta dung phương pháp 2 và điều kiển sự thay đổi của một đối tượng nào đó theo ngưỡng thì ta lên dùng phương pháp 1.

                Tôi sẽ đưa ra một ví dụ cho các bạn tham khảo.

                Ví dụ :

                Các bạn cần thiết kế một hệ thống đo các thông số như nhiệt độ ,áp suất của một đập nào đó của nhà máy thủy điện Hòa Bình theo một thời gian nào đó nhập vào từ bàn phím gửi về trung tâm và điều khiển mức nước sao cho luôn cao hơn một mức mà ta đã định sẵn.Cấu hình của thiết bị được thiết lập thông qua bàn phím.(Đây chỉ là một ví dụ do tôi nghĩ ra thôi nhé !!!)

                Phân tích bài toán:

                Ta có các công việc chính như sau:

                1.Đo các thông số và gửi về trung tâm .

                2.Điều khiển mức (1 ngưỡng)

                3.Giao tiếp với bàn phím và màn hình hiển thị.

                Đánh giá công việc và chọn giải pháp:

                1.Đo các thông số và gửi về trung tập theo thời gian định trước :Các bạn cần liên tục kiểm tra thời gian của RTC xem đã đến thời điểm lấy mẫu chưa và đây là quá trình hoạt động liên tục.

                2.Điều khiển mức :Đây là công việc rất quan trong và không liên tục vì vậy chúng ta sẽ sd ngắt và dung phương pháp 1 (bất cộng tác khi mà mức nước thấp hơn sẽ ưu tiên toàn bộ cho hoạt động điều khiển theo một luất điều khiển náo đó.)

                3.Giao tiếp với bàn phím và màn hình hiển thị:Đây là quá trình không liên tục và ta sử dụng ngắt.Do thời gian trể của phím lới … nên ta sd phương pháp cộng tác.



                Viết phần mềm cho hệ thống :Gồm các bước :

                Xây dụng các task,các ngắt và Kernel.

                Các bạn có thể tham khảo thêm bài “lập trình đa nhiệm cho vi điều khiển” Hôm sau tôi sẽ viết chương trình cho các bạn (nhưng chỉ là khung chương trình)

                Comment


                • #9
                  Không có ai viết tiếp giúp mình nhỉ ? Bận qua chưa thể viết tiếp được !

                  Comment


                  • #10
                    Hôm trước viết mà quên mất không nhắc các bạn bon Keil dùng timer0 làm đồng hồ cho Kernel vì vậy các bạn không thể swr dụng được timer 0.

                    Comment


                    • #11
                      Thiết kế RTOS bằng ngôn ngữ assembly và sử dụng trong môi trường lập trình assembly sẽ dễ thiết kế kernel hơn vì ta chỉ cần bảo toàn stack và thanh ghi chúng ta sử dụng, điều này rất dễ nhận biết trong quá trình lập trình và các biến khai báo thường sử dụng biến toàn cục. Nhưng nếu thiết kế trên ngôn ngữ bậc cao như C thì cần phải tạo data stack (lưu các biến cục bộ), system stack (lưu địa chỉ gọi hàm, tham số truyền của hệ thống ...) cho từng task và mỗi trình biên dịch sẽ có cơ chế cấp phát bộ nhớ và truyền biến khác nhau. Khi đó ngữ cảnh của một task mới được bảo vệ một cách an toàn. Hơn nữa, một RTOS không thể thiếu được cơ chế WaitTask và cơ chế Semaphore. Còn giải thuật chuyển ngữ cảnh thì có thể dùng preempty hay round-robin cũng được. Đa số RTOS dựa trên MCU còn hỗ trợ cái gọi là manual switching context, cái này dùng khi một đối tượng điều khiển cần tác động với mức ưu tiên cao nhất và nhanh nhất.
                      Nếu được, chúng ta bắt tay vào viết một cái RTOS cho AVR dùng trình biên dịch CodeVision C Compiler cái nhỉ? Không biết có ai có hứng thú không? RTOS của người Việt nam.

                      Comment


                      • #12
                        Cái switch task cho tới hôm nay đã trỏ thành cái bình thường rồi. Chỉ cần 400 byte và vài chục byte RAM là làm được. Nhưng cái quan trọng của hệ điều hành là làm sao cho người dùng phát triển ứng dụng trên đó nhanh nhất. Khi đo, các thư viện hàm API trở nên quan trọng hơn. Dù với ứng dụng nào programmer cũng có sắn các hàm để dùng luôn. Các bạn hãy thử tham khảo mã nguồn của HDDH linuk. Phần kernel chỉ là một phần rất nhỏ. Quan trọng là các bộ phận đi kèm cơ.
                        Hiện nay tôi thấy 1 HDH ngon cần có:
                        - Kernel task.
                        - TCP/IP stack.
                        - Modem controler.
                        - Webserver,telnet,ftp.
                        - File system.
                        - Database engine.
                        - Peripherial driver.
                        - Một số ba lăng nhăng điều khiển các thiết bị ngoài: ADC,DAC,RealTimer,....
                        Mình mong muốn cải biên cái linux thành một hệ mở để mọi người cùng hưởng ứng và phát triển.
                        Hệ điều hành là cái nền móng và đống gạch, gỗ, đá chưa thành hình. Bạn tùy ứng mà xây dựng nên sản phẩm. Không nên tự đóng gạch, xẻ gỗ để xây nhà==>hãy sử dụng HDH và post bài . .. . .
                        Nhà sản xuất chuyên nghiệp các sản phẩm OEM cho gia dụng và công nghiệp.

                        Biến tần
                        Máy giặt
                        Lò vi sóng
                        Bếp từ.
                        Tủ lạnh.
                        Điều hòa

                        Comment


                        • #13
                          Nguyên văn bởi MinhHa
                          Cái switch task cho tới hôm nay đã trỏ thành cái bình thường rồi. Chỉ cần 400 byte và vài chục byte RAM là làm được. Nhưng cái quan trọng của hệ điều hành là làm sao cho người dùng phát triển ứng dụng trên đó nhanh nhất. Khi đo, các thư viện hàm API trở nên quan trọng hơn. Dù với ứng dụng nào programmer cũng có sắn các hàm để dùng luôn. Các bạn hãy thử tham khảo mã nguồn của HDDH linuk. Phần kernel chỉ là một phần rất nhỏ. Quan trọng là các bộ phận đi kèm cơ.
                          Hiện nay tôi thấy 1 HDH ngon cần có:
                          - Kernel task.
                          - TCP/IP stack.
                          - Modem controler.
                          - Webserver,telnet,ftp.
                          - File system.
                          - Database engine.
                          - Peripherial driver.
                          - Một số ba lăng nhăng điều khiển các thiết bị ngoài: ADC,DAC,RealTimer,....
                          Mình mong muốn cải biên cái linux thành một hệ mở để mọi người cùng hưởng ứng và phát triển.
                          Hệ điều hành là cái nền móng và đống gạch, gỗ, đá chưa thành hình. Bạn tùy ứng mà xây dựng nên sản phẩm. Không nên tự đóng gạch, xẻ gỗ để xây nhà==>hãy sử dụng HDH và post bài . .. . .
                          Vậy thì tôi khuyến cáo nên dùng PC , nếu phát triển thiết bị handheld thì mua một cái O2 hay mấy cái nokia chạy hệ điều hành Simbian 60 rồi lập trình application trên nó là giải pháp tuyệt vời nhất. Nói thật chứ, tôi chưa thấy một hệ VDK nào có cả database engine , những cái khác hoàn toàn có thể và đều có sẵn dưới dạng các thư viện rời rạc rồi. Người sử dụng chỉ việc nhét những cái mình cần vào 1 cái core kernel thôi. Như thế hệ mới tối ưu và linh hoạt chứ all in one trong 1 con MCU thi` quả là không tưởng và tôi tin rằng không ai muốn làm thế với lý do giới hạn của bộ nhớ Flash trong MCU.

                          Comment


                          • #14
                            Nghe nói bác MinhHa làm thành công hệ điều hành nhúng này 2-3 năm về trước trên 386 mà tích hợp đủ thứ như bác kể trên? Công lực bác cao thật.
                            Còn làm trên mấy con uC nửa vời lấy làm khó chịu lắm. Nhất là sự kế thừa và tiện dụng.
                            Last edited by vutricongbka; 20-12-2005, 16:33.
                            -------------------

                            Comment


                            • #15
                              Vậy thì phải nhìn lại cái topic này trước khi post bài nhé, mấy bố

                              Lập trình đa nhiệm cho vi điều khiển

                              Comment

                              Về tác giả

                              Collapse

                              vutricongbka Tìm hiểu thêm về vutricongbka

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X