git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15625 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
5d245911e1
commit
c696466411
|
@ -77,9 +77,9 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
uint32_t hdr_exit;
|
uint32_t hdr_exit;
|
||||||
/**
|
/**
|
||||||
* @brief VFQ vector.
|
* @brief VRQ vector.
|
||||||
*/
|
*/
|
||||||
uint32_t hdr_vfq;
|
uint32_t hdr_vrq;
|
||||||
/**
|
/**
|
||||||
* @brief Used-defined parameters, defaulted to zero.
|
* @brief Used-defined parameters, defaulted to zero.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -48,6 +48,15 @@
|
||||||
#define SB_SYSC_EVENT_WAIT_ANY 9
|
#define SB_SYSC_EVENT_WAIT_ANY 9
|
||||||
#define SB_SYSC_EVENT_WAIT_ALL 10
|
#define SB_SYSC_EVENT_WAIT_ALL 10
|
||||||
#define SB_SYSC_EVENT_BROADCAST 11
|
#define SB_SYSC_EVENT_BROADCAST 11
|
||||||
|
#define SB_SYSC_LOADELF 12
|
||||||
|
#define SB_SYSC_VRQ_SETWT 248
|
||||||
|
#define SB_SYSC_VRQ_CLRWT 249
|
||||||
|
#define SB_SYSC_VRQ_SETEN 250
|
||||||
|
#define SB_SYSC_VRQ_CLREN 251
|
||||||
|
#define SB_SYSC_VRQ_DISABLE 252
|
||||||
|
#define SB_SYSC_VRQ_ENABLE 253
|
||||||
|
#define SB_SYSC_VRQ_GETISR 254
|
||||||
|
#define SB_SYSC_VRQ_RETURN 255
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -72,14 +72,18 @@ static void sb_api_loadelf(struct port_extctx *ectxp);
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Standard API handlers
|
* @name VRQ pseudo-instructions handlers
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#if (SB_CFG_ENABLE_VRQ == TRUE) || defined(__DOXYGEN__)
|
#if (SB_CFG_ENABLE_VRQ == TRUE) || defined(__DOXYGEN__)
|
||||||
#define SB_SVC252_HANDLER sb_vrq_disable
|
#define SB_SVC248_HANDLER sb_api_vrq_setwt
|
||||||
#define SB_SVC253_HANDLER sb_vrq_enable
|
#define SB_SVC249_HANDLER sb_api_vrq_clrwt
|
||||||
#define SB_SVC254_HANDLER sb_vrq_getisr
|
#define SB_SVC250_HANDLER sb_api_vrq_seten
|
||||||
#define SB_SVC255_HANDLER sb_vrq_return
|
#define SB_SVC251_HANDLER sb_api_vrq_clren
|
||||||
|
#define SB_SVC252_HANDLER sb_api_vrq_disable
|
||||||
|
#define SB_SVC253_HANDLER sb_api_vrq_enable
|
||||||
|
#define SB_SVC254_HANDLER sb_api_vrq_getisr
|
||||||
|
#define SB_SVC255_HANDLER sb_api_vrq_return
|
||||||
#endif
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "sb.h"
|
#include "sb.h"
|
||||||
|
|
||||||
#if (SB_CFG_ENABLE_VRQ == TRUE) || defined(__DOXYGEN__)
|
#if (SB_CFG_ENABLE_VRQ == TRUE) || defined(__DOXYGEN__)
|
||||||
|
@ -51,7 +49,7 @@
|
||||||
/* Module local functions. */
|
/* Module local functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
__STATIC_FORCEINLINE void vfq_makectx(sb_class_t *sbp,
|
__STATIC_FORCEINLINE void vrq_makectx(sb_class_t *sbp,
|
||||||
struct port_extctx *newctxp,
|
struct port_extctx *newctxp,
|
||||||
uint32_t active_mask) {
|
uint32_t active_mask) {
|
||||||
uint32_t irqn = __CLZ(active_mask);
|
uint32_t irqn = __CLZ(active_mask);
|
||||||
|
@ -59,17 +57,41 @@ __STATIC_FORCEINLINE void vfq_makectx(sb_class_t *sbp,
|
||||||
|
|
||||||
/* Building the return context.*/
|
/* Building the return context.*/
|
||||||
newctxp->r0 = irqn;
|
newctxp->r0 = irqn;
|
||||||
newctxp->pc = sbp->sbhp->hdr_vfq; /* TODO validate or let it eventually crash? */
|
newctxp->pc = sbp->sbhp->hdr_vrq;
|
||||||
newctxp->xpsr = 0x01000000U;
|
newctxp->xpsr = 0x01000000U;
|
||||||
#if CORTEX_USE_FPU == TRUE
|
#if CORTEX_USE_FPU == TRUE
|
||||||
newctxp->fpscr = FPU->FPDSCR;
|
newctxp->fpscr = FPU->FPDSCR;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vrq_check_trigger(sb_class_t *sbp, struct port_extctx *ectxp) {
|
||||||
|
|
||||||
|
/* Triggering the VRQ if required.*/
|
||||||
|
if ((sbp->vrq_isr & SB_VRQ_ISR_DISABLED) == 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.*/
|
||||||
|
vrq_makectx(sbp, ectxp, active_mask);
|
||||||
|
__port_syscall_set_u_psp(sbp->tp, ectxp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Used as a known privileged address.
|
* @brief Used as a known privileged address.
|
||||||
*/
|
*/
|
||||||
static void vfq_privileged_code(void) {
|
static void vrq_privileged_code(void) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
}
|
}
|
||||||
|
@ -79,6 +101,48 @@ static void vfq_privileged_code(void) {
|
||||||
/* Module exported functions. */
|
/* Module exported functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Triggers VRQs on the specified sandbox.
|
||||||
|
*
|
||||||
|
* @param[in] sbp pointer to a @p sb_class_t structure
|
||||||
|
* @param[in] vmask mask of VRQs to be activated
|
||||||
|
*
|
||||||
|
* @sclass
|
||||||
|
*/
|
||||||
|
void sbVRQTriggerS(sb_class_t *sbp, sb_vrqmask_t vmask) {
|
||||||
|
|
||||||
|
chDbgCheckClassS();
|
||||||
|
|
||||||
|
/* Adding VRQ mask to the pending mask.*/
|
||||||
|
sbp->vrq_wtmask |= vmask;
|
||||||
|
|
||||||
|
/* Triggering the VRQ if required.*/
|
||||||
|
if ((sbp->vrq_isr & SB_VRQ_ISR_DISABLED) == 0U) {
|
||||||
|
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
||||||
|
|
||||||
|
if (active_mask != 0U) {
|
||||||
|
struct port_extctx *ectxp, *newctxp;
|
||||||
|
/* Getting the pointer from the context switch structure.*/
|
||||||
|
ectxp = sbp->tp->ctx.sp;
|
||||||
|
newctxp = ectxp - 1;
|
||||||
|
|
||||||
|
/* Checking if the new frame is within the sandbox else failure.*/
|
||||||
|
if (!sb_is_valid_write_range(sbp,
|
||||||
|
(void *)newctxp,
|
||||||
|
sizeof (struct port_extctx))) {
|
||||||
|
/* Making the sandbox return on a privileged address, this
|
||||||
|
will cause a fault and sandbox termination.*/
|
||||||
|
ectxp->pc = (uint32_t)vrq_privileged_code;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Building the return context.*/
|
||||||
|
vrq_makectx(sbp, newctxp, active_mask);
|
||||||
|
__port_syscall_set_u_psp(sbp->tp, newctxp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Triggers VRQs on the specified sandbox.
|
* @brief Triggers VRQs on the specified sandbox.
|
||||||
* @note This function must be called from IRQ context because
|
* @note This function must be called from IRQ context because
|
||||||
|
@ -97,7 +161,7 @@ void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) {
|
||||||
sbp->vrq_wtmask |= vmask;
|
sbp->vrq_wtmask |= vmask;
|
||||||
|
|
||||||
/* Triggering the VRQ if required.*/
|
/* Triggering the VRQ if required.*/
|
||||||
if (sbp->vrq_isr == 0U) {
|
if ((sbp->vrq_isr & SB_VRQ_ISR_DISABLED) == 0U) {
|
||||||
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
||||||
|
|
||||||
if (active_mask != 0U) {
|
if (active_mask != 0U) {
|
||||||
|
@ -117,7 +181,7 @@ void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) {
|
||||||
/* Making the sandbox return on a privileged address, this
|
/* Making the sandbox return on a privileged address, this
|
||||||
will cause a fault and sandbox termination.*/
|
will cause a fault and sandbox termination.*/
|
||||||
chSysUnlockFromISR();
|
chSysUnlockFromISR();
|
||||||
ectxp->pc = (uint32_t)vfq_privileged_code;
|
ectxp->pc = (uint32_t)vrq_privileged_code;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,17 +198,13 @@ void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) {
|
||||||
/* Making the sandbox return on a privileged address, this
|
/* Making the sandbox return on a privileged address, this
|
||||||
will cause a fault and sandbox termination.*/
|
will cause a fault and sandbox termination.*/
|
||||||
chSysUnlockFromISR();
|
chSysUnlockFromISR();
|
||||||
ectxp->pc = (uint32_t)vfq_privileged_code;
|
ectxp->pc = (uint32_t)vrq_privileged_code;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preventing leakage of information, clearing all register values, those
|
|
||||||
would come from outside the sandbox.*/
|
|
||||||
memset((void *)newctxp, 0, sizeof (struct port_extctx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Building the return context.*/
|
/* Building the return context.*/
|
||||||
vfq_makectx(sbp, newctxp, active_mask);
|
vrq_makectx(sbp, newctxp, active_mask);
|
||||||
__port_syscall_set_u_psp(sbp->tp, newctxp);
|
__port_syscall_set_u_psp(sbp->tp, newctxp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,66 +214,78 @@ void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sb_vrq_disable(struct port_extctx *ectxp) {
|
void sb_api_vrq_setwt(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
ectxp->r0 = sbp->vrq_wtmask;
|
||||||
|
sbp->vrq_wtmask |= ectxp->r0;
|
||||||
|
|
||||||
|
vrq_check_trigger(sbp, ectxp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_api_vrq_clrwt(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
ectxp->r0 = sbp->vrq_wtmask;
|
||||||
|
sbp->vrq_wtmask &= ~ectxp->r0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_api_vrq_seten(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
ectxp->r0 = sbp->vrq_enmask;
|
||||||
|
sbp->vrq_enmask |= ectxp->r0;
|
||||||
|
|
||||||
|
vrq_check_trigger(sbp, ectxp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_api_vrq_clren(struct port_extctx *ectxp) {
|
||||||
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
|
ectxp->r0 = sbp->vrq_enmask;
|
||||||
|
sbp->vrq_enmask &= ~ectxp->r0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sb_api_vrq_disable(struct port_extctx *ectxp) {
|
||||||
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
ectxp->r0 = sbp->vrq_isr;
|
ectxp->r0 = sbp->vrq_isr;
|
||||||
sbp->vrq_isr |= SB_VRQ_ISR_DISABLED;
|
sbp->vrq_isr |= SB_VRQ_ISR_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sb_vrq_enable(struct port_extctx *ectxp) {
|
void sb_api_vrq_enable(struct port_extctx *ectxp) {
|
||||||
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
ectxp->r0 = sbp->vrq_isr;
|
ectxp->r0 = sbp->vrq_isr;
|
||||||
sbp->vrq_isr &= ~SB_VRQ_ISR_DISABLED;
|
sbp->vrq_isr &= ~SB_VRQ_ISR_DISABLED;
|
||||||
|
|
||||||
/* Re-triggering the VRQ if required.*/
|
vrq_check_trigger(sbp, ectxp);
|
||||||
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.*/
|
void sb_api_vrq_getisr(struct port_extctx *ectxp) {
|
||||||
vfq_makectx(sbp, ectxp, active_mask);
|
|
||||||
__port_syscall_set_u_psp(sbp->tp, ectxp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sb_vrq_getisr(struct port_extctx *ectxp) {
|
|
||||||
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
|
||||||
ectxp->r0 = sbp->vrq_isr;
|
ectxp->r0 = sbp->vrq_isr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sb_vrq_return(struct port_extctx *ectxp) {
|
void sb_api_vrq_return(struct port_extctx *ectxp) {
|
||||||
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
|
||||||
|
sb_vrqmask_t active_mask;
|
||||||
|
|
||||||
if (((sbp->vrq_isr & SB_VRQ_ISR_IRQMODE) == 0U)) {
|
/* VRQs must be disabled on return, sanity check.*/
|
||||||
|
if (((sbp->vrq_isr & SB_VRQ_ISR_DISABLED) == 0U)) {
|
||||||
__sb_abort(CH_RET_EFAULT);
|
__sb_abort(CH_RET_EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-triggering the VRQ if required.*/
|
/* Re-triggering the VRQ if required.*/
|
||||||
if (sbp->vrq_isr == 0U) {
|
active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
||||||
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
|
|
||||||
|
|
||||||
if (active_mask != 0U) {
|
if (active_mask != 0U) {
|
||||||
/* Building the return context, reusing the current context structure.*/
|
/* Building the return context, reusing the current context structure.*/
|
||||||
vfq_makectx(sbp, ectxp, active_mask);
|
vrq_makectx(sbp, ectxp, active_mask);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Ending IRQ mode.*/
|
/* Returning from VRQ.*/
|
||||||
sbp->vrq_isr &= ~SB_VRQ_ISR_IRQMODE;
|
sbp->vrq_isr &= ~SB_VRQ_ISR_DISABLED;
|
||||||
|
|
||||||
/* Discarding the return current context, returning on the previous one.*/
|
/* Discarding the return current context, returning on the previous one.*/
|
||||||
ectxp++;
|
ectxp++;
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define SB_VRQ_ISR_DISABLED 1U
|
#define SB_VRQ_ISR_DISABLED 1U
|
||||||
#define SB_VRQ_ISR_IRQMODE 2U
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -65,11 +64,16 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
void sbVRQTriggerS(sb_class_t *sbp, sb_vrqmask_t vmask);
|
||||||
void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask);
|
void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask);
|
||||||
void sb_vrq_disable(struct port_extctx *ectxp);
|
void sb_api_vrq_setwt(struct port_extctx *ectxp);
|
||||||
void sb_vrq_enable(struct port_extctx *ectxp);
|
void sb_api_vrq_clrwt(struct port_extctx *ectxp);
|
||||||
void sb_vrq_getisr(struct port_extctx *ectxp);
|
void sb_api_vrq_seten(struct port_extctx *ectxp);
|
||||||
void sb_vrq_return(struct port_extctx *ectxp);
|
void sb_api_vrq_clren(struct port_extctx *ectxp);
|
||||||
|
void sb_api_vrq_disable(struct port_extctx *ectxp);
|
||||||
|
void sb_api_vrq_enable(struct port_extctx *ectxp);
|
||||||
|
void sb_api_vrq_getisr(struct port_extctx *ectxp);
|
||||||
|
void sb_api_vrq_return(struct port_extctx *ectxp);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -836,6 +836,87 @@ static inline void sbSleepMicroseconds(time_usecs_t usecs) {
|
||||||
sbSleep(sbTimeUS2I(usecs));
|
sbSleep(sbTimeUS2I(usecs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ @p setwt pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline void __sb_vrq_setwt(void) {
|
||||||
|
|
||||||
|
__syscall0(248);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ @p clrwt pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline void __sb_vrq_clrwt(void) {
|
||||||
|
|
||||||
|
__syscall0(249);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ @p seten pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline void __sb_vrq_seten(void) {
|
||||||
|
|
||||||
|
__syscall0(250);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ @p clren pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline void __sb_vrq_clren(void) {
|
||||||
|
|
||||||
|
__syscall0(251);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ @p disable pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline void __sb_vrq_disable(void) {
|
||||||
|
|
||||||
|
__syscall0(252);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ @p enable pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline void __sb_vrq_enable(void) {
|
||||||
|
|
||||||
|
__syscall0(253);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ @p getisr pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline uint32_t __sb_vrq_getisr(void) {
|
||||||
|
|
||||||
|
__syscall0r(254);
|
||||||
|
return r0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VRQ return pseudo-instruction.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
static inline void __sb_vrq_return(void) {
|
||||||
|
|
||||||
|
__syscall0(255);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* SBUSER_H */
|
#endif /* SBUSER_H */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
Loading…
Reference in New Issue