/** * \b test2_thread_func * * Entry point for test thread 2. * * @param[in] param Unused (optional thread entry parameter) * * @return None */ static void test2_thread_func (uint32_t param) { uint8_t status; /* Compiler warnings */ param = param; /* * Wait on sem1 with timeout. We are expecting to be woken up * by the main thread while blocking. */ status = atomSemGet(&sem1, (5 * SYSTEM_TICKS_PER_SEC)); if (status != ATOM_ERR_DELETED) { ATOMLOG (_STR("Test2 thread woke without deletion (%d)\n"), status); } else { /* We were woken due to deletion as expected, post sem2 to notify success */ if ((status = atomSemPut(&sem2)) != ATOM_OK) { ATOMLOG (_STR("Error posting sem2 on wakeup\n")); } } /* Wait forever */ while (1) { atomTimerDelay (SYSTEM_TICKS_PER_SEC); } }
/** * \b test_thread_func * * Entry point for test thread. The same thread entry point is used for all * four test threads, with the thread number/ID (1-4) passed as the entry * point parameter. * * @param[in] param Thread number (1,2,3,4) * * @return None */ static void test_thread_func (uint32_t param) { uint8_t thread_id; /* Thread ID is passed through the function parameter */ thread_id = (uint8_t)param; /* * Wait for sem1 to be posted. At creation of all test threads * the semaphore count is zero, so all four threads will block * here. */ if (atomSemGet (&sem1, 0) != ATOM_OK) { ATOMLOG (_STR("Thread sem fail\n")); } else { /* * Store our thread ID in the array using the current * wake_cnt order. The threads are deliberately woken up * some time apart to ensure that no protection is required * on this global data. */ wake_order[wake_cnt++] = thread_id; } /* Loop forever */ while (1) { atomTimerDelay (SYSTEM_TICKS_PER_SEC); } }
void uartProcess_thread_func (uint32_t param) { volatile uint32_t use=0,free=0; while (1) { //wait forever if (atomSemGet(&uart3Rxsem, 0) == ATOM_OK) { #ifdef GPS atomMutexGet (&gpsDatamutex,0); for (uint8_t i=0;i<rxDataBuff.len;i++) { GPSData.buff[i] = rxDataBuff.buff[i]; } atomMutexPut (&gpsDatamutex); atomSemPut (&gpsDatasem); #endif #ifdef CLI //UART send data to cli for (uint8_t i=0;i<rxDataBuff.len;i++) { cmdData.buff[i] = rxDataBuff.buff[i]; } cmdData.bufflen = rxDataBuff.len; atomSemPut (&cmdShellsem); #endif //get the used RAM atomThreadStackCheck (&uartProcess_tcb, (uint32_t*)&use, (uint32_t*)&free); taskState.taskRAMMax[uartProcess_tcb.threadNum][0]=(uint16_t)use; taskState.taskRAMMax[uartProcess_tcb.threadNum][1]=(uint16_t)free; } } }
/** * \b test_thread_func * * Entry point for test threads. * * @param[in] param Thread ID (0-2) * * @return None */ static void test_thread_func (uint32_t param) { uint8_t status; int thread_id; /* Pull out the passed thread ID */ thread_id = (int)param; /* * Wait on sem1 with timeout. We are expecting to be woken up * by the main thread while blocking. */ status = atomSemGet(&sem1, (5 * SYSTEM_TICKS_PER_SEC)); if (status != ATOM_ERR_DELETED) { ATOMLOG (_STR("Test1 thread woke without deletion (%d)\n"), status); } else { /* We were woken due to deletion as expected, set pass_flag to notify success */ pass_flag[thread_id] = TRUE; } /* Wait forever */ while (1) { atomTimerDelay (SYSTEM_TICKS_PER_SEC); } }
/** * \b test_thread_func * * Entry point for test thread. * * @param[in] param Unused (optional thread entry parameter) * * @return None */ static void test_thread_func (uint32_t param) { uint8_t status; int count; int failures; /* Compiler warnings */ param = param; /* * Attempt to decrement sem1 ten times, which should happen immediately * each time. */ failures = 0; count = INITIAL_SEM_COUNT; while (count--) { /* Decrement sem1 */ if ((status = atomSemGet (&sem1, -1)) != ATOM_OK) { /* Error decrementing semaphore, notify the status code */ ATOMLOG (_STR("G%d\n"), status); failures++; } } /* Check above stage was successful */ if (failures == 0) { /* Sem1 should now have a count of zero, and not allow a decrement */ if ((status = atomSemGet (&sem1, -1)) != ATOM_WOULDBLOCK) { /* Error getting semaphore, notify the status code */ ATOMLOG (_STR("W%d\n"), status); } /* Post sem2 to notify that the test passed */ else if ((status = atomSemPut (&sem2)) != ATOM_OK) { /* Error putting semaphore, notify the status code */ ATOMLOG (_STR("P%d\n"), status); } } /* Loop forever */ while (1) { atomTimerDelay (SYSTEM_TICKS_PER_SEC); } }
/** * \b test_thread_func * * Entry point for test thread. The same thread entry point is used for all * four test threads. * * @param[in] param Unused (optional thread entry parameter) * * @return None */ static void test_thread_func (uint32_t param) { uint32_t loop_cnt; uint8_t status; CRITICAL_STORE; /* Compiler warnings */ param = param; /* Run a Get/Put pair many times */ loop_cnt = NUM_TEST_LOOPS; while (loop_cnt--) { if ((status = atomSemGet (&sem1, 0)) != ATOM_OK) { /* Error getting semaphore, notify the status code */ ATOMLOG (_STR("G%d\n"), status); CRITICAL_START (); g_failures++; CRITICAL_END (); break; } else if ((status = atomSemPut (&sem1)) != ATOM_OK) { /* Error putting semaphore, notify the status code */ ATOMLOG (_STR("P%d\n"), status); CRITICAL_START (); g_failures++; CRITICAL_END (); break; } } /* Post sem2 to notify the main thread we're finished */ if (atomSemPut (&sem2) != ATOM_OK) { ATOMLOG (_STR("Sem2 putfail\n")); CRITICAL_START (); g_failures++; CRITICAL_END (); } /* Loop forever */ while (1) { atomTimerDelay (SYSTEM_TICKS_PER_SEC); } }
/** * \b test_thread_func * * Entry point for test thread. * * @param[in] param Unused (optional thread entry parameter) * * @return None */ static void test_thread_func (uint32_t param) { uint8_t status; /* Compiler warnings */ param = param; /* Repeatedly attempt to get the mutex and set shared_data to 1 */ while (1) { /* Block on the mutex sem1 */ if ((status = atomSemGet (&sem1, 0)) != ATOM_OK) { /* Error getting semaphore, notify the status code */ ATOMLOG (_STR("G%d\n"), status); break; } /* Got the mutex */ else { /* Set shared_data to signify that we think we have the mutex */ shared_data = 1; /* Release the mutex allowing the main thread to take it again */ if ((status = atomSemPut (&sem1)) != ATOM_OK) { /* Error putting semaphore, notify the status code */ ATOMLOG (_STR("P%d\n"), status); break; } } } /* Loop forever - we only reach here on error */ while (1) { atomTimerDelay (SYSTEM_TICKS_PER_SEC); } }
/** * \b test_start * * Start semaphore test. * * This tests basic counting semaphore operation between two threads. * * A semaphore is created with a count of 10. A second thread then * ensures that it can decrement the semaphore 10 times before * it can no longer be decremented. * * @retval Number of failures */ uint32_t test_start (void) { int failures; /* Default to zero failures */ failures = 0; /* Create sem with count ten for second thread to decrement */ if (atomSemCreate (&sem1, INITIAL_SEM_COUNT) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 1\n")); failures++; } /* Create sem to receive test-passed notification */ else if (atomSemCreate (&sem2, 0) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 1\n")); failures++; } else { /* Check that sem2 doesn't already have a positive count */ if (atomSemGet (&sem2, -1) != ATOM_WOULDBLOCK) { ATOMLOG (_STR("Sem2 already put\n")); failures++; } /* Create second thread */ else if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test_thread_func, 1, &test_thread_stack[0][TEST_THREAD_STACK_SIZE - 1], TEST_THREAD_STACK_SIZE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread\n")); failures++; } /* * The second thread has now been created and will attempt to * decrement sem1 ten times, then finally check that it cannot * decrement it any further. If this passes then the second * thread will post sem2 to notify us that the test has passed. */ else { /* Give the second thread one second to post sem2 */ if (atomSemGet (&sem2, SYSTEM_TICKS_PER_SEC) != ATOM_OK) { ATOMLOG (_STR("Sem2 not posted\n")); failures++; } } /* Delete semaphores, test finished */ if (atomSemDelete (&sem1) != ATOM_OK) { ATOMLOG (_STR("Delete failed\n")); failures++; } if (atomSemDelete (&sem2) != ATOM_OK) { ATOMLOG (_STR("Delete failed\n")); failures++; } } /* Check thread stack usage (if enabled) */ #ifdef ATOM_STACK_CHECKING { uint32_t used_bytes, free_bytes; int thread; /* Check all threads */ for (thread = 0; thread < NUM_TEST_THREADS; thread++) { /* Check thread stack usage */ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK) { ATOMLOG (_STR("StackCheck\n")); failures++; } else { /* Check the thread did not use up to the end of stack */ if (free_bytes == 0) { ATOMLOG (_STR("StackOverflow %d\n"), thread); failures++; } /* Log the stack usage */ #ifdef TESTS_LOG_STACK_USAGE ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes); #endif } } } #endif /* Quit */ return failures; }
/** * \b test_start * * Start semaphore test. * * This test exercises the semaphore creation and deletion APIs, including * waking threads blocking on a semaphore if the semaphore is deleted. * Deletion wakeups are tested twice: once for a thread which is blocking * with a timeout and once for a thread which is blocking with no timeout. * * @retval Number of failures */ uint32_t test_start (void) { int failures; uint32_t i; uint8_t status; /* Default to zero failures */ failures = 0; /* Test creation and deletion of semaphores: good values */ for (i = 0; i < 1000; i++) { if (atomSemCreate (&sem1, 0) == ATOM_OK) { if (atomSemDelete (&sem1) == ATOM_OK) { /* Success */ } else { /* Fail */ ATOMLOG (_STR("Error deleting semaphore\n")); failures++; break; } } else { /* Fail */ ATOMLOG (_STR("Error creating semaphore\n")); failures++; break; } } /* Test creation and deletion of semaphores: creation checks */ if (atomSemCreate (NULL, 0) != ATOM_OK) { /* Success */ } else { /* Fail */ ATOMLOG (_STR("Bad semaphore creation checks\n")); failures++; } /* Test creation and deletion of semaphores: deletion checks */ if (atomSemDelete (NULL) != ATOM_OK) { /* Success */ } else { /* Fail */ ATOMLOG (_STR("Bad semaphore deletion checks\n")); failures++; } /* Test wakeup of threads on semaphore deletion (thread blocking with no timeout) */ if (atomSemCreate (&sem1, 0) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 1\n")); failures++; } else if (atomSemCreate (&sem2, 0) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 2\n")); failures++; } else if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test1_thread_func, 0, &test_thread_stack[0][TEST_THREAD_STACK_SIZE - 1], TEST_THREAD_STACK_SIZE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread 1\n")); failures++; } else { /* * We have created two semaphores. sem1 is for the other thread * to wait on, which we will delete from this thread. We want * to see that the other thread is woken up if its semaphore * is deleted. This is indicated through sem2 being posted * back to us. */ /* Wait for the other thread to start blocking on sem1 */ if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK) { ATOMLOG (_STR("Failed timer delay\n")); failures++; } else { /* The other thread will be blocking on sem1 now, delete sem1 */ if (atomSemDelete(&sem1) != ATOM_OK) { ATOMLOG (_STR("Failed sem1 delete\n")); failures++; } else { /* Sem1 deleted. The thread should now wake up and post sem2. */ if ((status = atomSemGet (&sem2, (5*SYSTEM_TICKS_PER_SEC))) != ATOM_OK) { ATOMLOG (_STR("Notify fail (%d)\n"), status); failures++; } else { /* Success */ /* Clean up the last remaining semaphore */ if (atomSemDelete (&sem2) != ATOM_OK) { ATOMLOG (_STR("Failed sem2 delete\n")); failures++; } } } } } /* Test wakeup of threads on semaphore deletion (thread blocking with timeout) */ if (atomSemCreate (&sem1, 0) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 1\n")); failures++; } else if (atomSemCreate (&sem2, 0) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 2\n")); failures++; } else if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO, test2_thread_func, 0, &test_thread_stack[1][TEST_THREAD_STACK_SIZE - 1], TEST_THREAD_STACK_SIZE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread 2\n")); failures++; } else { /* * We have created two semaphores. sem1 is for the other thread * to wait on, which we will delete from this thread. We want * to see that the other thread is woken up if its semaphore * is deleted. This is indicated through sem2 being posted * back to us. */ /* Wait for the other thread to start blocking on sem1 */ if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK) { ATOMLOG (_STR("Failed timer delay\n")); failures++; } else { /* The other thread will be blocking on sem1 now, delete sem1 */ if (atomSemDelete(&sem1) != ATOM_OK) { ATOMLOG (_STR("Failed sem1 delete\n")); failures++; } else { /* Sem1 deleted. The thread should now wake up and post sem2. */ if ((status = atomSemGet (&sem2, (5*SYSTEM_TICKS_PER_SEC))) != ATOM_OK) { ATOMLOG (_STR("Notify fail (%d)\n"), status); failures++; } else { /* Success */ /* Clean up the last remaining semaphore */ if (atomSemDelete (&sem2) != ATOM_OK) { ATOMLOG (_STR("Failed sem2 delete\n")); failures++; } } } } } /* Check thread stack usage (if enabled) */ #ifdef ATOM_STACK_CHECKING { uint32_t used_bytes, free_bytes; int thread; /* Check all threads */ for (thread = 0; thread < NUM_TEST_THREADS; thread++) { /* Check thread stack usage */ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK) { ATOMLOG (_STR("StackCheck\n")); failures++; } else { /* Check the thread did not use up to the end of stack */ if (free_bytes == 0) { ATOMLOG (_STR("StackOverflow %d\n"), thread); failures++; } /* Log the stack usage */ #ifdef TESTS_LOG_STACK_USAGE ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes); #endif } } } #endif /* Quit */ return failures; }
/** * \b test_start * * Start semaphore test. * * This tests usage of a semaphore for basic mutual exclusion type * operation. Note that Atomthreads has a more fully-featured real * mutex implementation in the mutex module. * * The semaphore sem1 is initialised with a count of 1. Whichever * thread holds this semaphore can then modify the global variable * "shared_data". * * The main thread first takes the "mutex" sem1, then creates a * second thread. The second thread should block on the sem1 mutex * until the main thread releases it. The test checks that the * global "shared_data" is not modified by the second thread * until the main thread releases the mutex. * * @retval Number of failures */ uint32_t test_start (void) { int failures; int i; /* Default to zero failures */ failures = 0; /* Create sem with count one for mutex purposes */ if (atomSemCreate (&sem1, 1) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 1\n")); failures++; } else { /* Initialise the shared_data to zero */ shared_data = 0; /* Take the mutex to ensure only this thread can modify shared_data */ if (atomSemGet (&sem1, 0) != ATOM_OK) { ATOMLOG (_STR("Error taking mutex\n")); failures++; } /* Create second thread */ else if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test_thread_func, 1, &test_thread_stack[0][0], TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread\n")); failures++; } /* * The second thread has now been created and should block on * the "mutex" sem1 (which now has count zero) until we release * it. We wait a while and check that shared_data has not been * modified. */ for (i = 0; i < 4; i++) { /* * Sleep for a while to give the second thread a chance to * modify shared_data, thought it shouldn't until we * release the mutex. */ atomTimerDelay (SYSTEM_TICKS_PER_SEC/4); /* Check shared data. The second thread always sets it to one. */ if (shared_data != 0) { ATOMLOG (_STR("Shared data modified\n")); failures++; break; } } /* Check successful so far */ if (failures == 0) { /* * Release the mutex, which will allow the second thread to * wake and start modifying shared_data. */ if (atomSemPut (&sem1) != ATOM_OK) { ATOMLOG (_STR("Failed release\n")); failures++; } /* * Wait a little while then check that shared_data has * been modified. */ atomTimerDelay (SYSTEM_TICKS_PER_SEC/4); if (shared_data != 1) { ATOMLOG (_STR("Expected modify\n")); failures++; } /* * Release and take the mutex again a few times to ensure * that the mutex continues to protect shared_data. */ for (i = 0; i < 4; i++) { /* * Take the mutex again, to prevent second thread accessing * shared_data. */ if (atomSemGet (&sem1, SYSTEM_TICKS_PER_SEC) != ATOM_OK) { ATOMLOG (_STR("Retake %d\n"), i); failures++; break; } else { /* * Set shared_data to 0 and wait to ensure that the * second thread doesn't modify it while we have the * mutex again. */ shared_data = 0; /* Wait a while to give second thread potential to run */ atomTimerDelay(SYSTEM_TICKS_PER_SEC/4); /* * Check that shared_data has not been modified while we * own the mutex. */ if (shared_data != 0) { /* Thread is still modifying the data */ ATOMLOG (_STR("Still modifying\n")); failures++; break; } /* * Release the mutex, which will allow the second thread to * wake and start modifying shared_data again. */ if (atomSemPut (&sem1) != ATOM_OK) { ATOMLOG (_STR("Failed release\n")); failures++; } } } } /* Delete semaphore, test finished */ if (atomSemDelete (&sem1) != ATOM_OK) { ATOMLOG (_STR("Delete failed\n")); failures++; } } /* Check thread stack usage (if enabled) */ #ifdef ATOM_STACK_CHECKING { uint32_t used_bytes, free_bytes; int thread; /* Check all threads */ for (thread = 0; thread < NUM_TEST_THREADS; thread++) { /* Check thread stack usage */ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK) { ATOMLOG (_STR("StackCheck\n")); failures++; } else { /* Check the thread did not use up to the end of stack */ if (free_bytes == 0) { ATOMLOG (_STR("StackOverflow %d\n"), thread); failures++; } /* Log the stack usage */ #ifdef TESTS_LOG_STACK_USAGE ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes); #endif } } } #endif /* Quit */ return failures; }
/** * \b test_start * * Start mutex test. * * Stress-tests mutex Get and Put operations. Four threads are created which are * continually Getting and Putting the same mutex, with no time delays between * each Get/Put. * * @retval Number of g_failures */ uint32_t test_start (void) { CRITICAL_STORE; int finish_cnt; /* Default to zero g_failures */ g_failures = 0; /* Create mutex to stress */ if (atomMutexCreate (&mutex1) != ATOM_OK) { ATOMLOG (_STR("Error creating mutex\n")); g_failures++; } /* Create sem to receive thread-finished notification */ else if (atomSemCreate (&sem1, 0) != ATOM_OK) { ATOMLOG (_STR("Error creating sem\n")); g_failures++; } else { /* Take ownership of the mutex to ensure all threads wait for now */ if (atomMutexGet (&mutex1, 0) != ATOM_OK) { ATOMLOG (_STR("Error taking mutex\n")); g_failures++; } /* Create Thread 1 */ if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test_thread_func, 1, &test_thread_stack[0][TEST_THREAD_STACK_SIZE - 1], TEST_THREAD_STACK_SIZE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread\n")); CRITICAL_START (); g_failures++; CRITICAL_END (); } /* Create Thread 2 */ if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO, test_thread_func, 2, &test_thread_stack[1][TEST_THREAD_STACK_SIZE - 1], TEST_THREAD_STACK_SIZE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread\n")); CRITICAL_START (); g_failures++; CRITICAL_END (); } /* Create Thread 3 */ if (atomThreadCreate(&tcb[2], TEST_THREAD_PRIO, test_thread_func, 3, &test_thread_stack[2][TEST_THREAD_STACK_SIZE - 1], TEST_THREAD_STACK_SIZE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread\n")); CRITICAL_START (); g_failures++; CRITICAL_END (); } /* Create Thread 4 */ if (atomThreadCreate(&tcb[3], TEST_THREAD_PRIO, test_thread_func, 4, &test_thread_stack[3][TEST_THREAD_STACK_SIZE - 1], TEST_THREAD_STACK_SIZE) != ATOM_OK) { /* Fail */ ATOMLOG (_STR("Error creating test thread\n")); CRITICAL_START (); g_failures++; CRITICAL_END (); } /* Release ownership of the mutex to kick the threads off */ if (atomMutexPut (&mutex1) != ATOM_OK) { ATOMLOG (_STR("Error putting mutex\n")); g_failures++; } /* * All four threads will now be performing Gets/Puts on mutex1. * When they have finished they will post sem1, so we wait * until sem1 is posted four times. */ finish_cnt = 0; while (1) { /* * Attempt to Get sem1. When we have managed to get * the semaphore four times, it must have been posted * by all four threads. */ if (atomSemGet (&sem1, 0) == ATOM_OK) { /* Increment our count of finished threads */ finish_cnt++; /* Check if all four threads have now posted sem1 */ if (finish_cnt == 4) { break; } } } /* Delete OS objects, test finished */ if (atomMutexDelete (&mutex1) != ATOM_OK) { ATOMLOG (_STR("Delete failed\n")); CRITICAL_START (); g_failures++; CRITICAL_END (); } if (atomSemDelete (&sem1) != ATOM_OK) { ATOMLOG (_STR("Delete failed\n")); CRITICAL_START (); g_failures++; CRITICAL_END (); } } /* Check thread stack usage (if enabled) */ #ifdef ATOM_STACK_CHECKING { uint32_t used_bytes, free_bytes; int thread; /* Check all threads */ for (thread = 0; thread < NUM_TEST_THREADS; thread++) { /* Check thread stack usage */ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK) { ATOMLOG (_STR("StackCheck\n")); g_failures++; } else { /* Check the thread did not use up to the end of stack */ if (free_bytes == 0) { ATOMLOG (_STR("StackOverflow %d\n"), thread); g_failures++; } /* Log the stack usage */ #ifdef TESTS_LOG_STACK_USAGE ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes); #endif } } } #endif /* Quit */ return g_failures; }