blob: 2c78a3c96dc02c5ff0a3aa941399bdfbe3f767c6 [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 <zephyr/ztest.h>
#include <zephyr/irq_offload.h>
#define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
#define LIST_LEN 4
struct fdata_t {
sys_snode_t snode;
uint32_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(const void *p)
{
uint32_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));
}
static void tIsr_entry_get(const void *p)
{
void *rx_data;
uint32_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]);
}
zassert_true(k_fifo_is_empty((struct k_fifo *)p));
}
static void thread_entry_fn_single(void *p1, void *p2, void *p3)
{
void *rx_data;
uint32_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]);
}
/* 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;
uint32_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]);
/* 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, (const void *)p2);
/* Put items into fifo1 */
irq_offload(tIsr_entry_put, (const void *)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)
*/
ZTEST(fifo_usage, test_single_fifo_play)
{
void *rx_data;
uint32_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, K_NO_WAIT);
/* 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]);
}
/* 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)
*/
ZTEST(fifo_usage, test_dual_fifo_play)
{
void *rx_data;
uint32_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, K_NO_WAIT);
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]);
}
/* 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)
*/
ZTEST(fifo_usage, test_isr_fifo_play)
{
/* 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, K_NO_WAIT);
/* Put item into fifo */
irq_offload(tIsr_entry_put, (const void *)&fifo2);
/* Let the child thread run */
k_sem_take(&end_sema, K_FOREVER);
/* Get item from fifo */
irq_offload(tIsr_entry_get, (const void *)&fifo1);
/* Clear the spawn thread to avoid side effect */
k_thread_abort(tid);
}
/**
* @}
*/
ZTEST_SUITE(fifo_usage, NULL, NULL,
ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);