New to C++ Embedded Systems Programming

Hi all, I'm generally not a poster, however, I am being introduced to C++ Embedded Systems Programming (a field I am admittedly relatively ignorant to--the embedded programming part, not the C++ =P). I have been given a sample problem and I am a little confused on how to go about starting/solving it. The following is the objective:

To make an application that will utilize the following:
Message Queues,
Semaphores,
Timers,
Priority Levels,
Task Delays,
data synchronization (by using message queue)

Your class will contain the following:

Task 1:

* Highest priority task
* Pends on Timer event (which should be set to occur every 1 second)
* Sends message to Task 3
* releases Task 3's semaphore after sending messages

Task 2:

* Middle priority task
* pends on semaphore
* receives message queue and prints out the spare cycles.
* utilizes task delay after getting message queue information (10 msecs)
* clears cycle count being incremented in Task 4

Task 3:

* Lower priority task then Task 2
* Sends Message to task 2 (Should see that Task 2 will then run taking time from task 3)
* Message sent to task 2 will contain cycle count being calculated in Task 4

Task 4:

* Lowest priority task
* Counts Spare Cycle Time (only the lowest priority task in the system can do this.


All in all I am a bit confused as to what a semaphore is, through Wikipedia I was able to come up with the general definition of it being a protected variable... in addition to this I am a bit lost in how to incorporate timers and cycles in C++, something I have never handled before.

ANY help that can be provided would be absolutely appreciated. Also, in advance, I apologize if I am asking for too much or I'm posting in the wrong forum. I just need some guidance with this, as mentioned above, this is a bit new to me.

Thank you all for your time.
wow... your user name says alot about you!
1. It's todo with hexadecimal number counting system, something like 0x16 but harder to remember 2. The first bit is like "data" but spelt differently datta
Haha... well, to be perfectly honest... you were right on the money with that one kfex. Well done! The 0x16 translates to my age when I started using this username. BUT! Now on to the good stuff:

WELL!!! It's been a couple weeks =P BUT, I was able to figure it all out. It honestly wasn't that difficult. The OS (or RTOS rather) I was using is known as vxWorks. There is some outstanding documentation that comes along with it--and I recommend all who would like to venture into RTOS programming to check them out. I was able to solve the problem with the following as references (mind you, prior to these references I didn't even know what an RTOS was):

BOOKS:
VxWorks Kernel API Reference Vol 2, 6.3
VxWorks Kernel Programmers Guide, 6.3

ONLINE:
Intro to Reentrancy - http://www.embedded.com/story/OEG20010311S0005

Round-Robin Scheduling - http://en.wikipedia.org/wiki/Round-robin_scheduling

Interrupts - http://en.wikipedia.org/wiki/Interrupt

EDF (Least Time To Go) - http://en.wikipedia.org/wiki/Earliest_deadline_first_scheduling

Dynamic Memory Allocation - http://en.wikipedia.org/wiki/Memory_allocation

Fixed Priority Pre-Emptive Scheduling - http://en.wikipedia.org/wiki/Fixed_priority_pre-emptive_scheduling

RTOS - http://en.wikipedia.org/wiki/RTOS

Effective Use of RTOS Programming for Multithreaded Arc - http://www.embedded.com/columns/showArticle.jhtml?articleID=192501328

Mutex:
Dekker - http://en.wikipedia.org/wiki/Dekker%27s_algorithm#Pseudocode
Peterson - http://en.wikipedia.org/wiki/Peterson%27s_algorithm
Lamport - http://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm

Critical Section – http://en.wikipedia.org/wiki/Critical_section

INCREDIBLE HELP -> http://www.cs.ru.nl/lab/vxworks/www.rt.db.erau.edu/toc/TableOfContents.html
And here is the code... I do recommend to try this on your own though... copying mine will do nothing for you. Enjoy!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*INCLUDES*/
#include <vxWorks.h>
#include <taskLib.h>
#include <sysLib.h>
#include <semLib.h>
#include <time.h>
#include <stdio.h>


/*GLOBAL DEFINITIONS*/
#define LOWR 104       //Priority Level for taskFour
#define LOW 103        //Priority Level for taskThree
#define MID 102        //Priority Level for taskTwo
#define HIGH 101       //Priority Level for taskOne
#define MAX_MSGS 10    //Maximum messages for MQ
#define MAX_LNTH 50    //Maximum length for MQ


//Declare SPARE_CYCLE struct type:
struct SPARE_CYCLE {
   int Count;
} Cycle;


/*MESSAGE QUEUE ID's*/
MSG_Q_ID msgQId1;
MSG_Q_ID msgQId2;


/*DECLARE TASK FUNCTIONS*/
void taskOne(void);   //Highest Priority Task  - 101
void taskTwo(void);   //Medium Priority Task   - 102
void taskThree(void); //Low Priority Task      - 103
void taskFour(void);  //Lowest Priority Task   - 104


/*CREATE SEMAPHORE*/
SEM_ID semMutex;


/*TASK INITIATOR FUNCTION*/
void init(void)
{
	/*INITIATE COUNT CYCLE FOR TASK 4*/
	Cycle.Count = 0;
	
	
	/*WELCOME BANNER*/
	printf("\n\n\n############++++++++++++------------"
			"RUNNING"
			"------------++++++++++++############\n\n\n");
	
	
	/*PREPARE MESSAGE QUEUES*/
	//Message Queue 1:
	if((msgQId1 = msgQCreate(MAX_MSGS, MAX_LNTH, MSG_Q_FIFO))
			== NULL)
		printf("\n\n\n\t\t\t!!!!!SPAWNING OF msgQId1 FAILED!!!!!\n\n\n");
	
	//Message Queue 2:
	if((msgQId2 = msgQCreate(MAX_MSGS, MAX_LNTH, MSG_Q_FIFO))
			== NULL)
		printf("\n\n\n\t\t\t!!!!!SPAWNING OF msgQId2 FAILED!!!!!\n\n\n");
	
	
	/*PREPARE SEMAPHORE*/
	//Setup semMutex (PRIORITY-BASED SEMAPHORE):
	if((semMutex = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE))
			== NULL)
		printf("\n\n\n\t\t\t!!!!!SPAWNING OF semMutex FAILED!!!!!\n\n\n");
	
	
	/*PREPARE TASKS*/
	//Declare tid's for tasks:
	int taskIdOne;
	int taskIdTwo;
	int taskIdThree;
	int taskIdFour;
	
	//Task 1 -> HIGH:
	if((taskIdOne = taskSpawn("tsk1", HIGH, 0, 20000, (FUNCPTR)taskOne,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
		printf("\n\n\n\t\t\t!!!!!SPAWNING OF taskOne FAILED!!!!!\n\n\n");
	
	//Task 2 -> MID:
	if((taskIdTwo = taskSpawn("tsk2", MID, 0, 20000, (FUNCPTR)taskTwo,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
		printf("\n\n\n\t\t\t!!!!!SPAWNING OF taskTwo FAILED!!!!!\n\n\n");
	
	//Task 3 -> LOW:
	if((taskIdThree = taskSpawn("tsk3", LOW, 0, 20000, (FUNCPTR)taskThree,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
		printf("\n\n\n\t\t\t!!!!!SPAWNING OF taskThree FAILED!!!!!\n\n\n");
	
	//Task 4 -> LOWR:
	if((taskIdFour = taskSpawn("tsk4", LOWR, 0, 20000, (FUNCPTR)taskFour,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
		printf("\n\n\n\t\t\t!!!!!SPAWNING OF taskFour FAILED!!!!!\n\n\n");
}


/*DEFINITION OF TASK 1 - HIGH*/
void taskOne(void)
{
	//Lock Semaphore:
	semTake(semMutex, WAIT_FOREVER);
	printf("TASK 1: Semaphore Locked...\n");
	printf("\n\t\tTASK 1 TIMER IS SET TO EXECUTE IN %d SECOND.\n\n",
			sysClkRateGet()/60);
	
	//Delay task to occur every second:
	taskDelay(sysClkRateGet());


	/*MESSAGE SENDING*/
	//Prepare Message Going to Task 3:
	char message1[] = "Message from Task 1 Received.\n\t..Sending Message..\n";

	//Send Message to Task3:
	if(msgQSend(msgQId1, message1, MAX_LNTH, WAIT_FOREVER, MSG_PRI_URGENT)
			== ERROR)
		printf("\n\n\n\t\t\t!!!!!taskOne: msgQSend TO taskThree FAILED!!!!!\n\n\n");
	else
		printf("TASK 1: Message Sent To Task 3...\n");


	//Unlock Semaphore:
	printf("TASK 1: Semaphore Released...\n");
	semGive(semMutex);

	//Exit Task 1:
	printf("...............................TASK 1 EXITED.\n\n");
}


/*DEFINITION OF TASK 2 - MID*/
void taskTwo(void)
{
	/*MESSAGE RECEIVING*/
	//Receive Message from Task 3:
	char msgBuf[MAX_LNTH];
	if(msgQReceive(msgQId2, msgBuf, MAX_LNTH, WAIT_FOREVER)
			== ERROR)
		printf("\n\n\n\t\t\t!!!!!taskThree: msgQReceive FROM taskThree FAILED!!!!!\n\n\n");
	else
		printf("TASK 2: Message from Task 3 Received.\n\tCYCLE COUNT: %i\n", msgBuf);

	//Cleanup and Delete Message Queue 2:
	msgQDelete(msgQId2);
	
	
	/*10 MILLISECOND TASK DELAY (=10 000 000 NANOSECONDS)*/
	struct timespec nsTime;
	nsTime.tv_sec = 0;
	nsTime.tv_nsec = 10000000;
	nanosleep(&nsTime, NULL);
	
	
	//Clear Task 4's Cycle Count:
	Cycle.Count = 0;
	printf("TASK 2: CYCLE COUNT CLEARED: %i\n", Cycle.Count);
	
	//Exit Task 2:
	printf("...............................TASK 2 EXITED.\n\n");
}


/*DEFINITION OF TASK 3 - LOW*/
void taskThree(void)
{
	//Lock Semaphore Released By Task 1:
	semTake(semMutex, WAIT_FOREVER);
	printf("TASK 3: Semaphore Locked...\n");
	
		
	/*MESSAGE RECEIVING*/
	//Receive Message from Task 1:
	char msgBuf[MAX_LNTH];
	if(msgQReceive(msgQId1, msgBuf, MAX_LNTH, WAIT_FOREVER)
			== ERROR)
		printf("\n\n\n\t\t\t!!!!!taskThree: msgQReceive FROM taskOne FAILED!!!!!\n\n\n");
	else
		printf("TASK 3: %s\n", msgBuf);
	
	//Cleanup and Delete Message Queue 1
	msgQDelete(msgQId1);

	
	/*MESSAGE SENDING*/
	//Send Message to Task 2
	if(msgQSend(msgQId2, (char*)&(Cycle.Count), MAX_LNTH, WAIT_FOREVER, MSG_PRI_NORMAL)
			== ERROR)
		printf("\n\n\n\t\t\t!!!!!taskThree: msgQSend TO taskTwo FAILED!!!!!\n\n\n");


	//Unlock Semaphore:
	printf("TASK 3: Semaphore Released...\n");
	semGive(semMutex);
	
	//Exit Task 3:
	printf("...............................TASK 3 EXITED.\n\n");
}


/*DEFINITION OF TASK 4 - LOWR*/
void taskFour(void)
{
	while(1)
		Cycle.Count++;
}
Topic archived. No new replies allowed.