More virtual IRQs code.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15621 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
faef5bdb31
commit
57f0dcf26d
|
@ -32,6 +32,8 @@
|
||||||
#include "vfs.h"
|
#include "vfs.h"
|
||||||
#include "errcodes.h"
|
#include "errcodes.h"
|
||||||
|
|
||||||
|
#include "sbhdr.h"
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Module constants. */
|
/* Module constants. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -154,6 +156,11 @@
|
||||||
/* Module data structures and types. */
|
/* Module data structures and types. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of a mask of Virtual IRQs.
|
||||||
|
*/
|
||||||
|
typedef uint32_t sb_vrqmask_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of a sandbox manager global structure.
|
* @brief Type of a sandbox manager global structure.
|
||||||
*/
|
*/
|
||||||
|
@ -244,6 +251,10 @@ typedef struct {
|
||||||
* @brief Thread running in the sandbox.
|
* @brief Thread running in the sandbox.
|
||||||
*/
|
*/
|
||||||
thread_t *tp;
|
thread_t *tp;
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the image header.
|
||||||
|
*/
|
||||||
|
const sb_header_t *sbhp;
|
||||||
#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
|
#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Thread sending a message to the sandbox.
|
* @brief Thread sending a message to the sandbox.
|
||||||
|
@ -256,6 +267,20 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
event_source_t es;
|
event_source_t es;
|
||||||
#endif
|
#endif
|
||||||
|
#if (SB_CFG_ENABLE_VRQ == TRUE) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Global virtual IRQ status register.
|
||||||
|
*/
|
||||||
|
uint32_t vrq_isr;
|
||||||
|
/**
|
||||||
|
* @brief Mask of enabled virtual IRQ flags.
|
||||||
|
*/
|
||||||
|
sb_vrqmask_t vrq_enmask;
|
||||||
|
/**
|
||||||
|
* @brief Mask of pending virtual IRQ flags.
|
||||||
|
*/
|
||||||
|
sb_vrqmask_t vrq_wtmask;
|
||||||
|
#endif
|
||||||
#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__)
|
#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief VFS bindings for Posix API.
|
* @brief VFS bindings for Posix API.
|
||||||
|
@ -289,7 +314,6 @@ extern "C" {
|
||||||
#include "sbelf.h"
|
#include "sbelf.h"
|
||||||
#include "sbposix.h"
|
#include "sbposix.h"
|
||||||
#include "sbapi.h"
|
#include "sbapi.h"
|
||||||
#include "sbhdr.h"
|
|
||||||
#include "sbhost.h"
|
#include "sbhost.h"
|
||||||
|
|
||||||
#endif /* SBHOST_H */
|
#endif /* SBHOST_H */
|
||||||
|
|
|
@ -71,6 +71,18 @@ static void sb_api_loadelf(struct port_extctx *ectxp);
|
||||||
#define SB_SVC12_HANDLER sb_api_loadelf
|
#define SB_SVC12_HANDLER sb_api_loadelf
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Standard API handlers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#if (SB_CFG_ENABLE_VRQ == TRUE) || defined(__DOXYGEN__)
|
||||||
|
#define SB_SVC252_HANDLER sb_vrq_disable
|
||||||
|
#define SB_SVC253_HANDLER sb_vrq_enable
|
||||||
|
#define SB_SVC254_HANDLER sb_vrq_getisr
|
||||||
|
#define SB_SVC255_HANDLER sb_vrq_return
|
||||||
|
#endif
|
||||||
|
/** @} */
|
||||||
|
|
||||||
#define __SVC(x) asm volatile ("svc " #x)
|
#define __SVC(x) asm volatile ("svc " #x)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -958,7 +970,6 @@ static thread_t *sb_msg_wait_timeout_s(sysinterval_t timeout) {
|
||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void sb_cleanup(void) {
|
static void sb_cleanup(void) {
|
||||||
#if SB_CFG_ENABLE_VFS == TRUE
|
#if SB_CFG_ENABLE_VFS == TRUE
|
||||||
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
|
@ -60,7 +60,7 @@ typedef void (*port_syscall_t)(struct port_extctx *ectx);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
void __sb_abort(msg_t msg);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "sb.h"
|
#include "sb.h"
|
||||||
|
|
||||||
|
@ -194,14 +196,8 @@ size_t sb_check_strings_array(sb_class_t *sbp, const char *pp[], size_t max) {
|
||||||
*/
|
*/
|
||||||
void sbObjectInit(sb_class_t *sbp, const sb_config_t *config) {
|
void sbObjectInit(sb_class_t *sbp, const sb_config_t *config) {
|
||||||
|
|
||||||
|
memset((void *)sbp, 0, sizeof (sb_class_t));
|
||||||
sbp->config = config;
|
sbp->config = config;
|
||||||
sbp->tp = NULL;
|
|
||||||
#if CH_CFG_USE_MESSAGES == TRUE
|
|
||||||
sbp->msg_tp = NULL;
|
|
||||||
#endif
|
|
||||||
#if CH_CFG_USE_EVENTS == TRUE
|
|
||||||
chEvtObjectInit(&sbp->es);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,29 +217,28 @@ thread_t *sbStartThread(sb_class_t *sbp, const char *name,
|
||||||
void *wsp, size_t size, tprio_t prio,
|
void *wsp, size_t size, tprio_t prio,
|
||||||
const char *argv[], const char *envp[]) {
|
const char *argv[], const char *envp[]) {
|
||||||
thread_t *utp;
|
thread_t *utp;
|
||||||
const sb_header_t *sbhp;
|
|
||||||
const sb_config_t *config = sbp->config;
|
const sb_config_t *config = sbp->config;
|
||||||
void *usp, *uargv, *uenvp;
|
void *usp, *uargv, *uenvp;
|
||||||
size_t envsize, argsize, parsize;
|
size_t envsize, argsize, parsize;
|
||||||
int uargc, uenvc;
|
int uargc, uenvc;
|
||||||
|
|
||||||
/* Header location.*/
|
/* Header location.*/
|
||||||
sbhp = (const sb_header_t *)(void *)config->regions[config->code_region].area.base;
|
sbp->sbhp = (const sb_header_t *)(void *)config->regions[config->code_region].area.base;
|
||||||
|
|
||||||
/* Checking header magic numbers.*/
|
/* Checking header magic numbers.*/
|
||||||
if ((sbhp->hdr_magic1 != SB_HDR_MAGIC1) ||
|
if ((sbp->sbhp->hdr_magic1 != SB_HDR_MAGIC1) ||
|
||||||
(sbhp->hdr_magic2 != SB_HDR_MAGIC2)) {
|
(sbp->sbhp->hdr_magic2 != SB_HDR_MAGIC2)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking header size and alignment.*/
|
/* Checking header size and alignment.*/
|
||||||
if (sbhp->hdr_size != sizeof (sb_header_t)) {
|
if (sbp->sbhp->hdr_size != sizeof (sb_header_t)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking header entry point.*/
|
/* Checking header entry point.*/
|
||||||
if (!chMemIsSpaceWithinX(&config->regions[config->code_region].area,
|
if (!chMemIsSpaceWithinX(&config->regions[config->code_region].area,
|
||||||
(const void *)sbhp->hdr_entry,
|
(const void *)sbp->sbhp->hdr_entry,
|
||||||
(size_t)2)) {
|
(size_t)2)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -290,7 +285,7 @@ thread_t *sbStartThread(sb_class_t *sbp, const char *name,
|
||||||
.wbase = (stkalign_t *)wsp,
|
.wbase = (stkalign_t *)wsp,
|
||||||
.wend = (stkalign_t *)wsp + (size / sizeof (stkalign_t)),
|
.wend = (stkalign_t *)wsp + (size / sizeof (stkalign_t)),
|
||||||
.prio = prio,
|
.prio = prio,
|
||||||
.u_pc = sbhp->hdr_entry,
|
.u_pc = sbp->sbhp->hdr_entry,
|
||||||
.u_psp = (uint32_t)usp,
|
.u_psp = (uint32_t)usp,
|
||||||
.arg = (void *)sbp
|
.arg = (void *)sbp
|
||||||
};
|
};
|
||||||
|
@ -303,7 +298,7 @@ thread_t *sbStartThread(sb_class_t *sbp, const char *name,
|
||||||
utp = chThdCreateUnprivileged(&utd);
|
utp = chThdCreateUnprivileged(&utd);
|
||||||
|
|
||||||
/* For messages exchange.*/
|
/* For messages exchange.*/
|
||||||
sbp->tp = utp;
|
sbp->tp = utp;
|
||||||
|
|
||||||
return utp;
|
return utp;
|
||||||
}
|
}
|
||||||
|
@ -345,7 +340,6 @@ msg_t sbExec(sb_class_t *sbp, const char *pathname,
|
||||||
const char *argv[], const char *envp[]) {
|
const char *argv[], const char *envp[]) {
|
||||||
const sb_config_t *config = sbp->config;
|
const sb_config_t *config = sbp->config;
|
||||||
memory_area_t ma = config->regions[0].area;
|
memory_area_t ma = config->regions[0].area;
|
||||||
const sb_header_t *sbhp;
|
|
||||||
msg_t ret;
|
msg_t ret;
|
||||||
void *usp, *uargv, *uenvp;
|
void *usp, *uargv, *uenvp;
|
||||||
size_t envsize, argsize, parsize;
|
size_t envsize, argsize, parsize;
|
||||||
|
@ -396,21 +390,21 @@ msg_t sbExec(sb_class_t *sbp, const char *pathname,
|
||||||
CH_RETURN_ON_ERROR(ret);
|
CH_RETURN_ON_ERROR(ret);
|
||||||
|
|
||||||
/* Header location.*/
|
/* Header location.*/
|
||||||
sbhp = (const sb_header_t *)(void *)ma.base;
|
sbp->sbhp = (const sb_header_t *)(void *)ma.base;
|
||||||
|
|
||||||
/* Checking header magic numbers.*/
|
/* Checking header magic numbers.*/
|
||||||
if ((sbhp->hdr_magic1 != SB_HDR_MAGIC1) ||
|
if ((sbp->sbhp->hdr_magic1 != SB_HDR_MAGIC1) ||
|
||||||
(sbhp->hdr_magic2 != SB_HDR_MAGIC2)) {
|
(sbp->sbhp->hdr_magic2 != SB_HDR_MAGIC2)) {
|
||||||
return CH_RET_ENOEXEC;
|
return CH_RET_ENOEXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking header size.*/
|
/* Checking header size.*/
|
||||||
if (sbhp->hdr_size != sizeof (sb_header_t)) {
|
if (sbp->sbhp->hdr_size != sizeof (sb_header_t)) {
|
||||||
return CH_RET_ENOEXEC;
|
return CH_RET_ENOEXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking header entry point.*/
|
/* Checking header entry point.*/
|
||||||
if (!chMemIsSpaceWithinX(&ma, (const void *)sbhp->hdr_entry, (size_t)2)) {
|
if (!chMemIsSpaceWithinX(&ma, (const void *)sbp->sbhp->hdr_entry, (size_t)2)) {
|
||||||
return CH_RET_EFAULT;
|
return CH_RET_EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +414,7 @@ msg_t sbExec(sb_class_t *sbp, const char *pathname,
|
||||||
.wbase = (stkalign_t *)wsp,
|
.wbase = (stkalign_t *)wsp,
|
||||||
.wend = (stkalign_t *)wsp + (size / sizeof (stkalign_t)),
|
.wend = (stkalign_t *)wsp + (size / sizeof (stkalign_t)),
|
||||||
.prio = prio,
|
.prio = prio,
|
||||||
.u_pc = sbhp->hdr_entry,
|
.u_pc = sbp->sbhp->hdr_entry,
|
||||||
.u_psp = (uint32_t)usp,
|
.u_psp = (uint32_t)usp,
|
||||||
.arg = (void *)sbp
|
.arg = (void *)sbp
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,55 +51,157 @@
|
||||||
/* Module local functions. */
|
/* Module local functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
__STATIC_FORCEINLINE void vfq_makectx(sb_class_t *sbp,
|
||||||
|
struct port_extctx *ectxp,
|
||||||
|
uint32_t active_mask) {
|
||||||
|
uint32_t irqn = __CLZ(active_mask);
|
||||||
|
sbp->vrq_wtmask &= ~(1U << irqn);
|
||||||
|
|
||||||
|
/* Building the return context.*/
|
||||||
|
ectxp->r0 = irqn;
|
||||||
|
ectxp->pc = sbp->sbhp->hdr_vfq; /* TODO validate or let it eventually crash? */
|
||||||
|
ectxp->xpsr = 0x01000000U;
|
||||||
|
#if CORTEX_USE_FPU == TRUE
|
||||||
|
ectxp->fpscr = FPU->FPDSCR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Module exported functions. */
|
/* Module exported functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Activates VRQs on the specified sandbox.
|
* @brief Triggers VRQs on the specified sandbox.
|
||||||
|
* @note This function must be called from IRQ context because
|
||||||
|
* it manipulates exception stack frames.
|
||||||
*
|
*
|
||||||
* @param[in] sbp pointer to a @p sb_class_t structure
|
* @param[in] sbp pointer to a @p sb_class_t structure
|
||||||
* @param[in] vmask mask of VRQs to be activated
|
* @param[in] vmask mask of VRQs to be activated
|
||||||
* @return The operation status.
|
* @return The operation status.
|
||||||
* @retval false if the activation has succeeded.
|
* @retval false if the activation has succeeded.
|
||||||
* @retval true in case of sandbox stack overflow.
|
* @retval true in case of sandbox stack overflow.
|
||||||
|
*
|
||||||
|
* @special
|
||||||
*/
|
*/
|
||||||
bool sbVRQSignalMaskI(sb_class_t *sbp, sb_vrqmask_t vmask) {
|
bool sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) {
|
||||||
struct port_extctx *ectxp;
|
struct port_extctx *ectxp;
|
||||||
const sb_header_t *sbhp;
|
|
||||||
|
|
||||||
/* This IRQ could have preempted the sandbox itself or some other thread,
|
chSysLockFromISR();
|
||||||
handling is different.*/
|
|
||||||
if (sbp->tp->state == CH_STATE_CURRENT) {
|
|
||||||
/* Sandbox case, getting the current exception frame.*/
|
|
||||||
ectxp = (struct port_extctx *)__get_PSP() - 1;
|
|
||||||
|
|
||||||
/* Checking if the new frame is within the sandbox else failure.*/
|
/* Adding VRQ mask to the pending mask.*/
|
||||||
if (!sb_is_valid_write_range(sbp,
|
sbp->vrq_wtmask |= vmask;
|
||||||
(void *)ectxp,
|
|
||||||
sizeof (struct port_extctx))) {
|
/* Triggering the VRQ if required.*/
|
||||||
return true;
|
if (sbp->vrq_isr == 0U) {
|
||||||
|
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
||||||
|
|
||||||
|
if (active_mask != 0U) {
|
||||||
|
|
||||||
|
/* This IRQ could have preempted the sandbox itself or some other thread,
|
||||||
|
handling is different.*/
|
||||||
|
if (sbp->tp->state == CH_STATE_CURRENT) {
|
||||||
|
/* Sandbox case, getting the current exception frame.*/
|
||||||
|
ectxp = (struct port_extctx *)__get_PSP() - 1;
|
||||||
|
|
||||||
|
/* Checking if the new frame is within the sandbox else failure.*/
|
||||||
|
if (!sb_is_valid_write_range(sbp,
|
||||||
|
(void *)ectxp,
|
||||||
|
sizeof (struct port_extctx))) {
|
||||||
|
chSysUnlockFromISR();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ectxp = sbp->tp->ctx.sp - 1;
|
||||||
|
|
||||||
|
/* Checking if the new frame is within the sandbox else failure.*/
|
||||||
|
if (!sb_is_valid_write_range(sbp,
|
||||||
|
(void *)ectxp,
|
||||||
|
sizeof (struct port_extctx))) {
|
||||||
|
chSysUnlockFromISR();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Preventing leakage of information, clearing all register values, those
|
||||||
|
would come from outside the sandbox.*/
|
||||||
|
memset((void *)ectxp, 0, sizeof (struct port_extctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Building the return context.*/
|
||||||
|
vfq_makectx(sbp, ectxp, active_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlockFromISR();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_vrq_disable(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
ectxp->r0 = sbp->vrq_isr;
|
||||||
|
sbp->vrq_isr |= SB_VRQ_ISR_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_vrq_enable(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
ectxp->r0 = sbp->vrq_isr;
|
||||||
|
sbp->vrq_isr &= ~SB_VRQ_ISR_DISABLED;
|
||||||
|
|
||||||
|
/* Re-triggering the VRQ if required.*/
|
||||||
|
if (sbp->vrq_isr == 0U) {
|
||||||
|
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
||||||
|
|
||||||
|
if (active_mask != 0U) {
|
||||||
|
/* Creating a context for return.*/
|
||||||
|
ectxp--;
|
||||||
|
|
||||||
|
/* Checking if the new frame is within the sandbox else failure.*/
|
||||||
|
if (!sb_is_valid_write_range(sbp,
|
||||||
|
(void *)ectxp,
|
||||||
|
sizeof (struct port_extctx))) {
|
||||||
|
__sb_abort(CH_RET_EFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Building the return context.*/
|
||||||
|
vfq_makectx(sbp, ectxp, active_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_vrq_getisr(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
ectxp->r0 = sbp->vrq_isr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_vrq_return(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
if (((sbp->vrq_isr & SB_VRQ_ISR_IRQMODE) == 0U)) {
|
||||||
|
__sb_abort(CH_RET_EFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-triggering the VRQ if required.*/
|
||||||
|
if (sbp->vrq_isr == 0U) {
|
||||||
|
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
||||||
|
|
||||||
|
if (active_mask != 0U) {
|
||||||
|
/* Building the return context, reusing the current context structure.*/
|
||||||
|
vfq_makectx(sbp, ectxp, active_mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ectxp = sbp->tp->ctx.sp - 1;
|
/* Ending IRQ mode.*/
|
||||||
|
sbp->vrq_isr &= ~SB_VRQ_ISR_IRQMODE;
|
||||||
|
|
||||||
/* Checking if the new frame is within the sandbox else failure.*/
|
/* Discarding the return current context, returning on the previous one.*/
|
||||||
if (!sb_is_valid_write_range(sbp,
|
ectxp++;
|
||||||
(void *)ectxp,
|
|
||||||
sizeof (struct port_extctx))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Preventing leakage of information, clearing all register values, those
|
|
||||||
would come from outside the sandbox.*/
|
|
||||||
memset((void *)ectxp, 0, sizeof (struct port_extctx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header location.*/
|
|
||||||
sbhp = (const sb_header_t *)(void *)sbp->config->regions[sbp->config->code_region].area.base;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SB_CFG_ENABLE_VRQ == TRUE */
|
#endif /* SB_CFG_ENABLE_VRQ == TRUE */
|
||||||
|
|
|
@ -34,6 +34,14 @@
|
||||||
/* Module constants. */
|
/* Module constants. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Virtual ISR register bit definitions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define SB_VRQ_ISR_DISABLED 1U
|
||||||
|
#define SB_VRQ_ISR_IRQMODE 2U
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Module pre-compile time settings. */
|
/* Module pre-compile time settings. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -46,11 +54,6 @@
|
||||||
/* Module data structures and types. */
|
/* Module data structures and types. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type of a mask of Virtual IRQs.
|
|
||||||
*/
|
|
||||||
typedef uint32_t sb_vrqmask_t;
|
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Module macros. */
|
/* Module macros. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -62,7 +65,11 @@ typedef uint32_t sb_vrqmask_t;
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
bool sbVRQSignalMaskI(sb_class_t *sbp, sb_vrqmask_t vmask);
|
bool sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask);
|
||||||
|
void sb_vrq_disable(struct port_extctx *ectxp);
|
||||||
|
void sb_vrq_enable(struct port_extctx *ectxp);
|
||||||
|
void sb_vrq_getisr(struct port_extctx *ectxp);
|
||||||
|
void sb_vrq_return(struct port_extctx *ectxp);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue