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 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 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. * * @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. * * @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 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 semaphore test. * * With multiple threads blocking on a single semaphore, this test confirms that * they are woken in order when the semaphore is posted. The correct order for * waking is that the higher priority threads are woken first, followed by the * lower priority threads. Where multiple threads of the same priority are * waiting, the threads are woken in FIFO order (the order in which they started * waiting on the semaphore). * * To test this we create four threads which all wait on a single semaphore. * One pair of threads are running at high priority, with the other pair at a * lower priority: * * Thread 1: low prio thread A * Thread 2: low prio thread B * Thread 3: high prio thread A * Thread 4: high prio thread B * * The threads are forced to start blocking on the same semaphore in the * above order (the semaphore is initialised with count 0 to ensure any * threads calling atomSemGet() will block). * * We expect to see them woken up in the following order: * 3, 4, 1, 2 * * This proves the multiple blocking thread ordering in terms of both * the priority-queueing and same-priority-FIFO-queueing. * * @retval Number of failures */ uint32_t test_start (void) { int failures; int i; /* Default to zero failures */ failures = 0; /* Create sem with count zero (so that all threads will block) */ if (atomSemCreate (&sem1, 0) != ATOM_OK) { ATOMLOG (_STR("Error creating test semaphore 1\n")); failures++; } else { /* Create Thread 1 (lower priority thread A) */ if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO+1, 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++; } /* Delay to ensure the thread will start blocking on the semaphore */ atomTimerDelay (SYSTEM_TICKS_PER_SEC/4); /* Create Thread 2 (lower priority thread B) */ if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO+1, 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")); failures++; } /* Delay to ensure the thread will start blocking on the semaphore */ atomTimerDelay (SYSTEM_TICKS_PER_SEC/4); /* Create Thread 3 (higher priority thread A) */ 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")); failures++; } /* Delay to ensure the thread will start blocking on the semaphore */ atomTimerDelay (SYSTEM_TICKS_PER_SEC/4); /* Create Thread 4 (higher priority thread B) */ 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")); failures++; } /* Delay to ensure the thread will start blocking on the semaphore */ atomTimerDelay (SYSTEM_TICKS_PER_SEC/4); /* All four threads will now be blocking on sem1 */ /* * Initialise wake count, used by threads to determine * what order they were woken in. */ wake_cnt = 0; /* * Wake the four threads up in order, leaving some time between * each wake up for them to deal with global data in a * thread-safe fashion. */ for (i = 0; i < 4; i++) { /* Post semaphore to wake one of the threads up */ if (atomSemPut (&sem1) != ATOM_OK) { ATOMLOG (_STR("Post fail\n")); failures++; } /* Sleep to give the thread time to manipulate global data */ atomTimerDelay (SYSTEM_TICKS_PER_SEC / 4); } /* All four threads now woken up, check they woke in correct order */ if ((wake_order[0] != 3) || (wake_order[1] != 4) || (wake_order[2] != 1) || (wake_order[3] != 2)) { ATOMLOG (_STR("Bad order %d,%d,%d,%d\n"), wake_order[0], wake_order[1], wake_order[2], wake_order[3]); 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; }