-
Notifications
You must be signed in to change notification settings - Fork 828
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Scott Larson
committed
Aug 8, 2020
1 parent
608f55f
commit 6a018a4
Showing
95 changed files
with
34,462 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
armasm -g --cpu ARM1136J-S --apcs /interwork tx_initialize_low_level.s | ||
armcc -g -c -O2 --cpu ARM1136J-S --apcs /interwork -I../../../../common/inc -I../inc sample_threadx.c | ||
armlink -d -o sample_threadx.axf --elf --ro 0 --first tx_initialize_low_level.o(Init) --remove --map --symbols --list sample_threadx.map tx_initialize_low_level.o sample_threadx.o tx.a | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,369 @@ | ||
/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight | ||
threads of different priorities, using a message queue, semaphore, mutex, event flags group, | ||
byte pool, and block pool. */ | ||
|
||
#include "tx_api.h" | ||
|
||
#define DEMO_STACK_SIZE 1024 | ||
#define DEMO_BYTE_POOL_SIZE 9120 | ||
#define DEMO_BLOCK_POOL_SIZE 100 | ||
#define DEMO_QUEUE_SIZE 100 | ||
|
||
|
||
/* Define the ThreadX object control blocks... */ | ||
|
||
TX_THREAD thread_0; | ||
TX_THREAD thread_1; | ||
TX_THREAD thread_2; | ||
TX_THREAD thread_3; | ||
TX_THREAD thread_4; | ||
TX_THREAD thread_5; | ||
TX_THREAD thread_6; | ||
TX_THREAD thread_7; | ||
TX_QUEUE queue_0; | ||
TX_SEMAPHORE semaphore_0; | ||
TX_MUTEX mutex_0; | ||
TX_EVENT_FLAGS_GROUP event_flags_0; | ||
TX_BYTE_POOL byte_pool_0; | ||
TX_BLOCK_POOL block_pool_0; | ||
|
||
|
||
/* Define the counters used in the demo application... */ | ||
|
||
ULONG thread_0_counter; | ||
ULONG thread_1_counter; | ||
ULONG thread_1_messages_sent; | ||
ULONG thread_2_counter; | ||
ULONG thread_2_messages_received; | ||
ULONG thread_3_counter; | ||
ULONG thread_4_counter; | ||
ULONG thread_5_counter; | ||
ULONG thread_6_counter; | ||
ULONG thread_7_counter; | ||
|
||
|
||
/* Define thread prototypes. */ | ||
|
||
void thread_0_entry(ULONG thread_input); | ||
void thread_1_entry(ULONG thread_input); | ||
void thread_2_entry(ULONG thread_input); | ||
void thread_3_and_4_entry(ULONG thread_input); | ||
void thread_5_entry(ULONG thread_input); | ||
void thread_6_and_7_entry(ULONG thread_input); | ||
|
||
|
||
/* Define main entry point. */ | ||
|
||
int main() | ||
{ | ||
|
||
/* Enter the ThreadX kernel. */ | ||
tx_kernel_enter(); | ||
} | ||
|
||
|
||
/* Define what the initial system looks like. */ | ||
|
||
void tx_application_define(void *first_unused_memory) | ||
{ | ||
|
||
CHAR *pointer = TX_NULL; | ||
|
||
|
||
/* Create a byte memory pool from which to allocate the thread stacks. */ | ||
tx_byte_pool_create(&byte_pool_0, "byte pool 0", first_unused_memory, DEMO_BYTE_POOL_SIZE); | ||
|
||
/* Put system definition stuff in here, e.g. thread creates and other assorted | ||
create information. */ | ||
|
||
/* Allocate the stack for thread 0. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
/* Create the main thread. */ | ||
tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, | ||
pointer, DEMO_STACK_SIZE, | ||
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); | ||
|
||
|
||
/* Allocate the stack for thread 1. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
/* Create threads 1 and 2. These threads pass information through a ThreadX | ||
message queue. It is also interesting to note that these threads have a time | ||
slice. */ | ||
tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, | ||
pointer, DEMO_STACK_SIZE, | ||
16, 16, 4, TX_AUTO_START); | ||
|
||
/* Allocate the stack for thread 2. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, | ||
pointer, DEMO_STACK_SIZE, | ||
16, 16, 4, TX_AUTO_START); | ||
|
||
/* Allocate the stack for thread 3. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
/* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore. | ||
An interesting thing here is that both threads share the same instruction area. */ | ||
tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3, | ||
pointer, DEMO_STACK_SIZE, | ||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); | ||
|
||
/* Allocate the stack for thread 4. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4, | ||
pointer, DEMO_STACK_SIZE, | ||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); | ||
|
||
/* Allocate the stack for thread 5. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
/* Create thread 5. This thread simply pends on an event flag which will be set | ||
by thread_0. */ | ||
tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, | ||
pointer, DEMO_STACK_SIZE, | ||
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); | ||
|
||
/* Allocate the stack for thread 6. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
/* Create threads 6 and 7. These threads compete for a ThreadX mutex. */ | ||
tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6, | ||
pointer, DEMO_STACK_SIZE, | ||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); | ||
|
||
/* Allocate the stack for thread 7. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); | ||
|
||
tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7, | ||
pointer, DEMO_STACK_SIZE, | ||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); | ||
|
||
/* Allocate the message queue. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT); | ||
|
||
/* Create the message queue shared by threads 1 and 2. */ | ||
tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG)); | ||
|
||
/* Create the semaphore used by threads 3 and 4. */ | ||
tx_semaphore_create(&semaphore_0, "semaphore 0", 1); | ||
|
||
/* Create the event flags group used by threads 1 and 5. */ | ||
tx_event_flags_create(&event_flags_0, "event flags 0"); | ||
|
||
/* Create the mutex used by thread 6 and 7 without priority inheritance. */ | ||
tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); | ||
|
||
/* Allocate the memory for a small block pool. */ | ||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT); | ||
|
||
/* Create a block memory pool to allocate a message buffer from. */ | ||
tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE); | ||
|
||
/* Allocate a block and release the block memory. */ | ||
tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT); | ||
|
||
/* Release the block back to the pool. */ | ||
tx_block_release(pointer); | ||
} | ||
|
||
|
||
|
||
/* Define the test threads. */ | ||
|
||
void thread_0_entry(ULONG thread_input) | ||
{ | ||
|
||
UINT status; | ||
|
||
|
||
/* This thread simply sits in while-forever-sleep loop. */ | ||
while(1) | ||
{ | ||
|
||
/* Increment the thread counter. */ | ||
thread_0_counter++; | ||
|
||
/* Sleep for 10 ticks. */ | ||
tx_thread_sleep(10); | ||
|
||
/* Set event flag 0 to wakeup thread 5. */ | ||
status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR); | ||
|
||
/* Check status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
} | ||
} | ||
|
||
|
||
void thread_1_entry(ULONG thread_input) | ||
{ | ||
|
||
UINT status; | ||
|
||
|
||
/* This thread simply sends messages to a queue shared by thread 2. */ | ||
while(1) | ||
{ | ||
|
||
/* Increment the thread counter. */ | ||
thread_1_counter++; | ||
|
||
/* Send message to queue 0. */ | ||
status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER); | ||
|
||
/* Check completion status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
|
||
/* Increment the message sent. */ | ||
thread_1_messages_sent++; | ||
} | ||
} | ||
|
||
|
||
void thread_2_entry(ULONG thread_input) | ||
{ | ||
|
||
ULONG received_message; | ||
UINT status; | ||
|
||
/* This thread retrieves messages placed on the queue by thread 1. */ | ||
while(1) | ||
{ | ||
|
||
/* Increment the thread counter. */ | ||
thread_2_counter++; | ||
|
||
/* Retrieve a message from the queue. */ | ||
status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER); | ||
|
||
/* Check completion status and make sure the message is what we | ||
expected. */ | ||
if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received)) | ||
break; | ||
|
||
/* Otherwise, all is okay. Increment the received message count. */ | ||
thread_2_messages_received++; | ||
} | ||
} | ||
|
||
|
||
void thread_3_and_4_entry(ULONG thread_input) | ||
{ | ||
|
||
UINT status; | ||
|
||
|
||
/* This function is executed from thread 3 and thread 4. As the loop | ||
below shows, these function compete for ownership of semaphore_0. */ | ||
while(1) | ||
{ | ||
|
||
/* Increment the thread counter. */ | ||
if (thread_input == 3) | ||
thread_3_counter++; | ||
else | ||
thread_4_counter++; | ||
|
||
/* Get the semaphore with suspension. */ | ||
status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); | ||
|
||
/* Check status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
|
||
/* Sleep for 2 ticks to hold the semaphore. */ | ||
tx_thread_sleep(2); | ||
|
||
/* Release the semaphore. */ | ||
status = tx_semaphore_put(&semaphore_0); | ||
|
||
/* Check status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
} | ||
} | ||
|
||
|
||
void thread_5_entry(ULONG thread_input) | ||
{ | ||
|
||
UINT status; | ||
ULONG actual_flags; | ||
|
||
|
||
/* This thread simply waits for an event in a forever loop. */ | ||
while(1) | ||
{ | ||
|
||
/* Increment the thread counter. */ | ||
thread_5_counter++; | ||
|
||
/* Wait for event flag 0. */ | ||
status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR, | ||
&actual_flags, TX_WAIT_FOREVER); | ||
|
||
/* Check status. */ | ||
if ((status != TX_SUCCESS) || (actual_flags != 0x1)) | ||
break; | ||
} | ||
} | ||
|
||
|
||
void thread_6_and_7_entry(ULONG thread_input) | ||
{ | ||
|
||
UINT status; | ||
|
||
|
||
/* This function is executed from thread 6 and thread 7. As the loop | ||
below shows, these function compete for ownership of mutex_0. */ | ||
while(1) | ||
{ | ||
|
||
/* Increment the thread counter. */ | ||
if (thread_input == 6) | ||
thread_6_counter++; | ||
else | ||
thread_7_counter++; | ||
|
||
/* Get the mutex with suspension. */ | ||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); | ||
|
||
/* Check status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
|
||
/* Get the mutex again with suspension. This shows | ||
that an owning thread may retrieve the mutex it | ||
owns multiple times. */ | ||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); | ||
|
||
/* Check status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
|
||
/* Sleep for 2 ticks to hold the mutex. */ | ||
tx_thread_sleep(2); | ||
|
||
/* Release the mutex. */ | ||
status = tx_mutex_put(&mutex_0); | ||
|
||
/* Check status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
|
||
/* Release the mutex again. This will actually | ||
release ownership since it was obtained twice. */ | ||
status = tx_mutex_put(&mutex_0); | ||
|
||
/* Check status. */ | ||
if (status != TX_SUCCESS) | ||
break; | ||
} | ||
} |
Oops, something went wrong.