blob: b1056f23b429a1f7b88d21bc80b9beb810382a5c [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* @file
* @brief Use fifo API's in different scenarios
*
* This module tests following three basic scenarios:
*
* Scenario #1
* Test Thread enters items into a fifo, starts the Child Thread
* and waits for a semaphore. Child thread extracts all items from
* the fifo and enters some items back into the fifo. Child Thread
* gives the semaphore for Test Thread to continue. Once the control
* is returned back to Test Thread, it extracts all items from the fifo.
*
* Scenario #2
* Test Thread enters an item into fifo2, starts a Child Thread and
* extract an item from fifo1 once the item is there. The Child Thread
* will extract an item from fifo2 once the item is there and and enter
* an item to fifo1. The flow of control goes from Test Thread to
* Child Thread and so forth.
*
* Scenario #3
* Tests the ISR interfaces. Test thread puts items into fifo2 and gives
* control to the Child thread. Child thread gets items from fifo2 and then
* puts items into fifo1. Child thread gives back control to the Test thread
* and Test thread gets the items from fifo1.
* All the Push and Pop operations happen in ISR Context.
*/
#include <ztest.h>
#include <irq_offload.h>
#define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACKSIZE)
#define LIST_LEN 4
struct fdata_t {
sys_snode_t snode;
u32_t data;
};
static K_FIFO_DEFINE(fifo1);
static K_FIFO_DEFINE(fifo2);
/* Data to put into FIFO */
static struct fdata_t data1[LIST_LEN];
static struct fdata_t data2[LIST_LEN];
static struct fdata_t data_isr[LIST_LEN];
static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
static struct k_thread tdata;
static struct k_sem end_sema;
/*entry of contexts*/
static void tIsr_entry_put(void *p)
{
u32_t i;
/* Put items into fifo */
for (i = 0U; i < LIST_LEN; i++) {
k_fifo_put((struct k_fifo *)p, (void *)&data_isr[i]);
}
zassert_false(k_fifo_is_empty((struct k_fifo *)p), NULL);
}
static void tIsr_entry_get(void *p)
{
void *rx_data;
u32_t i;
/* Get items from fifo */
for (i = 0U; i < LIST_LEN; i++) {
rx_data = k_fifo_get((struct k_fifo *)p, K_NO_WAIT);
zassert_equal(rx_data, (void *)&data_isr[i], NULL);
}
zassert_true(k_fifo_is_empty((struct k_fifo *)p), NULL);
}
static void thread_entry_fn_single(void *p1, void *p2, void *p3)
{
void *rx_data;
u32_t i;
/* Get items from fifo */
for (i = 0U; i < LIST_LEN; i++) {
rx_data = k_fifo_get((struct k_fifo *)p1, K_NO_WAIT);
zassert_equal(rx_data, (void *)&data1[i], NULL);
}
/* Put items into fifo */
for (i = 0U; i < LIST_LEN; i++) {
k_fifo_put((struct k_fifo *)p1, (void *)&data2[i]);
}
/* Give control back to Test thread */
k_sem_give(&end_sema);
}
static void thread_entry_fn_dual(void *p1, void *p2, void *p3)
{
void *rx_data;
u32_t i;
for (i = 0U; i < LIST_LEN; i++) {
/* Get items from fifo2 */
rx_data = k_fifo_get((struct k_fifo *)p2, K_FOREVER);
zassert_equal(rx_data, (void *)&data2[i], NULL);
/* Put items into fifo1 */
k_fifo_put((struct k_fifo *)p1, (void *)&data1[i]);
}
}
static void thread_entry_fn_isr(void *p1, void *p2, void *p3)
{
/* Get items from fifo2 */
irq_offload(tIsr_entry_get, p2);
/* Put items into fifo1 */
irq_offload(tIsr_entry_put, p1);
/* Give control back to Test thread */
k_sem_give(&end_sema);
}
/**
* @addtogroup kernel_fifo_tests
* @{
*/
/**
* @brief Tests single fifo get and put operation in thread context
* @details Test Thread enters items into a fifo, starts the Child Thread
* and waits for a semaphore. Child thread extracts all items from
* the fifo and enters some items back into the fifo. Child Thread
* gives the semaphore for Test Thread to continue. Once the control
* is returned back to Test Thread, it extracts all items from the fifo.
* @see k_fifo_get(), k_fifo_is_empty(), k_fifo_put(), #K_FIFO_DEFINE(x)
*/
static void test_single_fifo_play(void)
{
void *rx_data;
u32_t i;
/* Init kernel objects */
k_sem_init(&end_sema, 0, 1);
/* Put items into fifo */
for (i = 0U; i < LIST_LEN; i++) {
k_fifo_put(&fifo1, (void *)&data1[i]);
}
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
thread_entry_fn_single, &fifo1, NULL, NULL,
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, 0);
/* Let the child thread run */
k_sem_take(&end_sema, K_FOREVER);
/* Get items from fifo */
for (i = 0U; i < LIST_LEN; i++) {
rx_data = k_fifo_get(&fifo1, K_NO_WAIT);
zassert_equal(rx_data, (void *)&data2[i], NULL);
}
/* Clear the spawn thread to avoid side effect */
k_thread_abort(tid);
}
/**
* @brief Tests dual fifo get and put operation in thread context
* @details test Thread enters an item into fifo2, starts a Child Thread and
* extract an item from fifo1 once the item is there. The Child Thread
* will extract an item from fifo2 once the item is there and and enter
* an item to fifo1. The flow of control goes from Test Thread to
* Child Thread and so forth.
* @see k_fifo_get(), k_fifo_is_empty(), k_fifo_put(), #K_FIFO_DEFINE(x)
*/
static void test_dual_fifo_play(void)
{
void *rx_data;
u32_t i;
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
thread_entry_fn_dual, &fifo1, &fifo2, NULL,
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, 0);
for (i = 0U; i < LIST_LEN; i++) {
/* Put item into fifo */
k_fifo_put(&fifo2, (void *)&data2[i]);
/* Get item from fifo */
rx_data = k_fifo_get(&fifo1, K_FOREVER);
zassert_equal(rx_data, (void *)&data1[i], NULL);
}
/* Clear the spawn thread to avoid side effect */
k_thread_abort(tid);
}
/**
* @brief Tests fifo put and get operation in interrupt context
* @details Tests the ISR interfaces. Test thread puts items into fifo2
* and gives control to the Child thread. Child thread gets items from
* fifo2 and then puts items into fifo1. Child thread gives back control
* to the Test thread and Test thread gets the items from fifo1.
* All the Push and Pop operations happen in ISR Context.
* @see k_fifo_get(), k_fifo_is_empty(), k_fifo_put(), #K_FIFO_DEFINE(x)
*/
static void test_isr_fifo_play(void)
{
/* Init kernel objects */
k_sem_init(&end_sema, 0, 1);
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
thread_entry_fn_isr, &fifo1, &fifo2, NULL,
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, 0);
/* Put item into fifo */
irq_offload(tIsr_entry_put, &fifo2);
/* Let the child thread run */
k_sem_take(&end_sema, K_FOREVER);
/* Get item from fifo */
irq_offload(tIsr_entry_get, &fifo1);
/* Clear the spawn thread to avoid side effect */
k_thread_abort(tid);
}
/**
* @}
*/
/*test case main entry*/
void test_main(void)
{
ztest_test_suite(test_fifo_usage,
ztest_unit_test(test_single_fifo_play),
ztest_unit_test(test_dual_fifo_play),
ztest_unit_test(test_isr_fifo_play));
ztest_run_test_suite(test_fifo_usage);
}