618 lines
18 KiB
C
618 lines
18 KiB
C
/***************************************************************************
|
|
*
|
|
* Copyright 2015-2019 BES.
|
|
* All rights reserved. All unpublished rights reserved.
|
|
*
|
|
* No part of this work may be used or reproduced in any form or by any
|
|
* means, or stored in a database or retrieval system, without prior written
|
|
* permission of BES.
|
|
*
|
|
* Use of this work is governed by a license granted by BES.
|
|
* This work contains confidential and proprietary information of
|
|
* BES. which is protected by copyright, trade secret,
|
|
* trademark and other intellectual property rights.
|
|
*
|
|
****************************************************************************/
|
|
#ifdef CHIP_HAS_TRANSQ
|
|
|
|
#include "plat_addr_map.h"
|
|
#include "reg_transq.h"
|
|
#include "hal_transq.h"
|
|
#include "hal_trace.h"
|
|
#include "hal_cmu.h"
|
|
#include "stdbool.h"
|
|
#include "cmsis_nvic.h"
|
|
|
|
// BITMAP:
|
|
// [High Priority Slots] ...... [Normal Priority Slots]
|
|
// 31 30 29 28 27 26 25 ...... 10 9 8 7 6 5 4 3 2 1 0
|
|
|
|
static struct TRANSQ_T * const transq[HAL_TRANSQ_ID_QTY] = {
|
|
(struct TRANSQ_T *)TRANSQ0_BASE,
|
|
#if (CHIP_HAS_TRANSQ > 1)
|
|
(struct TRANSQ_T *)TRANSQ1_BASE,
|
|
#endif
|
|
};
|
|
|
|
static struct TRANSQ_T * const peer_transq[HAL_TRANSQ_ID_QTY] = {
|
|
(struct TRANSQ_T *)TRANSQ0_PEER_BASE,
|
|
#if (CHIP_HAS_TRANSQ > 1)
|
|
(struct TRANSQ_T *)TRANSQ1_PEER_BASE,
|
|
#endif
|
|
};
|
|
|
|
static const IRQn_Type remote_irq_num[HAL_TRANSQ_ID_QTY] = {
|
|
TRANSQ0_RMT_IRQn,
|
|
#if (CHIP_HAS_TRANSQ > 1)
|
|
TRANSQ1_RMT_IRQn,
|
|
#endif
|
|
};
|
|
|
|
static const IRQn_Type local_irq_num[HAL_TRANSQ_ID_QTY] = {
|
|
TRANSQ0_LCL_IRQn,
|
|
#if (CHIP_HAS_TRANSQ > 1)
|
|
TRANSQ1_LCL_IRQn,
|
|
#endif
|
|
};
|
|
|
|
static struct HAL_TRANSQ_CFG_T transq_cfg[HAL_TRANSQ_ID_QTY];
|
|
|
|
static uint8_t next_tx_slot[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];
|
|
|
|
static uint8_t active_tx_slot[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];
|
|
|
|
static bool tx_slot_full[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];
|
|
|
|
static uint8_t next_rx_slot[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];
|
|
|
|
static uint32_t rx_irq_mask[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];
|
|
|
|
static uint32_t construct_mask(uint32_t lsb, uint32_t width)
|
|
{
|
|
int i;
|
|
uint32_t result;
|
|
|
|
if (lsb >= 32 || width == 0) {
|
|
return 0;
|
|
}
|
|
|
|
result = 0;
|
|
for (i = lsb; i < lsb + width; i++) {
|
|
result |= (1 << i);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static uint32_t get_next_rx_slot(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, uint32_t slot)
|
|
{
|
|
slot++;
|
|
if (pri == HAL_TRANSQ_PRI_HIGH) {
|
|
if (slot >= TRANSQ_SLOT_NUM) {
|
|
slot = TRANSQ_SLOT_NUM - transq_cfg[id].slot.rx_num[pri];
|
|
}
|
|
} else {
|
|
if (slot >= transq_cfg[id].slot.rx_num[pri]) {
|
|
slot = 0;
|
|
}
|
|
}
|
|
|
|
return slot;
|
|
}
|
|
|
|
static uint32_t get_next_tx_slot(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, uint32_t slot)
|
|
{
|
|
slot++;
|
|
if (pri == HAL_TRANSQ_PRI_HIGH) {
|
|
if (slot >= TRANSQ_SLOT_NUM) {
|
|
slot = TRANSQ_SLOT_NUM - transq_cfg[id].slot.tx_num[pri];
|
|
}
|
|
} else {
|
|
if (slot >= transq_cfg[id].slot.tx_num[pri]) {
|
|
slot = 0;
|
|
}
|
|
}
|
|
|
|
return slot;
|
|
}
|
|
|
|
static void hal_transq_remote_irq_handler(void)
|
|
{
|
|
enum HAL_TRANSQ_ID_T id;
|
|
enum HAL_TRANSQ_PRI_T pri;
|
|
uint32_t status;
|
|
uint32_t slot;
|
|
|
|
#if (CHIP_HAS_TRANSQ > 1)
|
|
IRQn_Type irq = NVIC_GetCurrentActiveIRQ();
|
|
|
|
for (id = HAL_TRANSQ_ID_0; id < HAL_TRANSQ_ID_QTY; id++) {
|
|
if (irq == remote_irq_num[id]) {
|
|
break;
|
|
}
|
|
}
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return;
|
|
}
|
|
#else
|
|
id = HAL_TRANSQ_ID_0;
|
|
#endif
|
|
|
|
while ((status = peer_transq[id]->RMT_MIS) != 0) {
|
|
slot = next_rx_slot[id][HAL_TRANSQ_PRI_HIGH];
|
|
if (slot < TRANSQ_SLOT_NUM && (status & (1 << slot))) {
|
|
pri = HAL_TRANSQ_PRI_HIGH;
|
|
} else {
|
|
pri = HAL_TRANSQ_PRI_NORMAL;
|
|
slot = next_rx_slot[id][HAL_TRANSQ_PRI_NORMAL];
|
|
|
|
ASSERT(slot < TRANSQ_SLOT_NUM && (status & (1 << slot)),
|
|
"TRANSQ-%d: Rx IRQ when no slot or out of order: status=0x%08x next=%d pri_next=%d",
|
|
id, status, next_rx_slot[id][HAL_TRANSQ_PRI_NORMAL], next_rx_slot[id][HAL_TRANSQ_PRI_HIGH]);
|
|
}
|
|
|
|
// Mask IRQ from corresponding slots
|
|
peer_transq[id]->RMT_INTMASK &= ~rx_irq_mask[id][pri];
|
|
|
|
if (transq_cfg[id].rx_handler) {
|
|
transq_cfg[id].rx_handler(pri);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int hal_transq_active_tx_valid(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri)
|
|
{
|
|
return (active_tx_slot[id][pri] >= TRANSQ_SLOT_NUM ||
|
|
active_tx_slot[id][pri] != next_tx_slot[id][pri] ||
|
|
tx_slot_full[id][pri]);
|
|
}
|
|
|
|
static void hal_transq_local_irq_handler(void)
|
|
{
|
|
enum HAL_TRANSQ_ID_T id;
|
|
enum HAL_TRANSQ_PRI_T pri;
|
|
uint32_t status;
|
|
uint32_t slot, next_slot;
|
|
uint32_t lock;
|
|
|
|
#if (CHIP_HAS_TRANSQ > 1)
|
|
IRQn_Type irq = NVIC_GetCurrentActiveIRQ();
|
|
|
|
for (id = HAL_TRANSQ_ID_0; id < HAL_TRANSQ_ID_QTY; id++) {
|
|
if (irq == local_irq_num[id]) {
|
|
break;
|
|
}
|
|
}
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return;
|
|
}
|
|
#else
|
|
id = HAL_TRANSQ_ID_0;
|
|
#endif
|
|
|
|
while ((status = transq[id]->LERR_MIS) != 0) {
|
|
transq[id]->LERR_ISC.LERR_INTCLR = status;
|
|
ASSERT(false, "TRANSQ-%d: Tx on active slot: 0x%08x", id, status);
|
|
}
|
|
|
|
while ((status = transq[id]->LDONE_MIS) != 0) {
|
|
if (transq_cfg[id].tx_handler) {
|
|
lock = int_lock();
|
|
|
|
ASSERT(hal_transq_active_tx_valid(id, HAL_TRANSQ_PRI_HIGH), "TRANSQ-%d: Corrupted pri active tx: active=%d next=%d full=%d",
|
|
id, active_tx_slot[id][HAL_TRANSQ_PRI_HIGH], next_tx_slot[id][HAL_TRANSQ_PRI_HIGH], tx_slot_full[id][HAL_TRANSQ_PRI_HIGH]);
|
|
ASSERT(hal_transq_active_tx_valid(id, HAL_TRANSQ_PRI_NORMAL), "TRANSQ-%d: Corrupted active tx: active=%d next=%d full=%d",
|
|
id, active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL], next_tx_slot[id][HAL_TRANSQ_PRI_NORMAL], tx_slot_full[id][HAL_TRANSQ_PRI_NORMAL]);
|
|
|
|
slot = active_tx_slot[id][HAL_TRANSQ_PRI_HIGH];
|
|
if (slot < TRANSQ_SLOT_NUM && (status & (1 << slot))) {
|
|
pri = HAL_TRANSQ_PRI_HIGH;
|
|
} else {
|
|
pri = HAL_TRANSQ_PRI_NORMAL;
|
|
slot = active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL];
|
|
|
|
ASSERT(slot < TRANSQ_SLOT_NUM && (status & (1 << slot)),
|
|
"TRANSQ-%d: Tx done IRQ when slot empty or out of order: status=0x%08x next=%d pri_next=%d",
|
|
id, status, active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL], active_tx_slot[id][HAL_TRANSQ_PRI_HIGH]);
|
|
}
|
|
|
|
// Clear the interrupt
|
|
transq[id]->LDONE_ISC.LDONE_INTCLR = (1 << slot);
|
|
|
|
next_slot = get_next_tx_slot(id, pri, slot);
|
|
|
|
if (!tx_slot_full[id][pri] && next_slot == next_tx_slot[id][pri]) {
|
|
// No tx in progress
|
|
active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
|
|
} else {
|
|
tx_slot_full[id][pri] = false;
|
|
if (transq_cfg[id].slot.tx_num[pri] == 1) {
|
|
// No tx in progress
|
|
active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
|
|
} else {
|
|
// Some tx in progress
|
|
active_tx_slot[id][pri] = next_slot;
|
|
}
|
|
}
|
|
|
|
int_unlock(lock);
|
|
|
|
transq_cfg[id].tx_handler(pri,
|
|
(const uint8_t *)transq[id]->WSLOT[slot].ADDR,
|
|
transq[id]->WSLOT[slot].LEN);
|
|
} else {
|
|
transq[id]->LDONE_INTMASK = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_get_rx_status(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, bool *ready)
|
|
{
|
|
uint32_t lock;
|
|
uint32_t slot;
|
|
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
if (pri >= HAL_TRANSQ_PRI_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_PRI;
|
|
}
|
|
if (transq_cfg[id].slot.rx_num[pri] == 0) {
|
|
return HAL_TRANSQ_RET_BAD_RX_NUM;
|
|
}
|
|
if (transq_cfg[id].rx_handler) {
|
|
// Rx will be processed by IRQ handler
|
|
return HAL_TRANSQ_RET_BAD_MODE;
|
|
}
|
|
|
|
lock = int_lock();
|
|
|
|
slot = next_rx_slot[id][pri];
|
|
|
|
if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
|
|
*ready = true;
|
|
} else {
|
|
*ready = false;
|
|
}
|
|
|
|
int_unlock(lock);
|
|
|
|
return HAL_TRANSQ_RET_OK;
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_get_tx_status(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, bool *done)
|
|
{
|
|
uint32_t lock;
|
|
uint32_t slot, next_slot;
|
|
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
if (pri >= HAL_TRANSQ_PRI_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_PRI;
|
|
}
|
|
if (transq_cfg[id].slot.tx_num[pri] == 0) {
|
|
return HAL_TRANSQ_RET_BAD_TX_NUM;
|
|
}
|
|
if (transq_cfg[id].tx_handler) {
|
|
// Tx done will be processed by IRQ handler
|
|
return HAL_TRANSQ_RET_BAD_MODE;
|
|
}
|
|
|
|
lock = int_lock();
|
|
|
|
slot = active_tx_slot[id][pri];
|
|
|
|
ASSERT(hal_transq_active_tx_valid(id, pri), "TRANSQ-%d: Corrupted active tx: pri=%d active=%d next=%d full=%d",
|
|
id, pri, active_tx_slot[id][pri], next_tx_slot[id][pri], tx_slot_full[id][pri]);
|
|
|
|
if (transq[id]->LDONE_ISC.LDONE_RIS & (1 << slot)) {
|
|
*done = true;
|
|
|
|
// Clear the interrupt
|
|
transq[id]->LDONE_ISC.LDONE_INTCLR = (1 << slot);
|
|
|
|
next_slot = get_next_tx_slot(id, pri, slot);
|
|
|
|
if (!tx_slot_full[id][pri] && next_slot == next_tx_slot[id][pri]) {
|
|
// No tx in progress
|
|
active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
|
|
} else {
|
|
tx_slot_full[id][pri] = false;
|
|
if (transq_cfg[id].slot.tx_num[pri] == 1) {
|
|
// No tx in progress
|
|
active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
|
|
} else {
|
|
// Some tx in progress
|
|
active_tx_slot[id][pri] = next_slot;
|
|
}
|
|
}
|
|
} else {
|
|
*done = false;
|
|
}
|
|
|
|
int_unlock(lock);
|
|
|
|
return HAL_TRANSQ_RET_OK;
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_rx_first(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, const uint8_t **data, uint32_t *len)
|
|
{
|
|
enum HAL_TRANSQ_RET_T ret;
|
|
uint32_t slot;
|
|
//uint32_t lock;
|
|
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
if (pri >= HAL_TRANSQ_PRI_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_PRI;
|
|
}
|
|
if (transq_cfg[id].slot.rx_num[pri] == 0) {
|
|
return HAL_TRANSQ_RET_BAD_RX_NUM;
|
|
}
|
|
|
|
//lock = int_lock();
|
|
|
|
slot = next_rx_slot[id][pri];
|
|
|
|
if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
|
|
// Msg available
|
|
ret = HAL_TRANSQ_RET_OK;
|
|
|
|
if (data) {
|
|
*data = (const uint8_t *)peer_transq[id]->RSLOT[slot].ADDR;
|
|
}
|
|
if (len) {
|
|
*len = peer_transq[id]->RSLOT[slot].LEN;
|
|
}
|
|
} else {
|
|
// No msg. Re-enable IRQ
|
|
ret = HAL_TRANSQ_RET_RX_EMPTY;
|
|
|
|
if (data) {
|
|
*data = NULL;
|
|
}
|
|
if (len) {
|
|
*len = 0;
|
|
}
|
|
peer_transq[id]->RMT_INTMASK |= rx_irq_mask[id][pri];
|
|
}
|
|
|
|
//int_unlock(lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_rx_next(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, const uint8_t **data, uint32_t *len)
|
|
{
|
|
enum HAL_TRANSQ_RET_T ret;
|
|
uint32_t slot;
|
|
//uint32_t lock;
|
|
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
if (pri >= HAL_TRANSQ_PRI_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_PRI;
|
|
}
|
|
if (transq_cfg[id].slot.rx_num[pri] == 0) {
|
|
return HAL_TRANSQ_RET_BAD_RX_NUM;
|
|
}
|
|
|
|
ret = HAL_TRANSQ_RET_OK;
|
|
|
|
//lock = int_lock();
|
|
|
|
slot = next_rx_slot[id][pri];
|
|
|
|
if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
|
|
// Clear cur IRQ
|
|
peer_transq[id]->RMT_ISC.RMT_INTCLR = (1 << slot);
|
|
|
|
// Update next_rx_slot
|
|
slot = get_next_rx_slot(id, pri, slot);
|
|
next_rx_slot[id][pri] = slot;
|
|
|
|
if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
|
|
// Next msg available
|
|
if (data) {
|
|
*data = (const uint8_t *)peer_transq[id]->RSLOT[slot].ADDR;
|
|
}
|
|
if (len) {
|
|
*len = peer_transq[id]->RSLOT[slot].LEN;
|
|
}
|
|
} else {
|
|
// No msg
|
|
ret = HAL_TRANSQ_RET_RX_EMPTY;
|
|
}
|
|
} else {
|
|
// No msg
|
|
ret = HAL_TRANSQ_RET_RX_EMPTY;
|
|
}
|
|
|
|
if (ret == HAL_TRANSQ_RET_RX_EMPTY) {
|
|
if (data) {
|
|
*data = NULL;
|
|
}
|
|
if (len) {
|
|
*len = 0;
|
|
}
|
|
// Re-enable IRQ
|
|
peer_transq[id]->RMT_INTMASK |= rx_irq_mask[id][pri];
|
|
}
|
|
|
|
//int_unlock(lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_tx(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, const uint8_t *data, uint32_t len)
|
|
{
|
|
enum HAL_TRANSQ_RET_T ret;
|
|
uint32_t lock;
|
|
uint32_t slot;
|
|
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
if (pri >= HAL_TRANSQ_PRI_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_PRI;
|
|
}
|
|
if (transq_cfg[id].slot.tx_num[pri] == 0) {
|
|
return HAL_TRANSQ_RET_BAD_TX_NUM;
|
|
}
|
|
|
|
lock = int_lock();
|
|
|
|
if (tx_slot_full[id][pri]) {
|
|
ret = HAL_TRANSQ_RET_TX_FULL;
|
|
} else {
|
|
ret = HAL_TRANSQ_RET_OK;
|
|
|
|
slot = next_tx_slot[id][pri];
|
|
|
|
transq[id]->WSLOT[slot].ADDR = (uint32_t)data;
|
|
transq[id]->WSLOT[slot].LEN = len;
|
|
transq[id]->RMT_INTSET = (1 << slot);
|
|
|
|
// Update active_tx_slot if this is the only tx in progress
|
|
if (active_tx_slot[id][pri] >= TRANSQ_SLOT_NUM) {
|
|
active_tx_slot[id][pri] = slot;
|
|
}
|
|
|
|
// Update next_tx_slot
|
|
next_tx_slot[id][pri] = get_next_tx_slot(id, pri, slot);
|
|
|
|
if (next_tx_slot[id][pri] == active_tx_slot[id][pri]) {
|
|
tx_slot_full[id][pri] = true;
|
|
}
|
|
}
|
|
|
|
int_unlock(lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_update_num(enum HAL_TRANSQ_ID_T id, const struct HAL_TRANSQ_SLOT_NUM_T *slot)
|
|
{
|
|
uint32_t tx_mask;
|
|
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
if (slot == NULL) {
|
|
return HAL_TRANSQ_RET_BAD_SLOT;
|
|
}
|
|
if (slot->tx_num[HAL_TRANSQ_PRI_NORMAL] + slot->tx_num[HAL_TRANSQ_PRI_HIGH] > TRANSQ_SLOT_NUM) {
|
|
return HAL_TRANSQ_RET_BAD_TX_NUM;
|
|
}
|
|
if (slot->rx_num[HAL_TRANSQ_PRI_NORMAL] + slot->rx_num[HAL_TRANSQ_PRI_HIGH] > TRANSQ_SLOT_NUM) {
|
|
return HAL_TRANSQ_RET_BAD_RX_NUM;
|
|
}
|
|
|
|
transq_cfg[id].slot = *slot;
|
|
|
|
rx_irq_mask[id][HAL_TRANSQ_PRI_NORMAL] = construct_mask(0, slot->rx_num[HAL_TRANSQ_PRI_NORMAL]);
|
|
rx_irq_mask[id][HAL_TRANSQ_PRI_HIGH] = construct_mask(
|
|
TRANSQ_SLOT_NUM - slot->rx_num[HAL_TRANSQ_PRI_HIGH],
|
|
slot->rx_num[HAL_TRANSQ_PRI_HIGH]);
|
|
|
|
tx_mask = construct_mask(0, slot->tx_num[HAL_TRANSQ_PRI_NORMAL]) |
|
|
construct_mask(TRANSQ_SLOT_NUM - slot->tx_num[HAL_TRANSQ_PRI_HIGH], slot->tx_num[HAL_TRANSQ_PRI_HIGH]);
|
|
|
|
transq[id]->RMT_INTMASK = tx_mask;
|
|
transq[id]->LERR_INTMASK = tx_mask;
|
|
if (transq_cfg[id].tx_handler) {
|
|
transq[id]->LDONE_INTMASK = tx_mask;
|
|
} else {
|
|
transq[id]->LDONE_INTMASK = 0;
|
|
}
|
|
|
|
return HAL_TRANSQ_RET_OK;
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_open(enum HAL_TRANSQ_ID_T id, const struct HAL_TRANSQ_CFG_T *cfg)
|
|
{
|
|
const struct HAL_TRANSQ_SLOT_NUM_T *slot;
|
|
uint32_t ctrl;
|
|
enum HAL_TRANSQ_RET_T ret;
|
|
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
if (cfg == NULL) {
|
|
return HAL_TRANSQ_RET_BAD_CFG;
|
|
}
|
|
|
|
#ifdef CHIP_BEST2000
|
|
hal_cmu_clock_enable(HAL_CMU_MOD_P_TRANSQ_WF);
|
|
hal_cmu_reset_clear(HAL_CMU_MOD_P_TRANSQ_WF);
|
|
#elif defined(CHIP_BEST2001) && !defined(CHIP_BEST2001_DSP)
|
|
//2001 dsp has enable transq clk at hal_cmu_dsp_clock_enable()
|
|
hal_cmu_clock_enable(HAL_CMU_MOD_P_TQWF);
|
|
hal_cmu_reset_clear(HAL_CMU_MOD_P_TQWF);
|
|
hal_cmu_clock_enable(HAL_CMU_MOD_P_TQA7);
|
|
hal_cmu_reset_clear(HAL_CMU_MOD_P_TQA7);
|
|
#endif
|
|
|
|
transq_cfg[id] = *cfg;
|
|
|
|
slot = &cfg->slot;
|
|
|
|
ret = hal_transq_update_num(id, slot);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
|
|
next_tx_slot[id][HAL_TRANSQ_PRI_NORMAL] = slot->tx_num[HAL_TRANSQ_PRI_NORMAL] ? 0 : TRANSQ_SLOT_NUM;
|
|
active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL] = TRANSQ_SLOT_NUM;
|
|
tx_slot_full[id][HAL_TRANSQ_PRI_NORMAL] = false;
|
|
next_rx_slot[id][HAL_TRANSQ_PRI_NORMAL] = slot->rx_num[HAL_TRANSQ_PRI_NORMAL] ? 0 : TRANSQ_SLOT_NUM;
|
|
|
|
next_tx_slot[id][HAL_TRANSQ_PRI_HIGH] = slot->tx_num[HAL_TRANSQ_PRI_HIGH] ?
|
|
(TRANSQ_SLOT_NUM - slot->tx_num[HAL_TRANSQ_PRI_HIGH]) : TRANSQ_SLOT_NUM;
|
|
active_tx_slot[id][HAL_TRANSQ_PRI_HIGH] = TRANSQ_SLOT_NUM;
|
|
tx_slot_full[id][HAL_TRANSQ_PRI_HIGH] = false;
|
|
next_rx_slot[id][HAL_TRANSQ_PRI_HIGH] = slot->rx_num[HAL_TRANSQ_PRI_HIGH] ?
|
|
(TRANSQ_SLOT_NUM - slot->rx_num[HAL_TRANSQ_PRI_HIGH]) : TRANSQ_SLOT_NUM;
|
|
|
|
transq[id]->LDONE_ISC.LDONE_INTCLR = ~0UL;
|
|
transq[id]->LERR_ISC.LERR_INTCLR = ~0UL;
|
|
transq[id]->RMT_ISC.RMT_INTCLR = ~0UL;
|
|
|
|
ctrl = CTRL_REMOTE_IRQ_EN | CTRL_LOCAL_ERR_IRQ_EN;
|
|
if (cfg->tx_handler) {
|
|
ctrl |= CTRL_LOCAL_DONE_IRQ_EN;
|
|
}
|
|
transq[id]->CTRL = ctrl;
|
|
|
|
if (cfg->rx_handler) {
|
|
NVIC_SetVector(remote_irq_num[id], (uint32_t)hal_transq_remote_irq_handler);
|
|
NVIC_SetPriority(remote_irq_num[id], IRQ_PRIORITY_NORMAL);
|
|
NVIC_ClearPendingIRQ(remote_irq_num[id]);
|
|
NVIC_EnableIRQ(remote_irq_num[id]);
|
|
}
|
|
|
|
NVIC_SetVector(local_irq_num[id], (uint32_t)hal_transq_local_irq_handler);
|
|
NVIC_SetPriority(local_irq_num[id], IRQ_PRIORITY_NORMAL);
|
|
NVIC_ClearPendingIRQ(local_irq_num[id]);
|
|
NVIC_EnableIRQ(local_irq_num[id]);
|
|
|
|
return HAL_TRANSQ_RET_OK;
|
|
}
|
|
|
|
enum HAL_TRANSQ_RET_T hal_transq_close(enum HAL_TRANSQ_ID_T id)
|
|
{
|
|
if (id >= HAL_TRANSQ_ID_QTY) {
|
|
return HAL_TRANSQ_RET_BAD_ID;
|
|
}
|
|
|
|
transq[id]->CTRL = 0;
|
|
NVIC_DisableIRQ(remote_irq_num[id]);
|
|
NVIC_DisableIRQ(local_irq_num[id]);
|
|
|
|
return HAL_TRANSQ_RET_OK;
|
|
}
|
|
|
|
#endif // CHIP_HAS_TRANSQ
|