示例#1
0
/**
 * \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;

    /*
     * Take mutex2 so that main thread can test mutex APIs on a mutex
     * which it does not own.
     */
    status = atomMutexGet(&mutex2, 0);
    if (status != ATOM_OK)
    {
        ATOMLOG (_STR("Mutex get (%d)\n"), status);
    }
    else
    {
        /* We took ownership of mutex2, set g_owned to notify success */
        g_owned = 1;
    }

    /* Wait forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#2
0
/**
 * \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);
    }
}
示例#3
0
/**
 * \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;
    uint8_t msg;
    int thread_id;

    /* Pull out the passed thread ID */
    thread_id = (int)param;

    /*
     * Wait on queue1 with timeout. We are expecting to be woken up
     * by the main thread while blocking.
     */
    status = atomQueueGet(&queue1, (5 * SYSTEM_TICKS_PER_SEC), &msg);
    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);
    }
}
示例#4
0
/**
 * \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, msg;

    /* Compiler warnings */
    param = param;

    /*
     * Wait on queue1 with timeout. We are expecting to be woken up
     * by the main thread while blocking.
     */
    status = atomQueueGet(&queue1, (5 * SYSTEM_TICKS_PER_SEC), &msg);
    if (status != ATOM_ERR_DELETED)
    {
        ATOMLOG (_STR("Test2 thread woke without deletion (%d)\n"), status);
    }
    else
    {
        /* We were woken due to deletion as expected, set g_result to notify success */
        g_result = 1;
    }

    /* Wait forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#5
0
/**
 * \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, msg;

    /* Compiler warnings */
    param = param;

    /* Set a test value for posting to the queue */
    msg = 0x66;

    /*
     * Post to queue1 with timeout. The queue should be full so
     * we are expecting to block. We should then be woken up by the
     * main thread while blocking.
     */
    status = atomQueuePut(&queue1, (5 * SYSTEM_TICKS_PER_SEC), &msg);
    if (status != ATOM_ERR_DELETED)
    {
        ATOMLOG (_STR("Test2 thread woke without deletion (%d)\n"), status);
    }
    else
    {
        /* We were woken due to deletion as expected, set g_result to notify success */
        g_result = 1;
    }

    /* Wait forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#6
0
/**
 * \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);
    }
}
示例#7
0
/**
 * \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;

    /* Block on the mutex */
    if ((status = atomMutexGet (&mutex1, 0)) != ATOM_OK)
    {
        /* Error getting mutex, notify the status code */
        ATOMLOG (_STR("G%d\n"), status);
    }

    /* Got the mutex */
    else
    {
        /* Set shared_data to signify that we think we have the mutex */
        shared_data = 1;
    }

    /* Loop forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#8
0
/**
 * \b test_thread_func
 *
 * Entry point for test thread. The same thread entry point is used for all
 * three test threads, with the thread number/ID (1-3) passed as the entry
 * point parameter.
 *
 * @param[in] param Thread number (1,2,3)
 *
 * @return None
 */
static void test_thread_func (uint32_t param)
{
    uint8_t thread_id;
    uint32_t start_time, end_time;

    /* Thread ID is passed through the function parameter */
    thread_id = (uint8_t)param;

    /*
     * Sleep for 1 tick to ensure that the thread starts near
     * a timer tick boundary. This ensures that the system
     * tick does not advance between the atomTimeGet() call
     * and the actual atomTimerDelay() call being made.
     */
    atomTimerDelay (1);

    /* Loop running the test forever */
    while (1)
    {
        /* Record the start time */
        start_time = atomTimeGet();

        /* Sleep for n ticks, where n is the thread ID */
        if (atomTimerDelay(thread_id) != ATOM_OK)
        {
            g_failure_cnt[thread_id-1]++;
        }
        else
        {
            /* Record the time we woke up */
            end_time = atomTimeGet();

            /* Check that time has advanced by exactly n ticks */
            if ((end_time - start_time) != thread_id)
            {
                g_failure_cnt[thread_id-1]++;
            }
        }
    }
}
示例#9
0
/**
 * \b main_thread_func
 *
 * Entry point for main application thread.
 *
 * This is the first thread that will be executed when the OS is started.
 *
 * @param[in] data Unused (optional thread entry parameter)
 *
 * @return None
 */
static void main_thread_func (uint32_t data)
{
    uint32_t test_status;

    /* Put a message out on the UART */
    ATOMLOG("Go\n");

    /* Start test. All tests use the same start API. */
    test_status = test_start();

    /* Check main thread stack usage (if enabled) */
#ifdef ATOM_STACK_CHECKING
    if (test_status == 0)
    {
        uint32_t used_bytes, free_bytes;

        /* Check idle thread stack usage */
        if (atomThreadStackCheck (&main_tcb, &used_bytes, &free_bytes) == ATOM_OK)
        {
            /* Check the thread did not use up to the end of stack */
            if (free_bytes == 0)
            {
                ATOMLOG("Main stack overflow\n");
                test_status++;
            }

            /* Log the stack usage */
#ifdef TESTS_LOG_STACK_USAGE
            ATOMLOG("MainUse:%d\n", used_bytes);
#endif
        }

    }
#endif

    /* Log final status */
    if (test_status == 0)
    {
        ATOMLOG("Pass\n");
    }
    else
    {
        ATOMLOG("Fail(%d)\n", test_status);
    }

    /* Test finished, sit idle */
    while (1)
    {
        atomTimerDelay(SYSTEM_TICKS_PER_SEC);
    }
}
示例#10
0
/**
 * \b test1_thread_func
 *
 * Entry point for test thread 1.
 *
 * @param[in] param Unused (optional thread entry parameter)
 *
 * @return None
 */
static void test1_thread_func (uint32_t param)
{
    uint32_t msg;
    int num_entries, count, failures;

    /* Compiler warnings */
    param = param;

    /* Default to no errors */
    failures = 0;

    /*
     * Loop receiving messages until we have received the number of
     * values in the test array.
     */
    num_entries = sizeof(test_values) / sizeof(test_values[0]);
    for (count = 0; count < num_entries; count++)
    {
        /* Receive a value from the queue */
        if (atomQueueGet (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
        {
            ATOMLOG (_STR("Failed get\n"));
            failures++;
        }

        /* Check that we received the expected value */
        else if (msg != test_values[count])
        {
            ATOMLOG (_STR("Val%d\n"), count);
            failures++;
        }
    }

    /*
     * Set g_result to indicate success if we had no failures.
     * Thread-protection is not required on g_result because it
     * is only ever set by this thread.
     */
    if (failures == 0)
    {
        /* No failures */
        g_result = 1;
    }

    /* Wait forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#11
0
文件: main.c 项目: navaro/atomthreads
/**
 * \b test_thread
 *
 * Function calling the test function of the Atomthreads test suite.
 *
 */
void
test_thread (uint32_t param)
{
    uint32_t failures ;
    CRITICAL_STORE ;

    failures = test_start ()  ;

    atomTimerDelay (10) ;
    CRITICAL_START() ;
    printf ("%s %s\r\n", ATOMTHREADS_TEST, failures ? "FAIL" : "PASS") ;
    exit (failures) ;
    CRITICAL_END() ;
}
示例#12
0
/**
 * \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 = atomMutexGet (&mutex1, 0)) != ATOM_OK)
        {
            /* Error getting mutex, notify the status code */
            ATOMLOG (_STR("G%d\n"), status);
            CRITICAL_START ();
            g_failures++;
            CRITICAL_END ();
            break;
        }
        else if ((status = atomMutexPut (&mutex1)) != ATOM_OK)
        {
            /* Error putting mutex, notify the status code */
            ATOMLOG (_STR("P%d\n"), status);
            CRITICAL_START ();
            g_failures++;
            CRITICAL_END ();
            break;
        }
    }

    /* Post sem1 to notify the main thread we're finished */
    if (atomSemPut (&sem1) != ATOM_OK)
    {
        ATOMLOG (_STR("Sem1 putfail\n"));
        CRITICAL_START ();
        g_failures++;
        CRITICAL_END ();
    }

    /* Loop forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#13
0
/**
 * \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);
    }
}
示例#14
0
u8 flashEraseSector(u32 sector)
{
	u32  sectorAddr = ((u32)sector << 12);
  u8   timeout=TIMEOUT;
  flashWriteEnable();                                                           //开启写使能
  FILECS_LOW;                                                                   //使能设备

  spiSendByte(SECTOR_ERA_COM);                                                  //扇区擦除
  spiSendByte((u8)(sectorAddr>>16));                                            //发送地址
  spiSendByte((u8)(sectorAddr>>8));                                             //发送地址
  spiSendByte((u8)(sectorAddr));                                                //发送地址

  FILECS_HIGH;                                                                  //禁能设备
  while (flashReadStateCom()&STATUS_WIP){
    atomTimerDelay (1);
    if (0==(timeout--))break;
	}
  return 0x01;
}
示例#15
0
/**
 * \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);
    }
}
示例#16
0
/**
 * \b test_thread_func
 *
 * Entry point for test thread.
 *
 * @param[in] param Thread ID (0 = low prio, 1 = high prio)
 *
 * @return None
 */
static void test_thread_func (uint32_t param)
{
    int thread_id;

    /* Pull out thread ID */
    thread_id = (int)param;

    /* Run forever */
    while (1)
    {
        /* If this thread is requested to sleep, sleep until told to stop */
        if (sleep_request[thread_id])
        {
            atomTimerDelay (1);
        }
        else
        {
            /* Otherwise set running flag for this thread */
            running_flag[thread_id] = TRUE;
        }
    }
}
示例#17
0
/**
 * \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 mutex1 to be posted. At creation of all test threads the mutex
     * is owned by the parent thread, so all four threads will block here.
     */
    if (atomMutexGet (&mutex1, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Get fail\n"));
    }
    else
    {
        /*
         * Store our thread ID in the array using the current
         * wake_cnt order. The threads are holding ownership
         * of a mutex here, which provides protection for this
         * global data.
         */
        wake_order[wake_cnt++] = thread_id;

        /* Release the mutex so that the next thread wakes up */
        if (atomMutexPut (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Put fail\n"));
        }

    }

    /* Loop forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#18
0
/*
 * flash最多写一个page,256字节
 * *buf数据指针
 * pageAddr写入地址  (不一定是page头)
 * writeNum写入数据byte量
 */
void flashWritePage(u8 *buf, u32 pageAddr, u16 writeNum)
{
  u8 timeout=TIMEOUT;
  flashWriteEnable();
	FILECS_LOW;                                                                   //使能设备
	
	spiSendByte(PAGE_PRO_COM);                                                    //发送写数据命令
  spiSendByte((u8)(pageAddr>>16));                                              //发送地址
  spiSendByte((u8)(pageAddr>>8));                                               //发送地址
  spiSendByte((u8)(pageAddr));                                                  //发送地址
	
	for (u16 i=0; i<writeNum; i++){
		spiSendByte(*buf);																												  //数据发送
		buf++;
	}
	FILECS_HIGH;
  
  while (flashReadStateCom()&STATUS_WIP){
    atomTimerDelay (1);
    if (0==(timeout--))break;
	}
}
示例#19
0
/**
 * \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;
    uint8_t msg;

    /* Thread ID is passed through the function parameter */
    thread_id = (uint8_t)param;

    /*
     * Wait for a message to appear on queue1. At creation of all test
     * threads the queue is empty, so all four threads will block here.
     */
    if (atomQueueGet (&queue1, 0, &msg) != ATOM_OK)
    {
        ATOMLOG (_STR("Get fail\n"));
    }
    else
    {
        /*
         * Store our thread ID in the array using the current
         * wake_cnt order. The threads are woken with large
         * pauses between, which provides protection for this
         * global data. This allows us to test queues without
         * assuming a working implementation of a mutex (or
         * similar protection mechanism).
         */
        wake_order[wake_cnt++] = thread_id;

    }

    /* Loop forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
示例#20
0
void clock_update_func (uint32_t data)
{
	while(1) {
		// Increment time (global variables protected by mutex lock)
		if (atomMutexGet(&clock_mutex, 0) == ATOM_OK) {

			g_sec++;
			if (g_sec > 59) {
				g_sec = 0;
				g_min++;
				if (g_min > 59) {
					g_min = 0;
					g_hour++;
					if (g_hour > 23)
						g_hour = 0;
				}
			}
			
		}
		atomMutexPut(&clock_mutex);
		atomTimerDelay(100);

	}
}
示例#21
0
/**
 * \b test_start
 *
 * Start mutex test.
 *
 * This test exercises the atomMutexGet() and atomMutexPut() APIs including
 * forcing the various error indications which can be returned from the
 * APIs to ensure that handling for these corner cases have been correctly
 * implemented.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    uint8_t status;
    ATOM_TIMER timer_cb;
    int count;

    /* Default to zero failures */
    failures = 0;

    /* Test parameter checks */
    if (atomMutexGet (NULL, 0) != ATOM_ERR_PARAM)
    {
        ATOMLOG (_STR("Get param failed\n"));
        failures++;
    }
    if (atomMutexPut (NULL) != ATOM_ERR_PARAM)
    {
        ATOMLOG (_STR("Put param failed\n"));
        failures++;
    }

    /* Test atomMutexGet() can not be called from interrupt context */
    g_result = 0;
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test mutex1\n"));
        failures++;
    }
    else
    {
        /* Fill out the timer callback request structure */
        timer_cb.cb_func = testCallback;
        timer_cb.cb_data = NULL;
        timer_cb.cb_ticks = SYSTEM_TICKS_PER_SEC;

        /* Request the timer callback to run in one second */
        if (atomTimerRegister (&timer_cb) != ATOM_OK)
        {
            ATOMLOG (_STR("Error registering timer\n"));
            failures++;
        }

        /* Wait two seconds for g_result to be set indicating success */
        else
        {
            atomTimerDelay (2 * SYSTEM_TICKS_PER_SEC);
            if (g_result != 1)
            {
                ATOMLOG (_STR("Context check failed\n"));
                failures++;
            }
        }

        /* Delete the test mutex */
        if (atomMutexDelete (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Mutex1 delete failed\n"));
            failures++;
        }
    }

    /* Create mutex1 which will be owned by us */
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test mutex 1\n"));
        failures++;
    }

    /* Create mutex2 which will be owned by another thread */
    else if (atomMutexCreate (&mutex2) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test mutex 2\n"));
        failures++;
    }

    /* Create a test thread, the sole purpose of which is to own mutex2 */
    g_owned = 0;
    if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test_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++;
    }

    /* Sleep until the test thread owns mutex2 */
    atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    if (g_owned == 0)
    {
        ATOMLOG (_STR("Thread own fail\n"));
        failures++;
    }

    /* Test wait on mutex with timeout - should timeout while owned by another thread */
    if ((status = atomMutexGet (&mutex2, SYSTEM_TICKS_PER_SEC)) != ATOM_TIMEOUT)
    {
        ATOMLOG (_STR("Get %d\n"), status);
        failures++;
    }
    else
    {
        /* Success */
    }

    /* Test wait on mutex with no blocking - should return that owned by another thread */
    if ((status = atomMutexGet (&mutex2, -1)) != ATOM_WOULDBLOCK)
    {
        ATOMLOG (_STR("Wouldblock err %d\n"), status);
        failures++;
    }

    /* Test wait on mutex with no blocking when mutex is available */
    if (atomMutexGet (&mutex1, -1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error taking mutex1\n"));
        failures++;
    }
    else
    {
        /* Relinquish ownership of mutex1 */
        if (atomMutexPut (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Error posting mutex\n"));
            failures++;
        }
    }

    /* Test for lock count overflows with too many gets */
    count = 255;
    while (count--)
    {
        if (atomMutexGet (&mutex1, 0) != ATOM_OK)
        {
            ATOMLOG (_STR("Error getting mutex1\n"));
            failures++;
            break;
        }
    }

    /* The lock count should overflow this time */
    if (atomMutexGet (&mutex1, 0) != ATOM_ERR_OVF)
    {
        ATOMLOG (_STR("Error tracking overflow\n"));
        failures++;
    }
    else
    {
        /* Success */
    }

    /* Delete the test mutexes */
    if (atomMutexDelete (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error deleting mutex1\n"));
        failures++;
    }
    if (atomMutexDelete (&mutex2) != ATOM_OK)
    {
        ATOMLOG (_STR("Error deleting mutex2\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;
}
示例#22
0
/**
 * \b main_thread_func
 *
 * Entry point for main application thread.
 *
 * This is the first thread that will be executed when the OS is started.
 *
 * @param[in] data Unused (optional thread entry parameter)
 *
 * @return None
 */
static void main_thread_func (uint32_t data)
{
    uint32_t test_status;
    int sleep_ticks;

    /* Enable all LEDs (STK500-specific) */
    DDRB = 0xFF;
    PORTB = 0xFF;

    /* Initialise UART (9600bps) */
    if (uart_init(9600) != 0)
    {
        /* Error initialising UART */
    }

    /**
     * Redirect stdout via the UART. Note that the UART write routine
     * is protected via a semaphore, so the OS must be started before
     * use of the UART.
     */
    stdout = &uart_stdout;

    /* Put a message out on the UART */
    printf_P(PSTR("Go\n"));

    /* Start test. All tests use the same start API. */
    //test_status = test_start();

    /* Check main thread stack usage (if enabled) */
#ifdef ATOM_STACK_CHECKING
    if (test_status == 0)
    {
        uint32_t used_bytes, free_bytes;

        /* Check idle thread stack usage */
        if (atomThreadStackCheck (&main_tcb, &used_bytes, &free_bytes) == ATOM_OK)
        {
            /* Check the thread did not use up to the end of stack */
            if (free_bytes == 0)
            {
                printf_P (PSTR("Main stack overflow\n"));
                test_status++;
            }

            /* Log the stack usage */
#ifdef TESTS_LOG_STACK_USAGE
            printf_P (PSTR("MainUse:%d\n"), used_bytes);
#endif
        }

    }
#endif

    /* Log final status */
    if (test_status == 0)
    {
        printf_P (PSTR("Pass\n"));
    }
    else
    {
        printf_P (PSTR("Fail(%d)\n"), test_status);
    }

    /* Flash LED once per second if passed, very quickly if failed */
    sleep_ticks = (test_status == 0) ? SYSTEM_TICKS_PER_SEC : (SYSTEM_TICKS_PER_SEC/8);

    /* Test finished, flash slowly for pass, fast for fail */
    while (1)
    {
        /* Toggle a LED (STK500-specific) */
        PORTB ^= (1 << 7);

        /* Sleep then toggle LED again */
        atomTimerDelay(sleep_ticks);
    }

}
示例#23
0
/**
 * \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;
}
示例#24
0
/**
 * \b test_start
 *
 * Start queue test.
 *
 * This test exercises queue deletion, waking threads blocking on a queue
 * in atomQueuePut() if the queue is deleted.
 *
 * Deletion wakeups are tested twice: once for a thread which is blocking
 * in atomQueuePut() with a timeout and once for a thread which is
 * blocking in atomQueuePut() with no timeout.
 *
 * Deletion of threads blocking in atomQueueGet() are tested in queue2.c.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures, i;
    uint8_t msg;

    /* Default to zero failures */
    failures = 0;

    /* Set a test value for posting to the queue */
    msg = 0x66;

    /* Test wakeup of threads on queue deletion (thread blocking with no timeout) */
    g_result = 0;
    if (atomQueueCreate (&queue1, &queue1_storage[0], sizeof(uint8_t), QUEUE_ENTRIES) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test queue\n"));
        failures++;
    }

    /* Successful queue creation */
    else
    {
        /* Fill up all entries */
        for (i = 0; i < QUEUE_ENTRIES; i++)
        {
            if (atomQueuePut (&queue1, 0, &msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Error filling queue\n"));
                failures++;
            }
        }

        /* Create a test thread that will block because the queue is full */
        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 and filled a queue. We want to see that the other
             * thread is woken up if its queue is deleted. This is indicated
             * through g_result being set.
             */

            /* Wait for the other thread to start blocking on queue1 */
            if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed timer delay\n"));
                failures++;
            }
            else
            {
                /* The other thread will be blocking on queue1 now, delete queue1 */
                if (atomQueueDelete(&queue1) != ATOM_OK)
                {
                    ATOMLOG (_STR("Failed queue1 delete\n"));
                    failures++;
                }
                else
                {
                    /* Queue1 deleted. The thread should now wake up and set g_result. */
                    atomTimerDelay (SYSTEM_TICKS_PER_SEC);
                    if (g_result == 0)
                    {
                        ATOMLOG (_STR("Notify fail\n"));
                        failures++;
                    }
                    else
                    {
                        /* Success */
                    }
                }
            }
        }
    }

    /* Test wakeup of threads on semaphore deletion (thread blocking with timeout) */
    g_result = 0;
    if (atomQueueCreate (&queue1, &queue1_storage[0], sizeof(uint8_t), QUEUE_ENTRIES) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test queue\n"));
        failures++;
    }

    /* Successful queue creation */
    else
    {
        /* Fill up all entries */
        for (i = 0; i < QUEUE_ENTRIES; i++)
        {
            if (atomQueuePut (&queue1, 0, &msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Error filling queue\n"));
                failures++;
            }
        }

        /* Create a test thread that will block because the queue is full */
        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 and filled a queue. We want to see that the other
             * thread is woken up if its queue is deleted. This is indicated
             * through g_result being set.
             */

            /* Wait for the other thread to start blocking on queue1 */
            if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed timer delay\n"));
                failures++;
            }
            else
            {
                /* The other thread will be blocking on queue1 now, delete queue1 */
                if (atomQueueDelete(&queue1) != ATOM_OK)
                {
                    ATOMLOG (_STR("Failed queue1 delete\n"));
                    failures++;
                }
                else
                {
                    /* Queue1 deleted. The thread should now wake up and set g_result. */
                    atomTimerDelay (SYSTEM_TICKS_PER_SEC);
                    if (g_result == 0)
                    {
                        ATOMLOG (_STR("Notify fail\n"));
                        failures++;
                    }
                    else
                    {
                        /* Success */
                    }
                }
            }
        }
    }

    /* 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;
}
示例#25
0
int main ( void )
{
    int8_t status;
	sei();



	SerialInit(MYUBRR);
	InitWatch();
    /**
     * Reuse part of the idle thread's stack for the stack required
     * during this startup function.
     */
    SP = (int)&idle_thread_stack[(IDLE_STACK_SIZE_BYTES/2) - 1];

    /**
     * Note: to protect OS structures and data during initialisation,
     * interrupts must remain disabled until the first thread
     * has been restored. They are reenabled at the very end of
     * the first thread restore, at which point it is safe for a
     * reschedule to take place.
     */

    /**
     * Initialise the OS before creating our threads.
     *
     * Note that we cannot enable stack-checking on the idle thread on
     * this platform because we are already using part of the idle
     * thread's stack now as our startup stack. Prefilling for stack
     * checking would overwrite our current stack.
     *
     * If you are not reusing the idle thread's stack during startup then
     * you are free to enable stack-checking here.
     */
    status = atomOSInit(&idle_thread_stack[0], IDLE_STACK_SIZE_BYTES, FALSE);
    if (status == ATOM_OK)
    {

        /* Enable the system tick timer */
        avrInitSystemTickTimer();

        /* Create the main thread */
        status = atomThreadCreate(&main_tcb,
                     MAIN_THREAD_PRIO, main_thread_func, 0,
                     &main_thread_stack[0],
                     MAIN_STACK_SIZE_BYTES,
                     FALSE);
        if (status == ATOM_OK)
        {
            /**
             * Application threads successfully created. It is
             * now possible to start the OS. Execution will not return
             * from atomOSStart(), which will restore the context of
             * our application thread and start executing it.
             *
             * Note that interrupts are still disabled at this point.
             * They will be enabled as we restore and execute our first
             * thread in archFirstThreadRestore().
             */
            atomOSStart();

        }
    }
    while (1)
	{
		atomTimerDelay (2 * SYSTEM_TICKS_PER_SEC); // wait 2 sec

	}
    /* There was an error starting the OS if we reach here */
    return (0);
}
示例#26
0
/**
 * \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;

}
示例#27
0
/**
 * \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;

}
示例#28
0
/**
 * \b test_start
 *
 * Start mutex test.
 *
 * This tests timeouts on a mutex. We make a thread block with timeout
 * on a mutex, and test that sufficient time has actually passed as
 * was requested by the timeout parameter.
 *
 * The main thread creates a second thread which will immediately take
 * ownership of the mutex. The test checks that the correct timeout
 * occurs when the first thread blocks on the mutex which is already
 * owned (by the second thread).
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    uint32_t start_time, end_time;

    /* Default to zero failures */
    failures = 0;

    /* Create mutex */
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating mutex\n"));
        failures++;
    }
    else
    {
        /* Initialise the shared_data to zero */
        shared_data = 0;

        /* Create second thread */
        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 take ownership
         * of the mutex. We wait a while and check that shared_data has been
         * modified, which proves to us that the thread has taken the mutex.
         */
        atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);
        if (shared_data != 1)
        {
            ATOMLOG (_STR("Shared data unmodified\n"));
            failures++;
        }

        /* Check successful so far */
        if (failures == 0)
        {
            /* Take note of the start time */
            start_time = atomTimeGet();

            /* Block on the mutex with two second timeout */
            if (atomMutexGet (&mutex1, 2 * SYSTEM_TICKS_PER_SEC) != ATOM_TIMEOUT)
            {
                ATOMLOG (_STR("Failed get\n"));
                failures++;
            }

            /* Take note of the end time */
            end_time = atomTimeGet();

            /* Now check that two seconds have passed */
            if ((end_time < (start_time + (2 * SYSTEM_TICKS_PER_SEC)))
                || (end_time > (start_time + (2 * SYSTEM_TICKS_PER_SEC) + 1)))
            {
                ATOMLOG (_STR("Bad time\n"));
                failures++;
            }
        }

        /* Delete mutex, test finished */
        if (atomMutexDelete (&mutex1) != 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;

}
示例#29
0
/**
 * \b test_start
 *
 * Start queue test.
 *
 * This test verifies the queue deletion API, by deleting a queue
 * on which multiple threads are blocking, and checking that all three
 * are woken up with an appropriate error code.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    int i;

    /* Default to zero failures */
    failures = 0;

    /* Initialise pass status for all three threads to FALSE */
    for (i = 0; i < 3; i++) {
        pass_flag[i] = FALSE;
    }

    /* Test wakeup of three threads on queue deletion */
    if (atomQueueCreate (&queue1, &queue1_storage[0], sizeof(queue1_storage[0]), QUEUE_ENTRIES) != ATOM_OK) {
        ATOMLOG (_STR("Error creating Q\n"));
        failures++;
    }

    else {
        /* The queue is empty so all three test threads will block */

        /* Create test thread 1 */
        if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test_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++;
        }

        /* Create test thread 2 */
        else if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO, test_thread_func, 1,
                                  &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++;
        }

        /* Create test thread 3 */
        else if (atomThreadCreate(&tcb[2], TEST_THREAD_PRIO, test_thread_func, 2,
                                  &test_thread_stack[2][TEST_THREAD_STACK_SIZE - 1],
                                  TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread 3\n"));
            failures++;
        }

        /* Test threads now created */
        else {
            /* Wait a while for threads to start blocking on queue1 */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

            /* Delete queue1 now that all three threads should be blocking */
            if (atomQueueDelete (&queue1) != ATOM_OK) {
                ATOMLOG (_STR("Delete fail\n"));
                failures++;
            } else {
                /* Wait a while for all three threads to wake up */
                atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

                /* Check that all three threads have passed */
                if ((pass_flag[0] != TRUE) || (pass_flag[1] != TRUE) || (pass_flag[2] != TRUE)) {
                    ATOMLOG (_STR("Thread fail\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;
}
示例#30
0
/**
 * \b usart_app_init
 *
 * Initialize USART device.
 *
 * @param[in] None
 *
 * @return None
 */
void usart_app_init(void)
{
   static const gpio_map_t USART_GPIO_MAP =
      {
         {ONBOARD_USART_RX_PIN, ONBOARD_USART_RX_FUNCTION},
         {ONBOARD_USART_TX_PIN, ONBOARD_USART_TX_FUNCTION}
      };

   // USART options.
   static const usart_options_t USART_OPTIONS =
      {
         .baudrate     = 115200,
         .charlength   = 8,
         .paritytype   = USART_NO_PARITY,
         .stopbits     = USART_1_STOPBIT,
         .channelmode  = USART_NORMAL_CHMODE
      };
   // Assign GPIO to USART.
   gpio_enable_module(USART_GPIO_MAP,
                      sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));

   // Initialize USART in RS232 mode.
   usart_init_rs232(ONBOARD_USART, &USART_OPTIONS, PBA_HZ);
   
   // Hello world!
   usart_write_line(ONBOARD_USART, "\nHello, this is AT32AP7000 saying hello!\n");   
}

/**
 * \b main_thread_func
 *
 * Entry point for main application thread.
 *
 * This is the first thread that will be executed when the OS is started.
 *
 * @param[in] data Unused (optional thread entry parameter)
 *
 * @return None
 */
static void main_thread_func (uint32_t data)
{
   uint32_t test_status;
   int sleep_ticks;

   /* Initialise UART */
   usart_app_init();

   test_status = test_start();

   /* Check main thread stack usage (if enabled) */
#ifdef ATOM_STACK_CHECKING
   if (test_status == 0)
      {
         uint32_t used_bytes, free_bytes;

         /* Check idle thread stack usage */
         if (atomThreadStackCheck (&main_tcb, &used_bytes, &free_bytes) == ATOM_OK)
            {
               /* Check the thread did not use up to the end of stack */
               if (free_bytes == 0)
                  {
                     test_status++;
                  }
            }
      }
#endif

   /* Flash LED once per second if passed, very quickly if failed */
   sleep_ticks = (test_status == 0) ? SYSTEM_TICKS_PER_SEC : (SYSTEM_TICKS_PER_SEC/8);

   /* Test finished, flash slowly for pass, fast for fail */
   while (1)
      {
         /* Sleep then toggle LED again */
         atomTimerDelay (sleep_ticks);
      }

}