-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdwmac_irq.c
180 lines (147 loc) · 4.27 KB
/
dwmac_irq.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
* libdeca - UWB Library for Qorvo/Decawave DW3000
*
* Copyright (C) 2016 - 2024 Bruno Randolf ([email protected])
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 3. See the file LICENSE.txt for more details.
*/
#include <string.h>
#include <deca_device_api.h>
#include <deca_version.h>
#include "dwmac.h"
#include "dwtime.h"
#include "log.h"
#include "mac802154.h"
#include "platform/dwmac_task.h"
extern struct rxbuf rx_buffer;
extern struct txbuf* current_tx;
extern bool rx_reenable;
#ifndef __ZEPHYR__
static const char* LOG_TAG = "DECA";
#endif
static uint32_t tx_done_cnt = 0;
/*** all these functions are called from dwt_isr() in interrupt context ***/
void dwmac_irq_rx_ok_cb(const dwt_cb_data_t* status)
{
DBG_UWB_IRQ("*** RX 0x%" PRIx32 " flags 0x%x", status->status,
status->rx_flags);
struct rxbuf* rx = &rx_buffer;
#if CONFIG_DECA_DEBUG_IRQ_TIME
rx->ts_irq_start = dw_get_systime();
#endif
if (current_tx != NULL && current_tx->pto != 0) {
/* sometimes PTO triggers even though we just received a frame.
* this seems to happen when PTO is quite small, to avoid this
* we disable it here */
dwt_setpreambledetecttimeout(0);
}
if (status->datalength > DWMAC_RXBUF_LEN) {
LOG_ERR_IRQ("Received frame too large");
if (rx_reenable) {
dwt_rxenable(DWT_START_RX_IMMEDIATE);
}
return;
}
rx->len = status->datalength;
rx->ts = dw_get_rx_timestamp();
if (!(status->rx_flags & DWT_CB_DATA_RX_FLAG_ND)
&& status->datalength > 0) {
dwt_readrxdata(rx->buf, status->datalength, 0);
}
if (status->rx_flags & DWT_CB_DATA_RX_FLAG_CPER) {
uint16_t stat;
dwt_readstsstatus(&stat, 0);
if (stat & ~0x100) {
// TODO: Don't log status "Peak growth rate warning"
LOG_ERR_IRQ("STS error STS_TOAST: %x", stat);
}
// TODO: handle error
} else if (status->rx_flags & DWT_CB_DATA_RX_FLAG_ND) {
// TODO: STS can also be used with data frames
int16_t stsq;
#if DRIVER_VERSION_HEX >= 0x080202
int sts_ok = dwt_readstsquality(&stsq, 0);
#else
int sts_ok = dwt_readstsquality(&stsq);
#endif
if (!sts_ok) {
LOG_ERR_IRQ("STS Qual not good %d", stsq);
// TODO: handle error
}
}
#if CONFIG_DECA_USE_CARRIERINTEG
rx->ci = dwt_readcarrierintegrator();
#endif
#if CONFIG_DECA_READ_RXDIAG
dwt_readdiagnostics(&rx->diag);
#endif
if (rx_reenable || rx->buf[0] & MAC154_FC_FRAME_PEND
|| (current_tx != NULL && current_tx->resp_multi)) {
dwt_rxenable(DWT_START_RX_IMMEDIATE);
}
#if CONFIG_DECA_DEBUG_IRQ_TIME
rx->ts_irq_end = dw_get_systime();
#endif
dwtask_queue_event(DWEVT_RX, rx);
}
void dwmac_irq_rx_to_cb(const dwt_cb_data_t* dat)
{
DBG_UWB_IRQ("*** RX TO 0x%" PRIx32, dat->status);
/* reset timeout values to zero, if not they keep triggering */
#ifdef DRIVER_VERSION_HEX // >= 0x060007
if (dat->status & DWT_INT_RXFTO_BIT_MASK) {
dwt_setrxtimeout(0);
}
if (dat->status & DWT_INT_RXPTO_BIT_MASK) {
dwt_setpreambledetecttimeout(0);
}
#else // == 0x040000 decadriver
if (dat->status & DWT_INT_RFTO) {
dwt_setrxtimeout(0);
}
if (dat->status & DWT_INT_RXPTO) {
dwt_setpreambledetecttimeout(0);
}
#endif
dwtask_queue_event(DWEVT_RX_TIMEOUT, &dat->status);
if (rx_reenable || (current_tx != NULL && current_tx->resp_multi)) {
dwt_rxenable(DWT_START_RX_IMMEDIATE);
}
}
void dwmac_irq_err_cb(const dwt_cb_data_t* dat)
{
DBG_UWB_IRQ("*** ERR 0x%x 0x%" PRIx32, dat->rx_flags, dat->status);
if (rx_reenable || (current_tx != NULL && current_tx->resp_multi)) {
dwt_rxenable(DWT_START_RX_IMMEDIATE);
}
dwtask_queue_event(DWEVT_ERR, &dat->status);
/* in case we are waiting for a timeout, also queue a RX_TIMEOUT event (!)
* so the timeout handlers are called. */
if (current_tx != NULL
&& (current_tx->rx_timeout != 0 || current_tx->pto != 0)) {
dwtask_queue_event(DWEVT_RX_TIMEOUT, &dat->status);
}
}
void dwmac_irq_tx_done_cb(const dwt_cb_data_t* dat)
{
DBG_UWB_IRQ("*** TX Done 0x%" PRIx32, dat->status);
tx_done_cnt++;
if (current_tx == NULL) {
return;
}
dwtask_queue_event(DWEVT_TX_DONE, NULL);
}
void dwmac_irq_spi_err_cb(const dwt_cb_data_t* dat)
{
LOG_ERR_IRQ("*** SPI ERR");
}
void dwmac_irq_spi_rdy_cb(const dwt_cb_data_t* dat)
{
LOG_INF_IRQ("*** SPI RDY");
// dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_SPIRDY_BIT_MASK);
}
uint32_t dwmac_get_tx_irq_cnt(void)
{
return tx_done_cnt;
}