| /* |
| * 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 |
| #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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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); |
| } |