simplelink: dpl: update SwiP in dpl to enable RF driver

Also updated HwiP in order to support SwiP, and added QueueP which is
a dependency.

Signed-off-by: Vincent Wan <vincent.wan@linaro.org>
This commit is contained in:
Vincent Wan 2019-12-18 17:27:38 -08:00 committed by Kumar Gala
parent e8f58c6564
commit 8c430b64f0
5 changed files with 591 additions and 16 deletions

View File

@ -73,6 +73,7 @@ elseif(CONFIG_HAS_CC13X2_CC26X2_SDK)
kernel/zephyr/dpl/HwiP_zephyr.c
kernel/zephyr/dpl/SwiP_zephyr.c
kernel/zephyr/dpl/SemaphoreP_zephyr.c
kernel/zephyr/dpl/QueueP_zephyr.c
)
if(CONFIG_SOC_CC1352R)

View File

@ -128,12 +128,20 @@ void HwiP_delete(HwiP_Handle handle)
irq_disable(interruptNum - 16);
}
#elif defined(CONFIG_SOC_SERIES_CC13X2_CC26X2)
/* INT_PENDSV is already taken by Zephyr, so let's use INT_SWEV0 to support
* SwiP since this line is usually unused. Change this to a different
* interrupt if desired.
*/
int HwiP_swiPIntNum = INT_SWEV0;
typedef struct _HwiP_Obj {
uint32_t intNum;
struct sl_isr_args * cb;
} HwiP_Obj;
static struct sl_isr_args sl_OSC_COMB_cb = {NULL, 0};
static struct sl_isr_args sl_AUX_COMB_cb = {NULL, 0};
static struct sl_isr_args sl_SWEV0_cb = {NULL, 0};
/*
* ======== HwiP_construct ========
@ -143,32 +151,70 @@ HwiP_Handle HwiP_construct(HwiP_Struct *handle, int interruptNum,
{
HwiP_Obj *obj = (HwiP_Obj *)handle;
uintptr_t arg = 0;
uint8_t priority = INT_PRI_LEVEL7; /* default to lowest priority */
if (handle == NULL) {
return NULL;
}
if (params) {
priority = params->priority;
arg = params->arg;
}
/*
* Currently only support INT_OSC_COMB and INT_AUX_COMB
* Currently only support INT_OSC_COMB, INT_AUX_COMB, INT_SWEV0
*/
__ASSERT(INT_OSC_COMB == interruptNum || INT_AUX_COMB == interruptNum,
__ASSERT(INT_OSC_COMB == interruptNum || INT_AUX_COMB == interruptNum
|| INT_SWEV0 == interruptNum,
"Unexpected interruptNum: %d\r\n",
interruptNum);
/*
* Priority expected is either:
* INT_PRI_LEVEL1 to INT_PRI_LEVEL7,
* or ~0 or 255 (meaning lowest priority)
* ~0 and 255 are meant to be the same as INT_PRI_LEVEL7.
* For ~0 or 255, we want 7; but Zephyr IRQ_CONNECT adds +1
* to reserve INT_PRI_LEVEL0,
* so we pass 6 for those TI drivers passing prio = ~0.
*/
__ASSERT((INT_PRI_LEVEL7 == priority) ||
(INT_PRI_LEVEL6 == priority) ||
(INT_PRI_LEVEL5 == priority) ||
(INT_PRI_LEVEL4 == priority) ||
(INT_PRI_LEVEL3 == priority) ||
(INT_PRI_LEVEL2 == priority) ||
(INT_PRI_LEVEL1 == priority) ||
(0xFF == priority),
"Unexpected priority level, got: 0x%x\r\n",
(unsigned int)priority);
if (0xFF == priority) {
priority = INT_PRI_LEVEL7;
}
/* The priority for IRQ_CONNECT is encoded in the top 3 bits */
priority = (priority >> 5) - 1;
switch(interruptNum) {
case INT_OSC_COMB:
sl_OSC_COMB_cb.cb = hwiFxn;
sl_OSC_COMB_cb.arg = arg;
IRQ_CONNECT(INT_OSC_COMB - 16, 6, sl_isr, &sl_OSC_COMB_cb, 0);
obj->cb = &sl_OSC_COMB_cb;
IRQ_CONNECT(INT_OSC_COMB - 16, priority, sl_isr, &sl_OSC_COMB_cb, 0);
break;
case INT_AUX_COMB:
sl_AUX_COMB_cb.cb = hwiFxn;
sl_AUX_COMB_cb.arg = arg;
IRQ_CONNECT(INT_AUX_COMB - 16, 6, sl_isr, &sl_AUX_COMB_cb, 0);
obj->cb = &sl_AUX_COMB_cb;
IRQ_CONNECT(INT_AUX_COMB - 16, priority, sl_isr, &sl_AUX_COMB_cb, 0);
break;
case INT_SWEV0:
sl_SWEV0_cb.cb = hwiFxn;
sl_SWEV0_cb.arg = arg;
obj->cb = &sl_SWEV0_cb;
IRQ_CONNECT(INT_SWEV0 - 16, priority, sl_isr, &sl_SWEV0_cb, 0);
break;
default:
return(NULL);
@ -221,15 +267,22 @@ void HwiP_restore(uintptr_t key)
irq_unlock(key);
}
void HwiP_post(int interruptNum) {
ARG_UNUSED(interruptNum);
STUB("");
#if defined(CONFIG_SOC_SERIES_CC13X2_CC26X2)
void HwiP_post(int interruptNum)
{
IntPendSet((uint32_t)interruptNum);
}
void HwiP_setFunc(HwiP_Handle hwiP, HwiP_Fxn fxn, uintptr_t arg) {
ARG_UNUSED(hwiP);
ARG_UNUSED(fxn);
ARG_UNUSED(arg);
STUB("");
void HwiP_setFunc(HwiP_Handle hwiP, HwiP_Fxn fxn, uintptr_t arg)
{
HwiP_Obj *obj = (HwiP_Obj *)hwiP;
uintptr_t key = HwiP_disable();
obj->cb->cb = fxn;
obj->cb->arg = arg;
HwiP_restore(key);
}
void HwiP_destruct(HwiP_Struct *hwiP)
@ -244,3 +297,4 @@ void HwiP_destruct(HwiP_Struct *hwiP)
obj->cb->arg = (uintptr_t)NULL;
obj->cb = NULL;
}
#endif

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ======== QueueP.h ========
*/
typedef struct _QueueP_Elem {
struct _QueueP_Elem *volatile next;
struct _QueueP_Elem *volatile prev;
} QueueP_Elem;
typedef struct _QueueP_Obj {
QueueP_Elem elem;
} QueueP_Obj;
typedef QueueP_Obj *QueueP_Handle;
void QueueP_init(QueueP_Obj *obj);
uintptr_t QueueP_head(QueueP_Obj *obj);
uintptr_t QueueP_next(QueueP_Elem *qelem);
uintptr_t QueueP_prev(QueueP_Elem *qelem);
uintptr_t QueueP_get(QueueP_Obj *obj);
void QueueP_put(QueueP_Obj *obj, QueueP_Elem *elem);
void QueueP_remove(QueueP_Elem *qelem) ;
bool QueueP_empty(QueueP_Obj *obj);

View File

@ -0,0 +1,199 @@
/*
* Copyright (c) 2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ======== QueueP_zephyr.c ========
*/
#include <ti/drivers/dpl/HwiP.h>
#include "QueueP.h"
/*
* ======== QueueP_init ========
*/
void QueueP_init(QueueP_Obj *obj)
{
obj->elem.next = obj->elem.prev = &(obj->elem);
}
/*
* ======== QueueP_empty ========
*/
bool QueueP_empty(QueueP_Obj *obj)
{
return (obj->elem.next == &(obj->elem));
}
/*
* ======== QueueP_get ========
*/
uintptr_t QueueP_get(QueueP_Obj *obj)
{
QueueP_Elem *elem;
uintptr_t key;
key = HwiP_disable();
elem = obj->elem.next;
obj->elem.next = elem->next;
elem->next->prev = &(obj->elem);
HwiP_restore(key);
return ((uintptr_t)elem);
}
/*
* ======== QueueP_getTail ========
*/
uintptr_t QueueP_getTail(QueueP_Obj *obj)
{
QueueP_Elem *elem;
uintptr_t key;
key = HwiP_disable();
elem = obj->elem.prev;
obj->elem.prev = elem->prev;
elem->prev->next = &(obj->elem);
HwiP_restore(key);
return ((uintptr_t)elem);
}
/*
* ======== QueueP_head ========
*/
uintptr_t QueueP_head(QueueP_Obj *obj)
{
return ((uintptr_t)(obj->elem.next));
}
/*
* ======== elemClear ========
*/
void QueueP_elemClear(QueueP_Elem *qelem)
{
qelem->next = qelem->prev = qelem;
}
/*
* ======== insert ========
*/
void QueueP_insert(QueueP_Elem *qelem, QueueP_Elem *elem)
{
QueueP_put((QueueP_Obj *)qelem, elem);
}
/*
* ======== next ========
*/
uintptr_t QueueP_next(QueueP_Elem *qelem)
{
return ((uintptr_t)qelem->next);
}
/*
* ======== QueueP_prev ========
*/
uintptr_t QueueP_prev(QueueP_Elem *qelem)
{
return ((uintptr_t)qelem->prev);
}
/*
* ======== QueueP_put ========
*/
void QueueP_put(QueueP_Obj *obj, QueueP_Elem *elem)
{
uintptr_t key;
key = HwiP_disable();
elem->next = &(obj->elem);
elem->prev = obj->elem.prev;
obj->elem.prev->next = elem;
obj->elem.prev = elem;
HwiP_restore(key);
}
/*
* ======== QueueP_putHead ========
*/
void QueueP_putHead(QueueP_Obj *obj, QueueP_Elem *elem)
{
uintptr_t key;
key = HwiP_disable();
elem->prev = &(obj->elem);
elem->next = obj->elem.next;
obj->elem.next->prev = elem;
obj->elem.next = elem;
HwiP_restore(key);
}
/*
* ======== QueueP_remove ========
*/
void QueueP_remove(QueueP_Elem *qelem)
{
#if defined(__IAR_SYSTEMS_ICC__)
QueueP_Elem *temp;
temp = qelem->next;
qelem->prev->next = temp;
temp = qelem->prev;
qelem->next->prev = temp;
#else
qelem->prev->next = qelem->next;
qelem->next->prev = qelem->prev;
#endif
}
/*
* ======== isQueued ========
*/
bool QueueP_isQueued(QueueP_Elem *qelem)
{
if ((qelem->prev == qelem) && (qelem->next == qelem)) {
return (false);
}
else {
return (true);
}
}

View File

@ -6,17 +6,273 @@
#include <zephyr.h>
#include <ti/drivers/dpl/HwiP.h>
#include <ti/drivers/dpl/SwiP.h>
#include "QueueP.h"
/* Lowest priority interrupt */
#define INT_PRI_LEVEL7 0xe0
#define NUMPRI 4
typedef enum {
SwiP_State_Idle = 0,
SwiP_State_Posted,
SwiP_State_Running,
SwiP_State_Interrupted
} SwiP_State;
typedef uint32_t SwiP_LockState;
enum {
SwiP_LockState_Locked,
SwiP_LockState_Unlocked
};
typedef struct SwiP_Obj {
QueueP_Elem elem;
QueueP_Handle readyList;
SwiP_Params params;
SwiP_Fxn fxn;
uint32_t trigger;
uint32_t state;
} SwiP_Obj;
static void SwiP_handleHwi();
static const SwiP_Params SwiP_defaultParams = {
.arg0 = (uintptr_t) NULL,
.arg1 = (uintptr_t) NULL,
.priority = ~0, /* max priority */
.trigger = 0,
};
static volatile int SwiP_readyMask;
static volatile SwiP_LockState SwiP_lockState;
static volatile uint32_t SwiP_currentTrigger;
static volatile bool SwiP_schedulerRunning;
static volatile bool SwiP_initialized = false;
static HwiP_Struct SwiP_hwiStruct;
static QueueP_Obj SwiP_readyList[NUMPRI];
/* don't call with n == 0 */
static int maxbit(int n)
{
int mask = 1 << (NUMPRI - 1);
int max = NUMPRI - 1;
while (mask) {
if (n & mask) {
return max;
}
max--;
mask >>= 1;
}
return 0;
}
/*
* ======== SwiP_Params_init ========
*/
void SwiP_Params_init(SwiP_Params *params) {
/* structure copy */
*params = SwiP_defaultParams;
}
/*
* ======== SwiP_construct ========
*/
SwiP_Handle SwiP_construct(SwiP_Struct *handle, SwiP_Fxn swiFxn,
SwiP_Params *params)
{
SwiP_Obj *swi = (SwiP_Obj *)handle;
HwiP_Params hwiParams;
uintptr_t hwiKey;
uint32_t priority;
int i;
if (handle != NULL) {
hwiKey = HwiP_disable();
if (SwiP_initialized == false) {
for (i = 0; i < NUMPRI; i++) {
QueueP_init(&SwiP_readyList[i]);
}
SwiP_readyMask = 0;
SwiP_currentTrigger = 0;
SwiP_lockState = SwiP_LockState_Unlocked;
SwiP_schedulerRunning = false;
HwiP_Params_init(&hwiParams);
hwiParams.priority = INT_PRI_LEVEL7; // use the lowest priority
HwiP_construct(&SwiP_hwiStruct, HwiP_swiPIntNum, SwiP_handleHwi,
&hwiParams);
SwiP_initialized = true;
}
HwiP_restore(hwiKey);
if (params == NULL) {
params = (SwiP_Params *)&SwiP_defaultParams;
}
if (params->priority == (~0)) {
priority = NUMPRI - 1;
}
else {
priority = params->priority;
}
if (priority >= NUMPRI) {
return NULL;
}
else {
QueueP_init((QueueP_Obj *)&swi->elem);
swi->params = *params;
swi->params.priority = priority;
swi->fxn = swiFxn;
swi->trigger = swi->params.trigger;
swi->state = SwiP_State_Idle;
swi->readyList = &SwiP_readyList[priority];
}
}
return ((SwiP_Handle)swi);
}
/*
* ======== SwiP_destruct ========
*/
void SwiP_destruct(SwiP_Struct *handle)
{
SwiP_Obj *swi = (SwiP_Obj *)handle;
uintptr_t hwiKey = HwiP_disable();
/* if on SwiP_readyList, remove it */
QueueP_remove(&swi->elem);
if (QueueP_empty(swi->readyList)) {
SwiP_readyMask &= ~(1 << swi->params.priority);
}
HwiP_restore(hwiKey);
}
/*
* ======== SwiP_disable ========
*/
uintptr_t SwiP_disable(void)
{
k_sched_lock();
uintptr_t previousHwiState = HwiP_disable();
return 0;
SwiP_LockState previousLockState = SwiP_lockState;
SwiP_lockState = SwiP_LockState_Locked;
HwiP_restore(previousHwiState);
return previousLockState;
}
/*
* This is a non-preemptive fixed-priority scheduler implementation.
* It runs with interrupts disabled, but enables them for each swi.
*/
void SwiP_dispatch(uintptr_t hwiKey)
{
SwiP_Obj *swi;
int maxpri;
while (SwiP_readyMask && (SwiP_lockState == SwiP_LockState_Unlocked)) {
maxpri = maxbit(SwiP_readyMask);
swi = (SwiP_Obj *)QueueP_get(&SwiP_readyList[maxpri]);
if (QueueP_empty(&SwiP_readyList[maxpri])) {
SwiP_readyMask &= ~(1 << maxpri);
}
/*
* Prepare the swi for execution. The trigger has to be saved
* because the swi might re-post itself with another trigger value.
*/
swi->state = SwiP_State_Running;
SwiP_currentTrigger = swi->trigger;
swi->trigger = swi->params.trigger;
/* run the swi with interrupts enabled */
HwiP_restore(hwiKey);
swi->fxn(swi->params.arg0, swi->params.arg1);
hwiKey = HwiP_disable();
/* If the swi didn't get re-posted, set it to idle now */
if (swi->state == SwiP_State_Running) {
swi->state = SwiP_State_Idle;
}
}
/* Scheduler was set to running immediately after posting the interrupt */
SwiP_schedulerRunning = false;
}
static void SwiP_handleHwi()
{
uintptr_t hwiKey = HwiP_disable();
SwiP_dispatch(hwiKey);
HwiP_restore(hwiKey);
}
/*
* ======== SwiP_getTrigger ========
*/
uint32_t SwiP_getTrigger()
{
return (SwiP_currentTrigger);
}
/*
* ======== SwiP_or ========
*/
void SwiP_or(SwiP_Handle handle, uint32_t mask)
{
SwiP_Obj *swi = (SwiP_Obj *)handle;
uintptr_t hwiKey = HwiP_disable();
swi->trigger |= mask;
HwiP_restore(hwiKey);
SwiP_post(swi);
}
/*
* ======== SwiP_post ========
*/
void SwiP_post(SwiP_Handle handle)
{
SwiP_Obj *swi = (SwiP_Obj *)handle;
uintptr_t hwiKey = HwiP_disable();
/* (Re-)post an swi only once */
if (swi->state != SwiP_State_Posted) {
swi->state = SwiP_State_Posted;
QueueP_put(&SwiP_readyList[swi->params.priority],
(QueueP_Elem *)&swi->elem);
SwiP_readyMask |= 1 << swi->params.priority;
}
/* Activate the scheduler when not already running */
if ((SwiP_schedulerRunning == false) &&
(SwiP_lockState == SwiP_LockState_Unlocked)) {
HwiP_post(HwiP_swiPIntNum);
/* Set the scheduler into running state to avoid double posts */
SwiP_schedulerRunning = true;
}
HwiP_restore(hwiKey);
}
/*
@ -24,6 +280,17 @@ uintptr_t SwiP_disable(void)
*/
void SwiP_restore(uintptr_t key)
{
ARG_UNUSED(key);
k_sched_unlock();
uintptr_t hwiKey = HwiP_disable();
SwiP_lockState = key;
/* Determine whether the scheduler needs to run */
if (SwiP_readyMask && (key == SwiP_LockState_Unlocked) &&
(SwiP_schedulerRunning == false)) {
HwiP_post(HwiP_swiPIntNum);
/* Set the scheduler into running state to avoid double posts */
SwiP_schedulerRunning = true;
}
HwiP_restore(hwiKey);
}