| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- /* 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"
- #include <stdio.h>
- #define DEMO_STACK_SIZE 1024
- #define DEMO_BYTE_POOL_SIZE 10240
- #define DEMO_BLOCK_POOL_SIZE 100
- #define DEMO_QUEUE_SIZE 100
- // NOTE don't turn on all the debug, it really cost time
- // just turn on one and keep others close to see whether thread is running
- //#define DEBUG_THREAD_0
- //#define DEBUG_THREAD_1
- //#define DEBUG_THREAD_2
- //#define DEBUG_THREAD_3_4
- //#define DEBUG_THREAD_5
- #define DEBUG_THREAD_6_7
- /* 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;
- // This is an memory area used by ThreadX to allocate for task stacks and etc
- UCHAR memory_area[DEMO_BYTE_POOL_SIZE];
- /* 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. */
- // NOTE: TODO: first_unused_memory is not used here, since our port don't create a memory for you, you need
- // to prepare it by yourself like memory_area here
- 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", memory_area, 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);
- #ifdef DEBUG_THREAD_0
- printf("thread 0 is running %lu\n", thread_0_counter);
- #endif
- /* 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++;
- #ifdef DEBUG_THREAD_1
- printf("thread 1 is running %lu, msg sent %lu\n", thread_1_counter, thread_1_messages_sent);
- #endif
- }
- }
- 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++;
- #ifdef DEBUG_THREAD_2
- printf("thread 2 is running %lu, msg recv %lu\n", thread_2_counter, thread_2_messages_received);
- #endif
- }
- }
- 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);
- #ifdef DEBUG_THREAD_3_4
- printf("thread 3_4 is running, current is %lu, thread 3 counter %lu, thread 4 counter %lu\n", thread_input, thread_3_counter, thread_4_counter);
- #endif
- /* 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);
- #ifdef DEBUG_THREAD_5
- printf("thread 5 is running %lu\n", thread_5_counter);
- #endif
- /* 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);
- #ifdef DEBUG_THREAD_6_7
- printf("thread 6_7 is running, current is %lu, thread 6 counter %lu, thread 7 counter %lu\n", thread_input, thread_6_counter, thread_7_counter);
- #endif
- /* Check status. */
- if (status != TX_SUCCESS)
- break;
- #ifdef CFG_SIMULATION
- if (thread_7_counter > 2) {
- // directly exit if in nuclei internally simulation
- SIMULATION_EXIT(0);
- }
- #endif
- }
- }
|