Giải mã chập
-
Upload
pham-hoang-anh -
Category
Documents
-
view
480 -
download
8
Transcript of Giải mã chập
Lời nói đầu
Trong lĩnh vực truyền thông, các quá trình mã hóa và giải mã được sử dụng
nhiều với các chức năng khác nhau nhằm đảm bảo tính bảo mật, độ tin cậy cao khi
truyền tin. Do đó, việc xây dựng các phương pháp mã hóa, giải mã, việc chọn lựa
các tham số cho bộ tạo mã (encoder) và các bộ giải mã (decoder) là rất quan trọng
trong truyền tin an toàn. Cho đến nay, thông thường các phương pháp mã hóa và
giải mã chỉ được phân tích trên cơ sở phương pháp xử lý tín hiệu truyền thống,
biểu diễn theo thời gian, tần số hay không gian. Tuy vậy, dù được phân tích trên
cơ sở nào, thì việc thiết lập các bộ tạo mã hay giải mã đều được thực hiện dựa vào
các mô hình khối ở bước ban đầu. Hay nói cách khác, việc thiết lập các bộ tạo mã
hay giải mã chính là việc xây dựng một mô hình hệ thống với đầu vào là tin tức,
đầu ra là các từ mã và các biến trạng thái có trong hệ thống. Vì vậy, việc nhìn
nhận mã hóa và giải mã trên quan điểm lý thuyết hệ thống là có cơ sở thực hiện.
Đặc biệt, việc nghiên cứumã sửa sai trên quan điểm lý thuyết hệ thống có tầm
quan trọng đối với việc tìm các mã có khả năng sửa sai tốt, cần ít bit dư thừa, hay
tìm ra các mã mạnh kết hợp với khả năng quan sát, điều khiển đồng thời để tối ưu
hóa quá trình mã hóa và giải mã.
Trong khuôn khổ của môn học, mã chập được sử dụng để phân tích và làm
rõ thêm về việc biểu diễn mã trong không gian trạng thái. Ngoài ra, project còn
biểu diễn một bộ tạo mã và giải mã chập sử dụng phần mềm Matlab2010 nhằm có
cái nhìn rõ hơn về quá trình tạo mã và giải mã. Do hạn chế về thời gian tìm hiểu
nên để tài còn nhiều thiếu sót và kính mong cô chỉ bảo để đề tại được bổ sung
trong thời gian tới.
Page 1
Mục LụcChương 1.Lý thuyết về mã chập.......................................................................................................3
1.1. Bộ tạo mã chập.............................................................................................................3
1.2. Bộ giải mã chập............................................................................................................5
Chương 2: Mô phỏng bộ mã hóa và giải mã mã chập.....................................................................8
2.1. Mô hình của bộ mã hóa................................................................................................8
2.2. Kết quả mô phỏng......................................................................................................10
Kết luận.............................................................................................................................................12
Tài liệu tham khảo...........................................................................................................................13
Page 2
Chương 1.Lý thuyết về mã chập
1.1. Bộ tạo mã chập
Mã chập là một loại mã sửa sai được sử dụng trong mã hóa kênh với từ mã
được tạo ra nhờ việc cộng các bit thông tin và các bit có trong các thanh ghi dịch.
Để tạo ra mã chập, ta dùng bộ lập mã chập có nguyên tắc hoạt động dựa vào việc
“chập” dòng bit thông tin đầu vào với đáp ứng xung của bộ tạo mã. Do đó, một
dãy thông tin nhị phân u được chia thành kí tự dk=(dk(0),…..,dk
(k-1)). Các kí tự này
được ánh xạ thông qua bộ tạo mã gồm n bit. Hai tham số quan trọng của một từ
mã chập là tốc độ mã R = k/n và độ dài ràng buộc Kc = M+1 với M là số lượng
các thanh ghi dịch có trong bộ mã (độ dài ràng buộc là thời gian trải rộng của các
bit mà mỗi bít đầu vào ảnh hưởng lên). Hình 1 mô tả một bộ giải mã có tốc độ là
½, độ dài ràng buộc Kc = 3.
Hình 1. Sơ đồ khối và sơ đồ chuyển trạng thái của bộ tạo mã chập
Hình 1 cũng chỉ ra sơ đồ chuyển trạng thái tương ứng với các thanh ghi
dịch phía bên trái.Với các mã chập, việc mô tả bộ tạo mã bằng sơ đồ trạng thái sẽ
thuận lợi hơn. Nếu bộ lập mã có M thanh ghi dịch thì sẽ có 2M trạng thái S(m) với m
= 0,…,2M-1. Mỗi trạng thái được biểu diễn bởi một nút và sử chuyển đổi các trạng
thái được biểu diễn bằng các mũi tên. Trên các mũi tên mô tả bit đầu vào dk tương
ứng với các kí tự đầu ra xk được viết là dk/xk(0)x(1)
k.
Biểu đồ mắt cáo (trellis diagram) trong hình 2 mô tả sự chuyển đổi các
trạng thái theo thời gian. Với mỗi đầu vào dk, biểu đồ mắt cáo sẽ có tất cả các khả
năng dịch chuyển trạng thái có thể xảy ra.
Page 3
Hình 2. Biểu đồ mắt cáo thể hiện quá trình chuyển trạng thái theo thời gian
Giả sử trạng thái ban đầu của bộ tạo mã là trạng thái S(0). Biểu đồ mắt cáo
có thể được chia thành 3 pha: Với một bản tin có chiều dài là L, sau pha khởi tạo
của M bit được mã hóa dk, sẽ có L – M segment giống hệ nhau. Sau khi bản tin có
chiều dài L được mã hóa hết, thì bộ tạo mã sẽ chuyển về trạng thái ban đầu bằng
cách thêm vào M kí tự. Do đó, chiều dài của từ mã được tăng lên LT = L + M. Kĩ
thuật thêm M kí tự này sẽ làm cải thiện khả năng bị lỗi tại điểm cuối của bản tin
được mã hóa.
Để hiểu rõ hơn về biểu đồ mắt cáo, ta xem xét hình 3. Hình 3 biểu diễn quá
trình tạo từ mã sử dụng biểu đồ mắt cáo với bản tin có độ dài 12 bit với nội dung
d= (0,1,0,1,1,0,0,1,1,1,0,0) và được 24 bit từ mã đầu ra xk
Hình 3. Ví dụ về sử dụng biểu đồ mắt cáo với đầu vào cho trước
1.2. Bộ giải mã chập
Page 4
Có nhiều phương pháp giải mã chập. Tuy nhiên, trong project này, chúng ta
sẽ đề cập đến thuật toán giải mã chập Viterbi. Lý thuyết chung của thuật toán này
là nhằm tìm ra đường ngắn nhất có trong biểu đồ mắt cáo , đường dẫn đến một
trạng thái S(k) phải là đường ngắn nhất có thể. Thuật toán này có thể được chia
thành hai bước: 1) tính toán giá nhánh (branch metric), giá đường (path metric) và
các bit quyết định. 2) traceback. Trong pha 1, sự sai khác giữa kí tự nhận yk và tất
cả các kí tự khác mà có khả năng nhận được được tính toán. Trong trường hợp
hard decision mà các kí tự chỉ là bit 0 hoặc 1, thì khoảng cách Hamming đươc sử
dụng để tính brach metric. Khoảng cách Hamming sẽ tính số bit sai khác trong kí
tự nhận được với số bit trong các kí tự có khả năng nhận được. Trong ví dụ ở phần
1, khoảng cách Hamming có thể là 0, 1, 2. Kết quả sẽ được lưu trong path
metric.Với mỗi bước k, khoảng cách Hamming cho mỗi trạng thái Sk được tính
toán và được cộng vào path metric của các trạng thái trước đó (k-1). Trong pha
thứ 2, thuật toán Viterbi sẽ dò ngược lại để xác định ra chuỗi kí tự gần nhất. Trạng
thái ban đầu trong pha dò ngược là trạng thái có path metric thấp nhất.
Để hiểu rõ hơn về thuật toán Viterbi. Chúng ta tiếp tục xét ví dụ trong phần
1 với từ mã cuối cùng nhận được yk bị sai khác so với từ mã sau bộ lập mã xk do
quá trình truyền dữ liệu. (Hình 4)
Hình 4. Ví dụ về thuật toán Virterbi
Sau quá trình truyền, yk bị sai khác so với xk tại những bit được tô màu đỏ
như trên hình 4. Bước đầu để giải mã kí tự thu là tạo ra bảng tra LUT mô tả sơ đồ
chuyển trạng thái. Bảng tra này được dùng để tính toán khoảng cách Hamming.
Page 5
Hình 5. Ma trận chuyển trạng thái
Như trong hình 4, S(0) sẽ chuyển đến 1 trong hai trạng thái là S(0) hoặc S(2)
sau khi nhận kí tự truyền đầu tiên. Do kí tự nhận được y1 = 00, nên kí tự này sẽ
được so sánh với hai kí tự tại hai trạng thái chuyển có thể có là S(0) và S(2). Nếu
S(0)-> S(0) thì khoảng cách Hamming là 0 và nếu chuyển tới S(2) thì khoảng cách
Hamming là 2. Giá trị này sẽ được lưu lại tại các nút tương ứng bên trong mắt
cáo.Giá trị này sẽ được tiếp tục tính toán tại các mắt khác nhau sau mỗi lẫn
chuyển trạng thái và được cộng dồn cả giá trị của trạng thái trước. Tại mỗi trạng
thái, sẽ có những giá trị path metric của các trạng thái trước đó được cộng dồn ,
những giá trị này được so sánh với nhau và giá trị nhỏ hơn sẽ được trọn là path
metric tại thời điểm đó. Nối tất cả các mắt cáo có path metric nhỏ nhất tại từng
thời điểm, ta sẽ có sơ đồ chuyển trạng thái tối ưu nhất. (đường màu đỏ trên Hình
6).
Hình 6. Kết quả thực hiện pha 1 của thuật toán Virterbi
Sau khi kết thúc pha 1, pha 2 sẽ thực hiện việc traceback dựa theo sơ đồ
chuyển trạng thái đã có của pha 1. Để khởi tạo traceback, trạng thái có path metric
Page 6
nhỏ nhất sẽ được đưa vào một thanh ghi dịch 2 bit, trong ví dụ này là 00. Giá trị
này chính là con trỏ để chọn các bit lựa chọn. Quá trình traceback được mô tả
trong hình 7.
Hình 7. Quá trình Traceback
Tổ hợp các bit được đẩy ra khỏi thanh ghi dịch 2 bit tạo thành bản tin ban
đầu (các bit màu vàng). Từ đó ta kết thúc quá trình giải mã mã chập.
Page 7
Chương 2:
Mô phỏng bộ mã hóa và giải mã mã chập
Trong chương này, một bộ tạo mã chập và giải mã được xây dựng và mô
phỏng sử dụng công cụ Simulink của Matlab 2010.Đầu tiên, mô hình của bộ mã
hóa được đưa ra.Sau đó; chúng ta thiết lập sơ đồ khối sử dụng các khối trong
Simulink để thực hiện việc mã hóa và giải mã mã chập.Cuối cùng, kết quả mô
phỏng sẽ được đưa ra để kiểm chứng.
2.1. Mô hình của bộ mã hóa
Bộ mã hóa mã chập được mô tả trong hình 8 như sau:
Hình 8. Mô hình bộ mã hóa mã chậpMô hình trên biểu diễn bộ tạo mã có tốc độ code rate = 1/2 (1 đầu vào, 2
đầu ra), có độ dài ràng buộc là Kc = 7 (6 thanh ghi dịch + 1 đầu vào). Về mặt toán
học, bộ mã chập trên được hình thành bởi ma trận đa thức có dạng:
Z4+Z3+Z2+Z+1Z6+Z5+Z 4+Z3+Z+1
Từsơđồ mô hình bộ mã hóa mã chập trên, chúng ta sử dụng công cụ
Simulink của Matlab nhằm xây dựng một bộ mã hóa và giải mã mã chập với mô
hình như trong hình 8 như sau:
Page 8
Hình 9.Mô hình mã hóa và giải mã mã chập
Trong mô hình trên, quá trình mã hóa và giải mã mã chập được mô tả
thông qua 4 khối.Đầu tiên, tín hiệu bản tin bất kì được tạo ra một cách ngẫu nhiên
thôn qua bộ tạo mã nhị phân Bernoulli. Sau đó, chuỗi bit nhị phân này được đưa
lần lượt vào bộ mã hóa mã chập rồi đưa quá kênh truyền nhị phân với một xác
suất lỗi kênh truyền nhất định và cuối cùng được giải mã qua bộ giải mã sử dụng
thuật toán Virterbi. Bộ mã hóa mã chập được xây dựng bằng việc khai báo các
thông số cho biểu đồ chuyển trạng thái (Trellis structure) được có trong bộ mã hóa
mã chập. Cách khai báo như sau:
Trellis = poly2trellis ([chiều dài ràng buộc], [ hệ số trong đa thức sinh dưới dạng
bát phân])
Hàm Poly2trellis có nhiệm vụ chuyển đổi dạng đa thức sang sơ đồ chuyển
trạng thái của bộ mã hóa. Cấu trúc Trellis bao gồm các trường sau (hình 10).
Field in trellis Structure Dimensions Meaning
numInputSymbols Scalar Number of input symbols to the encoder: 2k
numOutputSymbols Scalar Number of output symbols from the encoder: 2
numStates Scalar Number of states in the encoder
nextStates numStates-by-2k matrix Next states for all combinations of current state and current input
outputs numStates-by-2k matrix Outputs (in octal) for all combinations of current state and current input
Hình 10. Các trường trong cấu trúc Trellis
Page 9
Trong các trường trên thì chiều dài ràng buộc của mã chập sẽ quy định số
đầu vào mã chập. Nếu số chiều dài ràng buộc là 2 thì số đầu vào mã chập sẽ là 2
và số kí tự đầu vào sẽ là 4…Ngoài ra các hệ số trong đa thức sinh dưới dạng nhị
phân sẽ được biểu diễn dưới dạng bát phân trong cấu trúc Trellis. Vi dụ, với bộ
lập mã trong hình 8 có hai đa thức sinh với các hệ số lập thành dạng nhị phân là
(1 1 1 1 0 0 1) ứng với đầu ra của bit thứ nhất và (1 0 1 1 0 1 1), trong khai báo
Trellis, dạng nhị phân này sẽ được đổi sang dạng bát phân là hai số 171 và 133.
Với bộ mã hóa như trên, cấu trúc trellis sẽ có 27 trạng thái trong bộ mã hóa.
Để hiểu rõ hơn về quá trình mã hóa và giải mã mã chập, kết quả mô phỏng
của bộ mã hóa này sẽ được đưa ra trong phần sau.
2.2. Kết quả mô phỏng
Với mô hình được cho trong hình 9, chúng ta thiết lập các thông số cho
từng khối như sau:
Khối tạo chuỗi bit nhị phân:
- Proballity of a zero: 0.5
- Initial seed: dùng hàm randseed
- Sample time: 0.5
Khối tạo mã chập: thiết lập Trellis poly2trellis ( 7, [171 133])
Khối kênh truyền đối xứng: xét xác suất lỗi: 0.02
Khối giải mã sử dụng thuật toán Virterbi: thiết lấp tương tự khối mã chập
Chọn thời gian mô phỏng từ 0 đến 100 s.
Sau khi đã thiết lập các khối, ta tiến hành mô phỏng và thu đươc kết quả
như trên hình 11
Page 10
Hình 11. Kết quả mô phỏng
Từ kết quả mô phỏng, ta thấy rằng quá trình mã hóa và giải mã một chuỗi
bit thông tin bất kì đã thành công. Với xác suất lỗi kênh truyền là 2% thì bit thông
tin sau khi giải mã bằng thuật toán Virterbi giữ nguyên được nội dung tin truyền.
Page 11
Hai chuỗi bit đầu ra
bộ mã chập
Bit thông tin
đầu vào
Chuỗi bit thông tin
sau giải mã
Tín hiệu sau khi đi
qua kênh truyền
Kết luận
Như vậy, quá trình mô phỏng việc mã hóa và giải mã mã chập đã được
thực hiện.Việc thiết lập mã và giải mã đều dựa vào biểu đồ mắt cáo và thuật toán
giải mã Virterbi.Sự tiện lợi của công cụ Simulink trong phần mềm Matlab cho
phép chúng ta có thể xây dựng được bất kì bộ tạo mã chập chỉ bằng cách thay đổi
các tham số trong sơ đồ khối của bộ tạo mã.
Tuy nhiên, project còn nhiều thiếu sót. Đó là chưa nêu ra được vai trò làm
giảm thiểu lỗi kênh truyền của mã chập bằng cách thiết lập mối quan hệ đồ thị
giữa tỉ số tín hiệu trên nhiễu SNR và tỉ lệ lỗi bit BER. Ngoài ra, việc xây dựng bộ
tạo mã chập theo quan điểm lý thuyết hệ thống chưa được thực hiện. Đây là những
hướng cần khắc phục trong thời gian tới của project.
Page 12
Tài liệu tham khảo
[1] Eric V. York (1997), Algebraic Description and Construction of Error Correcting
Codes: A Linear Systems point of view, Dissertation for the degree of Philosophy
Doctor of the University of Notre Dame, Notre Dame Indiana, USA.
[2] Brian M. Allen, (1999). Linear systems analysis and decoding of convolutional
codes.
[3] www.mathwork.com
Page 13
PHỤ LỤC CODE/* This code was developed as part of graduate coursework at Embry-
Riddle Aeronautical University
* under the guidance of Dr. Pat Anderson and Dr. Hever Moncayo.
*
* Author: Robert F. Hartley
* Assistant Developers: Francois Hugon, Brian DeRosa, and Christopher
Carvalho
* Support: [email protected]
*
* Oct. 25, 2012
* Version 1.0
*
*/
/*
* File: Arduino_IMU_sfcn.c
*
*
*
* --- THIS FILE GENERATED BY S-FUNCTION BUILDER: 3.0 ---
*
* This file is an S-function produced by the S-Function
* Builder which only recognizes certain fields. Changes made
* outside these fields will be lost the next time the block is
* used to load, edit, and resave this file. This file will be overwritten
* by the S-function Builder block. If you want to edit this file by hand,
* you must change it only in the area defined as:
*
* %%%-SFUNWIZ_defines_Changes_BEGIN
* #define NAME 'replacement text'
Page 14
* %%% SFUNWIZ_defines_Changes_END
*
* DO NOT change NAME--Change the 'replacement text' only.
*
* For better compatibility with the Simulink Coder, the
* "wrapper" S-function technique is used. This is discussed
* in the Simulink Coder's Manual in the Chapter titled,
* "Wrapper S-functions".
*
* -------------------------------------------------------------------------
* | See matlabroot/simulink/src/sfuntmpl_doc.c for a more detailed
template |
* -------------------------------------------------------------------------
* Created: Thu Aug 9 02:31:58 2012
*
*
*/
#define S_FUNCTION_LEVEL 2
#define S_FUNCTION_NAME Arduino_IMU_sfcn
/
*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<*/
/* %%%-SFUNWIZ_defines_Changes_BEGIN --- EDIT HERE TO _END
*/
#define NUM_INPUTS 7
/* Input Port 0 */
#define IN_PORT_0_NAME p_degs
#define INPUT_0_WIDTH 1
#define INPUT_DIMS_0_COL 1
#define INPUT_0_DTYPE real_T
Page 15
#define INPUT_0_COMPLEX COMPLEX_NO
#define IN_0_FRAME_BASED FRAME_NO
#define IN_0_BUS_BASED 0
#define IN_0_BUS_NAME
#define IN_0_DIMS 1-D
#define INPUT_0_FEEDTHROUGH 1
#define IN_0_ISSIGNED 1
#define IN_0_WORDLENGTH 8
#define IN_0_FIXPOINTSCALING 1
#define IN_0_FRACTIONLENGTH 3
#define IN_0_BIAS 0
#define IN_0_SLOPE 0.125
/* Input Port 1 */
#define IN_PORT_1_NAME q_degs
#define INPUT_1_WIDTH 1
#define INPUT_DIMS_1_COL 1
#define INPUT_1_DTYPE real_T
#define INPUT_1_COMPLEX COMPLEX_NO
#define IN_1_FRAME_BASED FRAME_NO
#define IN_1_BUS_BASED 0
#define IN_1_BUS_NAME
#define IN_1_DIMS 1-D
#define INPUT_1_FEEDTHROUGH 1
#define IN_1_ISSIGNED 1
#define IN_1_WORDLENGTH 8
#define IN_1_FIXPOINTSCALING 1
#define IN_1_FRACTIONLENGTH 3
#define IN_1_BIAS 0
#define IN_1_SLOPE 0.125
/* Input Port 2 */
#define IN_PORT_2_NAME r_degs
Page 16
#define INPUT_2_WIDTH 1
#define INPUT_DIMS_2_COL 1
#define INPUT_2_DTYPE real_T
#define INPUT_2_COMPLEX COMPLEX_NO
#define IN_2_FRAME_BASED FRAME_NO
#define IN_2_BUS_BASED 0
#define IN_2_BUS_NAME
#define IN_2_DIMS 1-D
#define INPUT_2_FEEDTHROUGH 1
#define IN_2_ISSIGNED 1
#define IN_2_WORDLENGTH 8
#define IN_2_FIXPOINTSCALING 1
#define IN_2_FRACTIONLENGTH 3
#define IN_2_BIAS 0
#define IN_2_SLOPE 0.125
/* Input Port 3 */
#define IN_PORT_3_NAME nx_g
#define INPUT_3_WIDTH 1
#define INPUT_DIMS_3_COL 1
#define INPUT_3_DTYPE real_T
#define INPUT_3_COMPLEX COMPLEX_NO
#define IN_3_FRAME_BASED FRAME_NO
#define IN_3_BUS_BASED 0
#define IN_3_BUS_NAME
#define IN_3_DIMS 1-D
#define INPUT_3_FEEDTHROUGH 1
#define IN_3_ISSIGNED 1
#define IN_3_WORDLENGTH 8
#define IN_3_FIXPOINTSCALING 1
#define IN_3_FRACTIONLENGTH 3
#define IN_3_BIAS 0
Page 17
#define IN_3_SLOPE 0.125
/* Input Port 4 */
#define IN_PORT_4_NAME ny_g
#define INPUT_4_WIDTH 1
#define INPUT_DIMS_4_COL 1
#define INPUT_4_DTYPE real_T
#define INPUT_4_COMPLEX COMPLEX_NO
#define IN_4_FRAME_BASED FRAME_NO
#define IN_4_BUS_BASED 0
#define IN_4_BUS_NAME
#define IN_4_DIMS 1-D
#define INPUT_4_FEEDTHROUGH 1
#define IN_4_ISSIGNED 1
#define IN_4_WORDLENGTH 8
#define IN_4_FIXPOINTSCALING 1
#define IN_4_FRACTIONLENGTH 3
#define IN_4_BIAS 0
#define IN_4_SLOPE 0.125
/* Input Port 5 */
#define IN_PORT_5_NAME nz_g
#define INPUT_5_WIDTH 1
#define INPUT_DIMS_5_COL 1
#define INPUT_5_DTYPE real_T
#define INPUT_5_COMPLEX COMPLEX_NO
#define IN_5_FRAME_BASED FRAME_NO
#define IN_5_BUS_BASED 0
#define IN_5_BUS_NAME
#define IN_5_DIMS 1-D
#define INPUT_5_FEEDTHROUGH 1
#define IN_5_ISSIGNED 1
#define IN_5_WORDLENGTH 8
Page 18
#define IN_5_FIXPOINTSCALING 1
#define IN_5_FRACTIONLENGTH 3
#define IN_5_BIAS 0
#define IN_5_SLOPE 0.125
/* Input Port 6 */
#define IN_PORT_6_NAME temp_degC
#define INPUT_6_WIDTH 1
#define INPUT_DIMS_6_COL 1
#define INPUT_6_DTYPE real_T
#define INPUT_6_COMPLEX COMPLEX_NO
#define IN_6_FRAME_BASED FRAME_NO
#define IN_6_BUS_BASED 0
#define IN_6_BUS_NAME
#define IN_6_DIMS 1-D
#define INPUT_6_FEEDTHROUGH 1
#define IN_6_ISSIGNED 1
#define IN_6_WORDLENGTH 8
#define IN_6_FIXPOINTSCALING 1
#define IN_6_FRACTIONLENGTH 3
#define IN_6_BIAS 0
#define IN_6_SLOPE 0.125
#define NUM_OUTPUTS 7
/* Output Port 0 */
#define OUT_PORT_0_NAME p_degs
#define OUTPUT_0_WIDTH 1
#define OUTPUT_DIMS_0_COL 1
#define OUTPUT_0_DTYPE real_T
#define OUTPUT_0_COMPLEX COMPLEX_NO
#define OUT_0_FRAME_BASED FRAME_NO
#define OUT_0_BUS_BASED 0
Page 19
#define OUT_0_BUS_NAME
#define OUT_0_DIMS 1-D
#define OUT_0_ISSIGNED 1
#define OUT_0_WORDLENGTH 8
#define OUT_0_FIXPOINTSCALING 1
#define OUT_0_FRACTIONLENGTH 3
#define OUT_0_BIAS 0
#define OUT_0_SLOPE 0.125
/* Output Port 1 */
#define OUT_PORT_1_NAME q_degs
#define OUTPUT_1_WIDTH 1
#define OUTPUT_DIMS_1_COL 1
#define OUTPUT_1_DTYPE real_T
#define OUTPUT_1_COMPLEX COMPLEX_NO
#define OUT_1_FRAME_BASED FRAME_NO
#define OUT_1_BUS_BASED 0
#define OUT_1_BUS_NAME
#define OUT_1_DIMS 1-D
#define OUT_1_ISSIGNED 1
#define OUT_1_WORDLENGTH 8
#define OUT_1_FIXPOINTSCALING 1
#define OUT_1_FRACTIONLENGTH 3
#define OUT_1_BIAS 0
#define OUT_1_SLOPE 0.125
/* Output Port 2 */
#define OUT_PORT_2_NAME r_degs
#define OUTPUT_2_WIDTH 1
#define OUTPUT_DIMS_2_COL 1
#define OUTPUT_2_DTYPE real_T
#define OUTPUT_2_COMPLEX COMPLEX_NO
#define OUT_2_FRAME_BASED FRAME_NO
Page 20
#define OUT_2_BUS_BASED 0
#define OUT_2_BUS_NAME
#define OUT_2_DIMS 1-D
#define OUT_2_ISSIGNED 1
#define OUT_2_WORDLENGTH 8
#define OUT_2_FIXPOINTSCALING 1
#define OUT_2_FRACTIONLENGTH 3
#define OUT_2_BIAS 0
#define OUT_2_SLOPE 0.125
/* Output Port 3 */
#define OUT_PORT_3_NAME nx_g
#define OUTPUT_3_WIDTH 1
#define OUTPUT_DIMS_3_COL 1
#define OUTPUT_3_DTYPE real_T
#define OUTPUT_3_COMPLEX COMPLEX_NO
#define OUT_3_FRAME_BASED FRAME_NO
#define OUT_3_BUS_BASED 0
#define OUT_3_BUS_NAME
#define OUT_3_DIMS 1-D
#define OUT_3_ISSIGNED 1
#define OUT_3_WORDLENGTH 8
#define OUT_3_FIXPOINTSCALING 1
#define OUT_3_FRACTIONLENGTH 3
#define OUT_3_BIAS 0
#define OUT_3_SLOPE 0.125
/* Output Port 4 */
#define OUT_PORT_4_NAME ny_g
#define OUTPUT_4_WIDTH 1
#define OUTPUT_DIMS_4_COL 1
#define OUTPUT_4_DTYPE real_T
#define OUTPUT_4_COMPLEX COMPLEX_NO
Page 21
#define OUT_4_FRAME_BASED FRAME_NO
#define OUT_4_BUS_BASED 0
#define OUT_4_BUS_NAME
#define OUT_4_DIMS 1-D
#define OUT_4_ISSIGNED 1
#define OUT_4_WORDLENGTH 8
#define OUT_4_FIXPOINTSCALING 1
#define OUT_4_FRACTIONLENGTH 3
#define OUT_4_BIAS 0
#define OUT_4_SLOPE 0.125
/* Output Port 5 */
#define OUT_PORT_5_NAME nz_g
#define OUTPUT_5_WIDTH 1
#define OUTPUT_DIMS_5_COL 1
#define OUTPUT_5_DTYPE real_T
#define OUTPUT_5_COMPLEX COMPLEX_NO
#define OUT_5_FRAME_BASED FRAME_NO
#define OUT_5_BUS_BASED 0
#define OUT_5_BUS_NAME
#define OUT_5_DIMS 1-D
#define OUT_5_ISSIGNED 1
#define OUT_5_WORDLENGTH 8
#define OUT_5_FIXPOINTSCALING 1
#define OUT_5_FRACTIONLENGTH 3
#define OUT_5_BIAS 0
#define OUT_5_SLOPE 0.125
/* Output Port 6 */
#define OUT_PORT_6_NAME temp_degC
#define OUTPUT_6_WIDTH 1
#define OUTPUT_DIMS_6_COL 1
#define OUTPUT_6_DTYPE real_T
Page 22
#define OUTPUT_6_COMPLEX COMPLEX_NO
#define OUT_6_FRAME_BASED FRAME_NO
#define OUT_6_BUS_BASED 0
#define OUT_6_BUS_NAME
#define OUT_6_DIMS 1-D
#define OUT_6_ISSIGNED 1
#define OUT_6_WORDLENGTH 8
#define OUT_6_FIXPOINTSCALING 1
#define OUT_6_FRACTIONLENGTH 3
#define OUT_6_BIAS 0
#define OUT_6_SLOPE 0.125
#define NPARAMS 4
/* Parameter 1 */
#define PARAMETER_0_NAME lpf_filt_freq_hz
#define PARAMETER_0_DTYPE uint32_T
#define PARAMETER_0_COMPLEX COMPLEX_NO
/* Parameter 2 */
#define PARAMETER_1_NAME gyro_scale
#define PARAMETER_1_DTYPE uint32_T
#define PARAMETER_1_COMPLEX COMPLEX_NO
/* Parameter 3 */
#define PARAMETER_2_NAME accel_scale
#define PARAMETER_2_DTYPE uint32_T
#define PARAMETER_2_COMPLEX COMPLEX_NO
/* Parameter 4 */
#define PARAMETER_3_NAME SampleTime
#define PARAMETER_3_DTYPE real_T
#define PARAMETER_3_COMPLEX COMPLEX_NO
#define SAMPLE_TIME_0 SampleTime
Page 23
#define NUM_DISC_STATES 0
#define DISC_STATES_IC [0]
#define NUM_CONT_STATES 0
#define CONT_STATES_IC [0]
#define SFUNWIZ_GENERATE_TLC 0
#define SOURCEFILES "__SFB__"
#define PANELINDEX 6
#define USE_SIMSTRUCT 0
#define SHOW_COMPILE_STEPS 0
#define CREATE_DEBUG_MEXFILE 0
#define SAVE_CODE_ONLY 1
#define SFUNWIZ_REVISION 3.0
/* %%%-SFUNWIZ_defines_Changes_END --- EDIT HERE TO _BEGIN
*/
/
*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<*/
#include "simstruc.h"
#define PARAM_DEF0(S) ssGetSFcnParam(S, 0)
#define PARAM_DEF1(S) ssGetSFcnParam(S, 1)
#define PARAM_DEF2(S) ssGetSFcnParam(S, 2)
#define PARAM_DEF3(S) ssGetSFcnParam(S, 3)
#define IS_PARAM_DOUBLE(pVal) (mxIsNumeric(pVal) && !
mxIsLogical(pVal) &&\
!mxIsEmpty(pVal) && !mxIsSparse(pVal) && !mxIsComplex(pVal) &&
mxIsDouble(pVal))
/*====================*
Page 24
* S-function methods *
*====================*/
#define MDL_CHECK_PARAMETERS
#if defined(MDL_CHECK_PARAMETERS) &&
defined(MATLAB_MEX_FILE)
/* Function: mdlCheckParameters
=============================================
* Abstract:
* Validate our parameters to verify they are okay.
*/
static void mdlCheckParameters(SimStruct *S)
{
int paramIndex = 0;
bool validParam = false;
/* All parameters must match the S-function Builder Dialog */
/* {
const mxArray *pVal0 = ssGetSFcnParam(S,0);
if (!IS_PARAM_DOUBLE(pVal0)) {
validParam = true;
paramIndex = 0;
goto EXIT_POINT;
}
}
{
const mxArray *pVal1 = ssGetSFcnParam(S,1);
if (!IS_PARAM_DOUBLE(pVal1)) {
validParam = true;
paramIndex = 1;
Page 25
goto EXIT_POINT;
}
}
{
const mxArray *pVal2 = ssGetSFcnParam(S,2);
if (!IS_PARAM_DOUBLE(pVal2)) {
validParam = true;
paramIndex = 2;
goto EXIT_POINT;
}
}
*/
{
const mxArray *pVal3 = ssGetSFcnParam(S,3);
if (!mxIsDouble(pVal3)) {
ssSetErrorStatus(S,"Sample time parameter SampleTime must be
of type double");
return;
}
}
{
const mxArray *pVal3 = ssGetSFcnParam(S,3);
if (!IS_PARAM_DOUBLE(pVal3)) {
validParam = true;
paramIndex = 3;
goto EXIT_POINT;
}
}
Page 26
EXIT_POINT:
if (validParam) {
char parameterErrorMsg[1024];
sprintf(parameterErrorMsg, "The data type and or complexity of
parameter %d does not match the "
"information specified in the S-function Builder dialog. "
"For non-double parameters you will need to cast them using
int8, int16, "
"int32, uint8, uint16, uint32 or boolean.", paramIndex + 1);
ssSetErrorStatus(S,parameterErrorMsg);
}
return;
}
#endif /* MDL_CHECK_PARAMETERS */
/* Function: mdlInitializeSizes
===============================================
* Abstract:
* Setup sizes of the various vectors.
*/
static void mdlInitializeSizes(SimStruct *S)
{
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
ssSetNumSFcnParams(S, NPARAMS); /* Number of expected
parameters */
#if defined(MATLAB_MEX_FILE)
if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
mdlCheckParameters(S);
if (ssGetErrorStatus(S) != NULL) {
return;
}
Page 27
} else {
return; /* Parameter mismatch will be reported by Simulink */
}
#endif
ssSetNumContStates(S, NUM_CONT_STATES);
ssSetNumDiscStates(S, NUM_DISC_STATES);
if (!ssSetNumInputPorts(S, NUM_INPUTS)) return;
/* Input Port 0 */
ssSetInputPortWidth(S, 0, INPUT_0_WIDTH);
ssSetInputPortDataType(S, 0, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 0, INPUT_0_COMPLEX);
ssSetInputPortDirectFeedThrough(S, 0, INPUT_0_FEEDTHROUGH);
ssSetInputPortRequiredContiguous(S, 0, 1); /*direct input signal
access*/
/* Input Port 1 */
ssSetInputPortWidth(S, 1, INPUT_1_WIDTH);
ssSetInputPortDataType(S, 1, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 1, INPUT_1_COMPLEX);
ssSetInputPortDirectFeedThrough(S, 1, INPUT_1_FEEDTHROUGH);
ssSetInputPortRequiredContiguous(S, 1, 1); /*direct input signal
access*/
/* Input Port 2 */
ssSetInputPortWidth(S, 2, INPUT_2_WIDTH);
ssSetInputPortDataType(S, 2, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 2, INPUT_2_COMPLEX);
ssSetInputPortDirectFeedThrough(S, 2, INPUT_2_FEEDTHROUGH);
Page 28
ssSetInputPortRequiredContiguous(S, 2, 1); /*direct input signal
access*/
/* Input Port 3 */
ssSetInputPortWidth(S, 3, INPUT_3_WIDTH);
ssSetInputPortDataType(S, 3, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 3, INPUT_3_COMPLEX);
ssSetInputPortDirectFeedThrough(S, 3, INPUT_3_FEEDTHROUGH);
ssSetInputPortRequiredContiguous(S, 3, 1); /*direct input signal
access*/
/* Input Port 4 */
ssSetInputPortWidth(S, 4, INPUT_4_WIDTH);
ssSetInputPortDataType(S, 4, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 4, INPUT_4_COMPLEX);
ssSetInputPortDirectFeedThrough(S, 4, INPUT_4_FEEDTHROUGH);
ssSetInputPortRequiredContiguous(S, 4, 1); /*direct input signal
access*/
/* Input Port 5 */
ssSetInputPortWidth(S, 5, INPUT_5_WIDTH);
ssSetInputPortDataType(S, 5, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 5, INPUT_5_COMPLEX);
ssSetInputPortDirectFeedThrough(S, 5, INPUT_5_FEEDTHROUGH);
ssSetInputPortRequiredContiguous(S, 5, 1); /*direct input signal
access*/
/* Input Port 6 */
ssSetInputPortWidth(S, 6, INPUT_6_WIDTH);
ssSetInputPortDataType(S, 6, SS_DOUBLE);
ssSetInputPortComplexSignal(S, 6, INPUT_6_COMPLEX);
Page 29
ssSetInputPortDirectFeedThrough(S, 6, INPUT_6_FEEDTHROUGH);
ssSetInputPortRequiredContiguous(S, 6, 1); /*direct input signal
access*/
if (!ssSetNumOutputPorts(S, NUM_OUTPUTS)) return;
/* Output Port 0 */
ssSetOutputPortWidth(S, 0, OUTPUT_0_WIDTH);
ssSetOutputPortDataType(S, 0, SS_DOUBLE);
ssSetOutputPortComplexSignal(S, 0, OUTPUT_0_COMPLEX);
/* Output Port 1 */
ssSetOutputPortWidth(S, 1, OUTPUT_1_WIDTH);
ssSetOutputPortDataType(S, 1, SS_DOUBLE);
ssSetOutputPortComplexSignal(S, 1, OUTPUT_1_COMPLEX);
/* Output Port 2 */
ssSetOutputPortWidth(S, 2, OUTPUT_2_WIDTH);
ssSetOutputPortDataType(S, 2, SS_DOUBLE);
ssSetOutputPortComplexSignal(S, 2, OUTPUT_2_COMPLEX);
/* Output Port 3 */
ssSetOutputPortWidth(S, 3, OUTPUT_3_WIDTH);
ssSetOutputPortDataType(S, 3, SS_DOUBLE);
ssSetOutputPortComplexSignal(S, 3, OUTPUT_3_COMPLEX);
/* Output Port 4 */
ssSetOutputPortWidth(S, 4, OUTPUT_4_WIDTH);
ssSetOutputPortDataType(S, 4, SS_DOUBLE);
ssSetOutputPortComplexSignal(S, 4, OUTPUT_4_COMPLEX);
/* Output Port 5 */
ssSetOutputPortWidth(S, 5, OUTPUT_5_WIDTH);
ssSetOutputPortDataType(S, 5, SS_DOUBLE);
ssSetOutputPortComplexSignal(S, 5, OUTPUT_5_COMPLEX);
/* Output Port 6 */
ssSetOutputPortWidth(S, 6, OUTPUT_6_WIDTH);
Page 30
ssSetOutputPortDataType(S, 6, SS_DOUBLE);
ssSetOutputPortComplexSignal(S, 6, OUTPUT_6_COMPLEX);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
/* Take care when specifying exception free code - see sfuntmpl_doc.c
*/
ssSetOptions(S, (SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_WORKS_WITH_CODE_REUSE));
}
/* Function: mdlInitializeSampleTimes
=========================================
* Abstract:
* Specifiy the sample time.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, *mxGetPr(ssGetSFcnParam(S, 3)));
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_SET_OUTPUT_PORT_DATA_TYPE
static void mdlSetOutputPortDataType(SimStruct *S, int port, DTypeId
dType)
{
Page 31
ssSetOutputPortDataType(S, 0, dType);
}
#define MDL_SET_INPUT_PORT_DATA_TYPE
static void mdlSetInputPortDataType(SimStruct *S, int port, DTypeId
dType)
{
ssSetInputPortDataType(S, 0, dType);
}
#define MDL_SET_DEFAULT_PORT_DATA_TYPES
static void mdlSetDefaultPortDataTypes(SimStruct *S)
{
ssSetOutputPortDataType(S, 0, SS_DOUBLE);
ssSetInputPortDataType(S, 0, SS_DOUBLE);
}
/* Function: mdlOutputs
=====================================================
==
*
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
real_T *p_degs = (real_T *)ssGetOutputPortRealSignal(S,0);
real_T *q_degs = (real_T *)ssGetOutputPortRealSignal(S,1);
real_T *r_degs = (real_T *)ssGetOutputPortRealSignal(S,2);
real_T *nx_g = (real_T *)ssGetOutputPortRealSignal(S,3);
real_T *ny_g = (real_T *)ssGetOutputPortRealSignal(S,4);
real_T *nz_g = (real_T *)ssGetOutputPortRealSignal(S,5);
real_T *temp_degC = (real_T *)ssGetOutputPortRealSignal(S,6);
Page 32
const int_T p_width0 =
mxGetNumberOfElements(PARAM_DEF0(S));
const int_T p_width1 =
mxGetNumberOfElements(PARAM_DEF1(S));
const int_T p_width2 =
mxGetNumberOfElements(PARAM_DEF2(S));
const int_T p_width3 =
mxGetNumberOfElements(PARAM_DEF3(S));
const uint32_T *lpf_filt_freq_hz = (const uint32_T
*)mxGetData(PARAM_DEF0(S));
const uint32_T *gyro_scale = (const uint32_T
*)mxGetData(PARAM_DEF1(S));
const uint32_T *accel_scale = (const uint32_T
*)mxGetData(PARAM_DEF2(S));
const real_T *SampleTime = (const real_T
*)mxGetData(PARAM_DEF3(S));
const real_T *p_degs_in = (real_T *)ssGetInputPortRealSignal(S,0);
const real_T *q_degs_in = (real_T *)ssGetInputPortRealSignal(S,1);
const real_T *r_degs_in = (real_T *)ssGetInputPortRealSignal(S,2);
const real_T *nx_g_in = (real_T *)ssGetInputPortRealSignal(S,3);
const real_T *ny_g_in = (real_T *)ssGetInputPortRealSignal(S,4);
const real_T *nz_g_in = (real_T *)ssGetInputPortRealSignal(S,5);
const real_T *temp_degC_in = (real_T
*)ssGetInputPortRealSignal(S,6);
p_degs[0] = p_degs_in[0];
q_degs[0] = q_degs_in[0];
r_degs[0] = r_degs_in[0];
nx_g[0] = nx_g_in[0];
Page 33
ny_g[0] = ny_g_in[0];
nz_g[0] = nz_g_in[0];
temp_degC[0] = temp_degC_in[0];
}
#define MDL_SET_WORK_WIDTHS
#if defined(MDL_SET_WORK_WIDTHS) &&
defined(MATLAB_MEX_FILE)
/* Function: mdlSetWorkWidths
=============================================
* Abstract:
* The optional method, mdlSetWorkWidths is called after input port
* width, output port width, and sample times of the S-function have
* been determined to set any state and work vector sizes which are
* a function of the input, output, and/or sample times.
*
* Run-time parameters are registered in this method using methods
* ssSetNumRunTimeParams, ssSetRunTimeParamInfo, and related
methods.
*/
static void mdlSetWorkWidths(SimStruct *S)
{
/* Set number of run-time parameters */
if (!ssSetNumRunTimeParams(S, 4))
return;
/*
* Register the run-time parameters
*/
Page 34
ssRegDlgParamAsRunTimeParam(S, 0, 0, "lpf_filt_freq_hz",
ssGetDataTypeId(S, "uint32"));
ssRegDlgParamAsRunTimeParam(S, 1, 1, "gyro_scale",
ssGetDataTypeId(S, "uint32"));
ssRegDlgParamAsRunTimeParam(S, 2, 2, "accel_scale",
ssGetDataTypeId(S, "uint32"));
ssRegDlgParamAsRunTimeParam(S, 3, 3, "SampleTime",
ssGetDataTypeId(S, "double"));
}
#endif
/* Function: mdlTerminate
=====================================================
* Abstract:
* In this function, you should perform any actions that are necessary
* at the termination of a simulation. For example, if memory was
* allocated in mdlStart, this is the place to free it.
*/
static void mdlTerminate(SimStruct *S)
{
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-
file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
/*FreeRTOS.org V5.0.4 - Copyright (C) 2003-2008 Richard Barry.
Page 35
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published
bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See theGNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
*************************************************************************** *************************************************************************** * * * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * * and even write all or part of your application on your behalf. * * See http://www.OpenRTOS.com for details of the services we provide to *
Page 36
* expedite your project. * * * *************************************************************************** ***************************************************************************
Please ensure to read the configuration and relevant port sections of the
online documentation.
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.*/
/* FreeRTOS.org includes. */#include "FreeRTOS.h"#include "task.h"#include "semphr.h"
/* Compiler includes. */#include <stdlib.h>#include <stdio.h>
/* The task that sends messages to the stdio gatekeeper. Two instances of this task are created. */static void prvPrintTask( void *pvParameters );
/* The gatekeeper task itself. */static void prvStdioGatekeeperTask( void *pvParameters );
Page 37
/* Define the strings that the tasks and interrupt will print out via the gatekeeper. */static char *pcStringsToPrint[] ={
"Task 1 ****************************************************\r\n",
"Task 2 ----------------------------------------------------\r\n","Message printed from the tick hook interrupt ##############\r\n"
};
/*-----------------------------------------------------------*/
/* Declare a variable of type xQueueHandle. This is used to send messages fromthe print tasks to the gatekeeper task. */xQueueHandle xPrintQueue;
int main( void ){ /* Before a queue is used it must be explicitly created. The queue is created
to hold a maximum of 5 character pointers. */ xPrintQueue = xQueueCreate( 5, sizeof( char * ) );
/* The tasks are going to use a pseudo random delay, seed the random number
generator. */srand( 567 );
/* Check the queue was created successfully. */if( xPrintQueue != NULL ){
/* Create two instances of the tasks that send messages to the gatekeeper.
The index to the string they attempt to write is passed in as the task
parameter (4th parameter to xTaskCreate()). The tasks are created at
different priorities so some pre-emption will occur. */xTaskCreate( prvPrintTask, "Print1", 1000, ( void * ) 0, 1,
NULL );
Page 38
xTaskCreate( prvPrintTask, "Print2", 1000, ( void * ) 1, 2, NULL );
/* Create the gatekeeper task. This is the only task that is permitted
to access standard out. */xTaskCreate( prvStdioGatekeeperTask, "Gatekeeper", 1000,
NULL, 0, NULL );
/* Start the scheduler so the created tasks start executing. */vTaskStartScheduler();
}
/* If all is well we will never reach here as the scheduler will now be running the tasks. If we do reach here then it is likely that there was insufficient heap memory available for a resource to be created. */
for( ;; );return 0;
}/*-----------------------------------------------------------*/
static void prvStdioGatekeeperTask( void *pvParameters ){char *pcMessageToPrint;
/* This is the only task that is allowed to write to the terminal output.
Any other task wanting to write to the output does not access the terminal
directly, but instead sends the output to this task. As only one task writes to standard out there are no mutual exclusion or serialization
issuesto consider within this task itself. */for( ;; ){
/* Wait for a message to arrive. */xQueueReceive( xPrintQueue, &pcMessageToPrint,
portMAX_DELAY );
/* There is no need to check the return value as the task will block
indefinitely and only run again when a message has arrived. When the
Page 39
next line is executed there will be a message to be output. */printf( "%s", pcMessageToPrint );fflush( stdout );
/* Now simply go back to wait for the next message. */}
}/*-----------------------------------------------------------*/
void vApplicationTickHook( void ){static int iCount = 0;portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* Print out a message every 200 ticks. The message is not written out
directly, but sent to the gatekeeper task. */iCount++;if( iCount >= 200 ){
/* In this case the last parameter (xHigherPriorityTaskWoken) is not
actually used but must still be supplied. */xQueueSendToFrontFromISR( xPrintQueue,
&( pcStringsToPrint[ 2 ] ), &xHigherPriorityTaskWoken );
/* Reset the count ready to print out the string again in 200 ticks
time. */iCount = 0;
}}/*-----------------------------------------------------------*/
static void prvPrintTask( void *pvParameters ){int iIndexToString;
/* Two instances of this task are created so the index to the string the task
will send to the gatekeeper task is passed in the task parameter. Cast this
to the required type. */
Page 40
iIndexToString = ( int ) pvParameters;
for( ;; ){
/* Print out the string, not directly but by passing the string to the
gatekeeper task on the queue. The queue is created before the scheduler is
started so will already exist by the time this task executes. A block time
is not specified as there should always be space in the queue. */
xQueueSendToBack( xPrintQueue, &( pcStringsToPrint[ iIndexToString ] ), 0 );
/* Wait a pseudo random time. Note that rand() is not necessarily
re-entrant, but in this case it does not really matter as the code does
not care what value is returned. In a more secure application a version
of rand() that is known to be re-entrant should be used - or calls to
rand() should be protected using a critical section. */vTaskDelay( ( rand() & 0x1FF ) );
}}
Page 41