irq_offload: API to run a function in IRQ context

Software interrupts or system calls aren't really appropriate for
zephyr, but we have an ongoing need in our test code to run a
function with arguments synchronously in interrupt context.

This patch introduces irq_offload() which allows us to do this without
separate initialization or having to manage fake IRQs in the
interrupt controller.

ARM assembly code contributed by Benjamin Walsh
<benjamin.walsh@windriver.com>

ARC is not yet implemented but will be in a subsequent patch.

irq_test_common.h has been removed and all test cases updated to
use the new API.

Change-Id: I9af99ed31b62bc7eb340e32cf65e3d11354d1ec7
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2015-11-17 14:08:45 -08:00 committed by Anas Nashif
commit bba9510319
44 changed files with 313 additions and 350 deletions

View file

@ -11,5 +11,5 @@ obj-y = atomic.o exc_exit.o irq_init.o \
fatal.o sys_fatal_error_handler.o
obj-$(CONFIG_MICROKERNEL) += task_abort.o
obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
obj-$(CONFIG_CPU_CORTEX_M) += cortex_m/

View file

@ -133,6 +133,14 @@ endmenu
menu "ARM Cortex-M3/M4 options"
depends on CPU_CORTEX_M3_M4
config IRQ_OFFLOAD
bool "Enable IRQ offload"
default n
help
Enable irq_offload() API which allows functions to be synchronously
run in interrupt context. Adds some overhead to context switching.
Mainly useful for test cases.
config SW_ISR_TABLE
bool
prompt "Enable software interrupt handler table"

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2015 Intel corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file Software interrupts utility code - ARM implementation
*/
#include <nanokernel.h>
#include <irq_offload.h>
static irq_offload_routine_t offload_routine;
static void *offload_param;
/* Called by __svc */
void _irq_do_offload(void)
{
offload_routine(offload_param);
}
void irq_offload(irq_offload_routine_t routine, void *parameter)
{
int key;
key = irq_lock();
offload_routine = routine;
offload_param = parameter;
__asm__ volatile ("svc #1");
irq_unlock(key);
}

View file

@ -152,6 +152,33 @@ SECTION_FUNC(TEXT, __svc)
_GDB_STUB_EXC_ENTRY
#if CONFIG_IRQ_OFFLOAD
tst lr, #0x4 /* did we come from thread mode ? */
ite eq /* if zero (equal), came from handler mode */
mrseq r0, MSP /* handler mode, stack frame is on MSP */
mrsne r0, PSP /* thread mode, stack frame is on PSP */
ldr r0, [r0, #24] /* grab address of PC from stack frame */
/* SVC is a two-byte instruction, point to it and read encoding */
ldr r0, [r0, #-2]
/*
* grab service call number: if zero, it's a context switch; if not,
* it's an irq offload
*/
ands r0, #0xff
beq _context_switch
push {lr}
blx _irq_do_offload /* call C routine which executes the offload */
pop {lr}
/* exception return is done in _IntExit(), including _GDB_STUB_EXC_EXIT */
b _IntExit
BRANCH_LABEL(_context_switch);
#endif
/*
* Unlock interrupts:
* - in a SVC call, so protected against context switches

View file

@ -36,10 +36,10 @@
/**
*
* @brief Find out if running in an ISR context
*
*
* The current executing vector is found in the IPSR register. We consider the
* IRQs (exception 16 and up), and the PendSV and SYSTICK exceptions, to be
* interrupts. Taking a fault within an exception is also considered in
* IRQs (exception 16 and up), and the SVC, PendSV, and SYSTICK exceptions,
* to be interrupts. Taking a fault within an exception is also considered in
* interrupt context.
*
* @return 1 if in ISR, 0 if not.
@ -48,8 +48,11 @@ static ALWAYS_INLINE int _IsInIsr(void)
{
uint32_t vector = _IpsrGet();
/* IRQs + PendSV + SYSTICK are interrupts */
return (vector > 13) || (vector && _ScbIsNestedExc());
/*
* IRQs + PendSV (14) + SVC (11) + SYSTICK (15) are interrupts.
* Vectors 12 and 13 are reserved, we'll never be in there
*/
return (vector > 10) || (vector && _ScbIsNestedExc());
}
/**

View file

@ -118,6 +118,14 @@ config PIC_DISABLE
help
This option disables all interrupts on the PIC
config IRQ_OFFLOAD
bool "Enable IRQ offload"
default n
help
Enable irq_offload() API which allows functions to be synchronously
run in interrupt context. Uses one entry in the IDT. Mainly useful
for test cases.
endmenu
menu "Processor Capabilities"

View file

@ -19,6 +19,7 @@ obj-y += gdt.o fatal.o cpuhalt.o \
crt0.o driver_static_irq_stubs.o \
atomic.o cache_s.o cache.o
obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
obj-$(CONFIG_FP_SHARING) += float.o
obj-$(CONFIG_MICROKERNEL) += strtask.o

View file

@ -40,6 +40,7 @@ entering and exiting a C interrupt handler.
GTEXT(_SpuriousIntNoErrCodeHandler)
GTEXT(_SpuriousIntHandler)
GTEXT(_DynIntStubsBegin)
GTEXT(_irq_sw_handler)
/* externs */
@ -512,3 +513,11 @@ stub_num = 0
1: jmp _DynIntStubCommon
.endr
#endif /* ALL_DYN_IRQ_STUBS */
#if CONFIG_IRQ_OFFLOAD
SECTION_FUNC(TEXT, _irq_sw_handler)
call _IntEnt
call _irq_do_offload
jmp _IntExit
#endif

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015 Intel corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file IRQ offload - x86 implementation
*/
#include <nanokernel.h>
#include <irq_offload.h>
#define SW_IRQ_VECTOR (CONFIG_IDT_NUM_VECTORS - 1)
extern void (*_irq_sw_handler)(void);
NANO_CPU_INT_REGISTER(_irq_sw_handler, NANO_SOFT_IRQ, SW_IRQ_VECTOR / 16,
SW_IRQ_VECTOR, 0);
static irq_offload_routine_t offload_routine;
static void *offload_param;
/* Called by asm stub */
void _irq_do_offload(void)
{
offload_routine(offload_param);
}
void irq_offload(irq_offload_routine_t routine, void *parameter)
{
int key;
/*
* Lock interrupts here to prevent any concurrency issues with
* the two globals
*/
key = irq_lock();
offload_routine = routine;
offload_param = parameter;
__asm__ volatile("int %[vector]" : : [vector] "i" (SW_IRQ_VECTOR));
irq_unlock(key);
}

39
include/irq_offload.h Normal file
View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2015 Intel corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file IRQ Offload interface
*/
#ifndef _IRQ_OFFLOAD_H_
#define _IRQ_OFFLOAD_H_
typedef void (*irq_offload_routine_t)(void *parameter);
/**
* @brief Run a function in interrupt context
*
* This function synchronously runs the provided function in interrupt
* context, passing in the supplied parameter. Useful for test code
* which needs to show that kernel objects work correctly in interrupt
* context.
*
* @param routine The function to run
* @param parameter Argument to pass to the function when it is run as an
* interrupt
*/
void irq_offload(irq_offload_routine_t routine, void *parameter);
#endif /* _SW_IRQ_H_ */

View file

@ -1,139 +0,0 @@
/* irq-test-common.h - IRQ utilities for tests */
/*
* Copyright (c) 2014 Wind River Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
DESCRIPTION
Interrupt stuff, abstracted across CPU architectures.
*/
#ifndef _IRQ_TEST_COMMON__H_
#define _IRQ_TEST_COMMON__H_
#if defined(CONFIG_X86)
#define IRQ_PRIORITY 3
#elif defined(CONFIG_ARM)
#if defined(CONFIG_CPU_CORTEX_M)
#define IRQ_PRIORITY _EXC_PRIO(3)
#endif /* CONFIG_CPU_CORTEX_M */
#endif
/*
* NUM_SW_IRQS must be defined before this file is included, and it
* currently only supports 1 or 2 as valid values.
*/
#if !defined(NUM_SW_IRQS)
#error NUM_SW_IRQS must be defined before including irq-test-common.h
#elif NUM_SW_IRQS < 1 || NUM_SW_IRQS > 2
#error NUM_SW_IRQS only supports 1 or 2 IRQs
#endif
typedef void (*vvfn)(void); /* void-void function pointer */
typedef void (*vvpfn)(void *); /* void-void_pointer function pointer */
#if defined(CONFIG_X86)
/*
* Opcode for generating a software interrupt. The ISR associated with each
* of these software interrupts will call either nano_isr_lifo_put() or
* nano_isr_lifo_get(). The imm8 data in the opcode sequence will need to be
* filled in after calling irq_connect().
*/
#include <drivers/loapic.h>
static uint8_t sw_irq_vectors[NUM_SW_IRQS];
static inline void sw_isr_trigger_0(void)
{
loapic_int_vec_trigger(sw_irq_vectors[0]);
}
#if NUM_SW_IRQS >= 2
static inline void sw_isr_trigger_1(void)
{
loapic_int_vec_trigger(sw_irq_vectors[1]);
}
#endif /* NUM_SW_IRQS >= 2 */
#elif defined(CONFIG_ARM)
#if defined(CONFIG_CPU_CORTEX_M)
#include <nanokernel.h>
static inline void sw_isr_trigger_0(void)
{
_NvicSwInterruptTrigger(0);
}
#if NUM_SW_IRQS >= 2
static inline void sw_isr_trigger_1(void)
{
_NvicSwInterruptTrigger(1);
}
#endif /* NUM_SW_IRQS >= 2 */
#endif /* CONFIG_CPU_CORTEX_M */
#endif
struct isrInitInfo {
vvpfn isr[2];
void *arg[2];
};
/**
*
* @brief Init interrupts
*
*/
static int initIRQ(struct isrInitInfo *i)
{
#if defined(CONFIG_X86)
int vector; /* vector to which interrupt is connected */
if (i->isr[0]) {
vector = irq_connect(NANO_SOFT_IRQ, IRQ_PRIORITY, i->isr[0],
i->arg[0], 0);
if (-1 == vector) {
return -1;
}
sw_irq_vectors[0] = vector;
}
#if NUM_SW_IRQS >= 2
if (i->isr[1]) {
vector = irq_connect(NANO_SOFT_IRQ, IRQ_PRIORITY, i->isr[1],
i->arg[1], 0);
if (-1 == vector) {
return -1;
}
sw_irq_vectors[1] = vector;
}
#endif /* NUM_SW_IRQS >= 2 */
#elif defined(CONFIG_ARM)
#if defined(CONFIG_CPU_CORTEX_M)
if (i->isr[0]) {
(void) irq_connect(0, IRQ_PRIORITY, i->isr[0], i->arg[0], 0);
irq_enable(0);
}
if (i->isr[1]) {
(void) irq_connect(1, IRQ_PRIORITY, i->isr[1], i->arg[1], 0);
irq_enable(1);
}
#endif /* CONFIG_CPU_CORTEX_M */
#endif /* CONFIG_X86 */
return 0;
}
#endif /* _IRQ_TEST_COMMON__H_ */

View file

@ -1 +1 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -2,4 +2,4 @@
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -28,11 +28,8 @@ This modules tests the following event APIs:
#include <zephyr.h>
#include <arch/cpu.h>
#include <toolchain.h>
#include <irq_offload.h>
/* test uses 1 software IRQs */
#define NUM_SW_IRQS 1
#include <irq_test_common.h>
#include <util_test_common.h>
typedef struct {
@ -42,8 +39,6 @@ typedef struct {
static int evidence = 0;
static ISR_INFO isrInfo;
static void (*_trigger_isrEventSignal)(void) = (vvfn)sw_isr_trigger_0;
static int handlerRetVal = 0;
extern void testFiberInit(void);
@ -65,6 +60,12 @@ void isr_event_signal_handler(void *data)
isr_event_send(pInfo->event);
}
static void _trigger_isrEventSignal(void)
{
irq_offload(isr_event_signal_handler, &isrInfo);
}
/**
*
* @brief Release the test fiber
@ -86,12 +87,6 @@ void releaseTestFiber(void)
void microObjectsInit(void)
{
struct isrInitInfo i = {
{isr_event_signal_handler, NULL},
{&isrInfo, NULL},
};
(void) initIRQ(&i);
testFiberInit();
TC_PRINT("Microkernel objects initialized\n");

View file

@ -1 +1 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -2,4 +2,4 @@
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -29,12 +29,9 @@ then announces the result of the test.
*/
#include <zephyr.h>
#include <irq_offload.h>
#include <tc_util.h>
/* test uses 1 software IRQs */
#define NUM_SW_IRQS 1
#include <irq_test_common.h>
#include <util_test_common.h>
extern void testFiberInit(void);
@ -82,7 +79,24 @@ ksem_t semList[] = {
ENDLIST
};
static vvfn _trigger_isrSemaSignal = (vvfn) sw_isr_trigger_0;
/**
*
* @brief ISR that gives specified semaphore
*
* @param isrData pointer to semaphore to be given
*
* @return N/A
*/
static void testIsrHandler(void *isrData)
{
isr_sem_give(*(ksem_t *)isrData);
}
static void _trigger_isrSemaSignal(void)
{
irq_offload(testIsrHandler, &testIsrInfo);
}
/**
*
@ -152,19 +166,6 @@ void LowPriTaskEntry(void)
task_sem_give(resultSems[LowPriTask()]);
}
/**
*
* @brief ISR that gives specified semaphore
*
* @param isrData pointer to semaphore to be given
*
* @return N/A
*/
static void testIsrHandler(void *isrData)
{
isr_sem_give(*(ksem_t *)isrData);
}
/**
*
@ -193,26 +194,6 @@ void releaseTestFiber(void)
nano_task_sem_give(&fiberSem);
}
/**
*
* @brief Initialize interrupt-related code
*
* Binds an ISR to the interrupt vector used to give semaphores from interrupt
* level.
*
* @return N/A
*/
static void testInterruptsInit(void)
{
struct isrInitInfo i = {
{ testIsrHandler, NULL},
{ &testIsrInfo, NULL},
};
(void) initIRQ(&i);
}
/**
*
* @brief Entry point for MonitorTask
@ -228,7 +209,6 @@ void MonitorTaskEntry(void)
ksem_t result;
int tasksDone;
testInterruptsInit();
testFiberInit();
PRINT_DATA("Starting semaphore tests\n");

View file

@ -1 +1 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -2,4 +2,4 @@
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -1,2 +1,3 @@
CONFIG_NUM_TASK_PRIORITIES=32
CONFIG_NUM_IRQS=2
CONFIG_NUM_IRQS=1
CONFIG_IRQ_OFFLOAD=y

View file

@ -4,4 +4,4 @@ CONFIG_NUM_TASK_PRIORITIES=32
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -27,11 +27,8 @@ This module tests the following task APIs:
#include <tc_util.h>
#include <zephyr.h>
#include <arch/cpu.h>
#include <irq_offload.h>
/* test uses 1 software IRQs */
#define NUM_SW_IRQS 1
#include <irq_test_common.h>
#include <util_test_common.h>
#define RT_PRIO 10 /* RegressionTask prio - must match prj.mdef */
@ -47,8 +44,6 @@ typedef struct {
int data;
} ISR_INFO;
static vvfn _trigger_isrTaskCommand = (vvfn)sw_isr_trigger_0;
static ISR_INFO isrInfo;
static int tcRC = TC_PASS; /* test case return code */
@ -101,7 +96,7 @@ void isr_task_command_handler(void *data)
int isrAPIsTest(int taskId, int taskPrio)
{
isrInfo.cmd = CMD_TASKID;
_trigger_isrTaskCommand();
irq_offload(isr_task_command_handler, &isrInfo);
if (isrInfo.data != taskId) {
TC_ERROR("isr_task_id_get() returned %d, not %d\n",
isrInfo.data, taskId);
@ -109,7 +104,7 @@ int isrAPIsTest(int taskId, int taskPrio)
}
isrInfo.cmd = CMD_PRIORITY;
_trigger_isrTaskCommand();
irq_offload(isr_task_command_handler, &isrInfo);
if (isrInfo.data != taskPrio) {
TC_ERROR("isr_task_priority_get() returned %d, not %d\n",
isrInfo.data, taskPrio);
@ -147,25 +142,6 @@ int taskMacrosTest(int taskId, int taskPrio)
return TC_PASS;
}
/**
*
* @brief Initialize objects used in this microkernel test suite
*
* @return N/A
*/
void microObjectsInit(void)
{
struct isrInitInfo i = {
{ isr_task_command_handler, NULL },
{ &isrInfo, NULL },
};
(void) initIRQ(&i);
TC_PRINT("Microkernel objects initialized\n");
}
/**
*
* @brief Helper task portion to test setting the priority
@ -499,7 +475,6 @@ void RegressionTask(void)
PRINT_LINE;
microObjectsInit();
task_start(HT_TASKID);
TC_PRINT("Testing isr_task_id_get() and isr_task_priority_get()\n");

View file

@ -1,2 +1,2 @@
CONFIG_NUM_TASK_PRIORITIES=32
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -4,4 +4,4 @@ CONFIG_NUM_TASK_PRIORITIES=32
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -1,3 +1,3 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y
CONFIG_ZERO_LATENCY_IRQS=y
CONFIG_NANO_TIMEOUTS=y

View file

@ -3,5 +3,5 @@
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NANO_TIMEOUTS=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y
CONFIG_NUM_DYNAMIC_EXC_NOERR_STUBS=1

View file

@ -29,11 +29,8 @@ This module tests the following CPU and thread related routines:
#include <tc_util.h>
#include <nano_private.h>
#include <arch/cpu.h>
#include <irq_offload.h>
/* test uses 1 software IRQs */
#define NUM_SW_IRQS 1
#include <irq_test_common.h>
#include <util_test_common.h>
/*
@ -99,8 +96,6 @@ static int fiberEvidence = 0;
static ISR_INFO isrInfo;
static void (*_trigger_isrHandler)(void) = (vvfn)sw_isr_trigger_0;
/**
*
* @brief Handler to perform various actions from within an ISR context
@ -129,6 +124,11 @@ void isr_handler(void *data)
break;
}
}
static void _trigger_isrHandler(void)
{
irq_offload(isr_handler, NULL);
}
/* Cortex-M3/M4 does not implement connecting non-IRQ exception handlers */
#if !defined(CONFIG_CPU_CORTEX_M3_M4)
@ -173,12 +173,7 @@ int initNanoObjects(void)
nanoCpuExcConnect(IV_DIVIDE_ERROR, exc_divide_error_handler);
#endif
struct isrInitInfo i = {
{isr_handler, NULL},
{&isrInfo, NULL},
};
return initIRQ(&i) < 0 ? TC_FAIL : TC_PASS;
return TC_PASS;
}
/**

View file

@ -1,4 +1,4 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y
CONFIG_NANO_TIMEOUTS=y
CONFIG_ASSERT=y
CONFIG_ASSERT_LEVEL=2

View file

@ -5,4 +5,4 @@ CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NANO_TIMEOUTS=y
CONFIG_ASSERT=y
CONFIG_ASSERT_LEVEL=2
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -55,11 +55,8 @@ Scenario #4:
#include <tc_util.h>
#include <misc/__assert.h>
#include <misc/util.h>
#include <irq_offload.h>
/* test uses 2 software IRQs */
#define NUM_SW_IRQS 2
#include <irq_test_common.h>
#include <util_test_common.h>
#ifndef FIBER_STACKSIZE
@ -120,9 +117,6 @@ int retCode = TC_PASS;
static ISR_FIFO_INFO isrFifoInfo = {&nanoFifoObj, NULL};
static void (*_trigger_nano_isr_fifo_put)(void) = (vvfn)sw_isr_trigger_0;
static void (*_trigger_nano_isr_fifo_get)(void) = (vvfn)sw_isr_trigger_1;
void fiber1(void);
void fiber2(void);
void fiber3(void);
@ -151,6 +145,12 @@ void isr_fifo_put(void *parameter)
nano_isr_fifo_put(pInfo->fifo_ptr, pInfo->data);
}
static void _trigger_nano_isr_fifo_put(void)
{
irq_offload(isr_fifo_put, &isrFifoInfo);
}
/**
*
* @brief Get an item from a FIFO
@ -170,6 +170,10 @@ void isr_fifo_get(void *parameter)
pInfo->data = nano_isr_fifo_get(pInfo->fifo_ptr);
}
static void _trigger_nano_isr_fifo_get(void)
{
irq_offload(isr_fifo_get, &isrFifoInfo);
}
/**
*
@ -557,13 +561,6 @@ void testTaskFifoGetW(void)
void initNanoObjects(void)
{
struct isrInitInfo i = {
{isr_fifo_put, isr_fifo_get},
{&isrFifoInfo, &isrFifoInfo},
};
(void)initIRQ(&i);
nano_fifo_init(&nanoFifoObj);
nano_fifo_init(&nanoFifoObj2);

View file

@ -3,3 +3,6 @@ CONFIG_CONSOLE=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_IPI_CONSOLE_RECEIVER=y
CONFIG_IPI_CONSOLE_SENDER=y
CONFIG_IRQ_OFFLOAD=y
CONFIG_DEBUG=y

View file

@ -1,5 +1,6 @@
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_CONSOLE=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_IPI_CONSOLE_RECEIVER=y
CONFIG_IPI_CONSOLE_SENDER=y
CONFIG_IRQ_OFFLOAD=y

View file

@ -22,13 +22,10 @@
#include <device.h>
#include <init.h>
#include <misc/printk.h>
#include <irq_offload.h>
#define NUM_SW_IRQS 2
#include <irq_test_common.h>
#include "ipi_dummy.h"
static void (*trigger_dummy_isr)(void) = (vvfn)sw_isr_trigger_0;
/* Implemented as a software interrupt so that callbacks are executed
* in the expected context */
@ -78,7 +75,7 @@ static int ipi_dummy_send(struct device *d, int wait, uint32_t id,
driver_data->regs.id = id;
driver_data->regs.busy = 1;
trigger_dummy_isr();
irq_offload(ipi_dummy_isr, d);
if (wait) {
while(driver_data->regs.busy) {
@ -100,10 +97,11 @@ static void ipi_dummy_register_callback(struct device *d, ipi_callback_t cb,
static int ipi_dummy_set_enabled(struct device *d, int enable)
{
struct ipi_dummy_driver_data *driver_data = d->driver_data;
driver_data->regs.enabled = enable;
if (enable) {
/* In case there are pending messages */
trigger_dummy_isr();
irq_offload(ipi_dummy_isr, d);
}
return 0;
}
@ -131,34 +129,11 @@ struct ipi_driver_api ipi_dummy_api = {
int ipi_dummy_init(struct device *d)
{
struct isrInitInfo iinfo;
struct ipi_dummy_config_info *config_info;
int irq, i;
struct ipi_dummy_driver_data *driver_data;
config_info = (struct ipi_dummy_config_info *)d->config->config_info;
driver_data = d->driver_data;
d->driver_api = &ipi_dummy_api;
irq = config_info->sw_irq;
if (irq >= NUM_SW_IRQS) {
printk("ipi_dummy_init: invalid sw irq %d\n", irq);
return DEV_INVALID_CONF;
}
for (i = 0; i < NUM_SW_IRQS; ++i) {
if (i == irq) {
iinfo.isr[i] = ipi_dummy_isr;
iinfo.arg[i] = d;
} else {
iinfo.isr[i] = NULL;
iinfo.arg[i] = NULL;
}
}
if (initIRQ(&iinfo)) {
printk("ipi_dummy_init: couldn't install sw irq handler\n");
return DEV_FAIL;
}
return DEV_OK;
}

View file

@ -38,10 +38,6 @@ struct ipi_dummy_driver_data {
volatile struct ipi_dummy_regs regs;
};
struct ipi_dummy_config_info {
int sw_irq;
};
int ipi_dummy_init(struct device *d);
#endif

View file

@ -39,12 +39,8 @@
#define INIT_PRIO_IPI_SEND 50
/* Set up the dummy IPI driver */
struct ipi_dummy_config_info ipi_dummy0_config_info = {
.sw_irq = 0
};
struct ipi_dummy_driver_data ipi_dummy0_driver_data;
DECLARE_DEVICE_INIT_CONFIG(ipi_dummy0, "ipi_dummy0", ipi_dummy_init,
&ipi_dummy0_config_info);
DECLARE_DEVICE_INIT_CONFIG(ipi_dummy0, "ipi_dummy0", ipi_dummy_init, NULL);
SYS_DEFINE_DEVICE(ipi_dummy0, &ipi_dummy0_driver_data, SECONDARY,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

View file

@ -1,4 +1,4 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y
CONFIG_NANO_TIMEOUTS=y
CONFIG_ASSERT=y
CONFIG_ASSERT_LEVEL=2

View file

@ -5,4 +5,4 @@ CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NANO_TIMEOUTS=y
CONFIG_ASSERT=y
CONFIG_ASSERT_LEVEL=2
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -46,11 +46,11 @@ These scenarios will be tested using a combinations of tasks, fibers and ISRs.
#include <tc_util.h>
#include <misc/util.h>
#include <misc/__assert.h>
#include <irq_offload.h>
/* test uses 2 software IRQs */
#define NUM_SW_IRQS 2
#include <irq_test_common.h>
#include <util_test_common.h>
#ifndef FIBER_STACKSIZE
@ -87,9 +87,6 @@ static volatile int fiberDetectedFailure = 0; /* non-zero on failure */
static char __stack fiberStack[FIBER_STACKSIZE];
static void (*_trigger_nano_isr_lifo_put)(void) = (vvfn)sw_isr_trigger_0;
static void (*_trigger_nano_isr_lifo_get)(void) = (vvfn)sw_isr_trigger_1;
static struct nano_lifo multi_waiters;
static struct nano_sem reply_multi_waiters;
@ -112,6 +109,12 @@ void isr_lifo_put(void *data)
nano_isr_lifo_put(pInfo->lifo_ptr, pInfo->data);
}
static void _trigger_nano_isr_lifo_put(void)
{
irq_offload(isr_lifo_put, &isrLifoInfo);
}
/**
*
* @brief Get an item from a LIFO
@ -131,6 +134,12 @@ void isr_lifo_get(void *data)
pInfo->data = nano_isr_lifo_get(pInfo->lifo_ptr);
}
static void _trigger_nano_isr_lifo_get(void)
{
irq_offload(isr_lifo_get, &isrLifoInfo);
}
/**
*
* @brief Fiber portion of test that waits on a LIFO
@ -445,13 +454,6 @@ int taskLifoNonWaitTest(void)
void initNanoObjects(void)
{
struct isrInitInfo i = {
{isr_lifo_put, isr_lifo_get},
{&isrLifoInfo, &isrLifoInfo},
};
(void)initIRQ(&i);
nano_lifo_init(&test_lifo); /* Initialize the LIFO */
nano_sem_init(&taskWaitSem); /* Initialize the task waiting semaphore */
nano_sem_init(&fiberWaitSem); /* Initialize the fiber waiting semaphore */

View file

@ -1,2 +1,2 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y
CONFIG_NANO_TIMEOUTS=y

View file

@ -3,4 +3,4 @@
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NANO_TIMEOUTS=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -43,11 +43,8 @@ Scenario #4:
#include <tc_util.h>
#include <arch/cpu.h>
#include <misc/util.h>
#include <irq_offload.h>
/* test uses 2 software IRQs */
#define NUM_SW_IRQS 2
#include <irq_test_common.h>
#include <util_test_common.h>
#ifndef FIBER_STACKSIZE
@ -77,9 +74,6 @@ static void *timerData[1];
static char __stack fiberStack[FIBER_STACKSIZE];
static void (*_trigger_nano_isr_sem_give)(void) = (vvfn)sw_isr_trigger_0;
static void (*_trigger_nano_isr_sem_take)(void) = (vvfn)sw_isr_trigger_1;
static struct nano_sem multi_waiters;
static struct nano_sem reply_multi_waiters;
@ -102,6 +96,11 @@ void isr_sem_take(void *data)
pInfo->data = nano_isr_sem_take(pInfo->sem);
}
static void _trigger_nano_isr_sem_take(void)
{
irq_offload(isr_sem_take, &isrSemInfo);
}
/**
*
* @brief Give a semaphore
@ -122,6 +121,11 @@ void isr_sem_give(void *data)
pInfo->data = 1; /* Indicate semaphore has been given */
}
static void _trigger_nano_isr_sem_give(void)
{
irq_offload(isr_sem_give, &isrSemInfo);
}
/**
*
* @brief Give and take the semaphore in a fiber without blocking
@ -253,13 +257,6 @@ static void fiberEntry(int arg1, int arg2)
void initNanoObjects(void)
{
struct isrInitInfo i = {
{isr_sem_give, isr_sem_take},
{&isrSemInfo, &isrSemInfo},
};
(void)initIRQ(&i);
nano_sem_init(&testSem);
nano_sem_init(&multi_waiters);
nano_sem_init(&reply_multi_waiters);

View file

@ -1 +1 @@
CONFIG_NUM_IRQS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -2,4 +2,4 @@
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NUM_DYNAMIC_STUBS=2
CONFIG_IRQ_OFFLOAD=y

View file

@ -48,11 +48,8 @@ these are run in ISR context.
#include <tc_util.h>
#include <arch/cpu.h>
#include <irq_offload.h>
/* test uses 2 software IRQs */
#define NUM_SW_IRQS 2
#include <irq_test_common.h>
#include <util_test_common.h>
#define STACKSIZE 2048
@ -96,9 +93,6 @@ int retCode = TC_PASS;
static ISR_STACK_INFO isrStackInfo = {&nanoStackObj, 0};
static void (*_trigger_nano_isr_stack_push)(void) = (vvfn)sw_isr_trigger_0;
static void (*_trigger_nano_isr_stack_pop)(void) = (vvfn)sw_isr_trigger_1;
void initData(void);
void fiber1(void);
void fiber2(void);
@ -149,6 +143,11 @@ void isr_stack_push(void *parameter)
} /* isr_stack_push */
static void _trigger_nano_isr_stack_push(void)
{
irq_offload(isr_stack_push, &isrStackInfo);
}
/**
*
* @brief Get an item from a STACK
@ -173,6 +172,10 @@ void isr_stack_pop(void *parameter)
} /* isr_stack_pop */
static void _trigger_nano_isr_stack_pop(void)
{
irq_offload(isr_stack_pop, &isrStackInfo);
}
/**
*
@ -468,13 +471,6 @@ void fiber3(void)
void initNanoObjects(void)
{
struct isrInitInfo i = {
{isr_stack_push, isr_stack_pop},
{&isrStackInfo, &isrStackInfo},
};
(void)initIRQ(&i);
nano_stack_init(&nanoStackObj, stack1);
nano_stack_init(&nanoStackObj2, stack2);
nano_sem_init(&nanoSemObj);