RADIO: Switch to level interrupts, readied for nrf53

* Switched to level interrupts
* Added DPPI connections
* Added nrf53 glue and config
* HAL: Added event and subscription overrides
* Used code templates for common logic
* Fixed a minor bug in the maxlen logic
  (max len was masked wrongly so it could be configured
  to be up to 2x longer than in real HW)

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
This commit is contained in:
Alberto Escolar Piedras 2023-09-20 17:12:45 +02:00
parent 49bcea209c
commit 802e0cf2b9
24 changed files with 2903 additions and 765 deletions

View File

@ -5,11 +5,13 @@ src/HW_models/NRF_HWLowL.c
src/HW_models/NRF_GPIO_backend.c
src/HW_models/NHW_EGU.c
src/HW_models/NHW_AAR.c
src/HW_models/NRF_RADIO_bitcounter.c
src/HW_models/NRF_RADIO_utils.c
src/HW_models/trivial_xo.c
src/HW_models/fake_timer.c
src/HW_models/NRF_RADIO.c
src/HW_models/NHW_RADIO.c
src/HW_models/NHW_RADIO_bitcounter.c
src/HW_models/NHW_RADIO_signals.c
src/HW_models/NHW_RADIO_timings.c
src/HW_models/NHW_RADIO_utils.c
src/HW_models/NHW_AES_CCM.c
src/HW_models/NHW_AES_ECB.c
src/HW_models/crc.c
@ -19,13 +21,10 @@ src/HW_models/bstest_ticker.c
src/HW_models/NRF_NVMC.c
src/HW_models/NRF_GPIO.c
src/HW_models/NHW_TEMP.c
src/HW_models/NRF_RADIO_tasks_regs.c
src/HW_models/NHW_TIMER.c
src/HW_models/bs_compat.c
src/HW_models/NRF_FICR.c
src/HW_models/NRF_RADIO_timings.c
src/HW_models/NRF_GPIOTE.c
src/HW_models/NHW_RNG.c
src/HW_models/weak_stubs.c
src/HW_models/NHW_CLOCK.c
src/HW_models/NRF_RADIO_signals.c

View File

@ -13,6 +13,11 @@ src/HW_models/NHW_DPPI.c
src/HW_models/NHW_CLOCK.c
src/HW_models/NHW_EGU.c
src/HW_models/NHW_misc.c
src/HW_models/NHW_RADIO.c
src/HW_models/NHW_RADIO_bitcounter.c
src/HW_models/NHW_RADIO_signals.c
src/HW_models/NHW_RADIO_timings.c
src/HW_models/NHW_RADIO_utils.c
src/HW_models/NHW_RNG.c
src/HW_models/NHW_RTC.c
src/HW_models/NHW_SWI.c

View File

@ -5,6 +5,7 @@ src/nrfx/hal/nrf_clock.c
src/nrfx/hal/nrf_dppi.c
src/nrfx/hal/nrf_ecb.c
src/nrfx/hal/nrf_egu.c
src/nrfx/hal/nrf_radio.c
src/nrfx/hal/nrf_rng.c
src/nrfx/hal/nrf_rtc.c
src/nrfx/hal/nrf_temp.c

View File

@ -8,6 +8,7 @@
/**
* RADIO - 2.4 GHz Radio
* https://infocenter.nordicsemi.com/topic/ps_nrf52833/radio.html?cp=5_1_0_5_17
* https://infocenter.nordicsemi.com/topic/ps_nrf52833/radio.html?cp=5_1_0_5_17
*
* Note: as of now, only 1&2Mbps BLE & 15.4 packet formats are supported, there is quite many notes around in the code
* where changes would be required to support other formats. PCNF1.STATLEN is always assumed 0
@ -91,11 +92,11 @@
*
* Implementation Specification:
* A diagram of the main state machine can be found in docs/RADIO_states.svg
* That main state machine is driven by a timer (Timer_RADIO) which results in calls to nrf_radio_timer_triggered()
* That main state machine is driven by a timer (Timer_RADIO) which results in calls to nhw_radio_timer_triggered()
* and the tasks which cause transitions and/or the timer to be set to a new value.
*
* Apart from this main state machine there is a small state machine for handling the automatic TIFS re-enabling.
* See TIFS_state, Timer_TIFS, nrf_radio_fake_task_TRXEN_TIFS, and maybe_prepare_TIFS()
* See TIFS_state, Timer_TIFS, nhw_RADIO_fake_task_TRXEN_TIFS, and maybe_prepare_TIFS()
* This TIFS machine piggybacks on the main machine and its timer.
*
* And apart from this, there is an "abort" state machine, which is used to handle SW or another peripheral
@ -149,23 +150,26 @@
#include "NHW_common_types.h"
#include "NHW_config.h"
#include "NHW_peri_types.h"
#include "NRF_RADIO.h"
#include "NHW_RADIO.h"
#include "NHW_RADIO_signals.h"
#include "NHW_RADIO_utils.h"
#include "NHW_RADIO_timings.h"
#include "NHW_RADIO_bitcounter.h"
#include "NHW_RADIO_priv.h"
#include "nsi_hw_scheduler.h"
#include "NHW_AES_CCM.h"
#include "irq_ctrl.h"
#include "NRF_HWLowL.h"
#include "crc.h"
#include "NRF_RADIO_signals.h"
#include "NRF_RADIO_utils.h"
#include "NRF_RADIO_timings.h"
#include "NRF_RADIO_bitcounter.h"
#include "NRF_RADIO_priv.h"
#include "nsi_tasks.h"
#include "nsi_hws_models_if.h"
#include "weak_stubs.h"
#if NHW_RADIO_TOTAL_INST > 1
#error "This model only supports 1 instance so far"
#endif
NRF_RADIO_Type NRF_RADIO_regs;
uint32_t NRF_RADIO_INTEN = 0; //interrupt enable (global for RADIO_signals.c)
static bs_time_t Timer_RADIO = TIME_NEVER; //main radio timer
static bs_time_t Timer_RADIO_abort_reeval = TIME_NEVER; //Abort reevaluation response timer, this timer must have the lowest priority of all events (which may cause an abort)
@ -203,12 +207,11 @@ static void Rx_Addr_received(void);
static void Tx_abort_eval_respond(void);
static void Rx_abort_eval_respond(void);
static void CCA_abort_eval_respond(void);
static void nrf_radio_device_address_match(uint8_t rx_buf[]);
static void nhw_radio_device_address_match(uint8_t rx_buf[]);
static void radio_reset(void) {
memset(&NRF_RADIO_regs, 0, sizeof(NRF_RADIO_regs));
radio_state = RAD_DISABLED;
NRF_RADIO_INTEN = 0;
radio_sub_state = SUB_STATE_INVALID;
Timer_RADIO = TIME_NEVER;
rssi_sampling_on = false;
@ -229,32 +232,34 @@ static void radio_reset(void) {
NRF_RADIO_regs.PSEL.DFEGPIO[i] = 0xFFFFFFFF;
NRF_RADIO_regs.DFEPACKET.MAXCNT = 0x00001000;
NRF_RADIO_regs.POWER = 1;
nhwra_signalif_reset();
}
static void nrf_radio_init(void) {
static void nhw_radio_init(void) {
nrfra_timings_init();
radio_reset();
radio_on = false;
bits_per_us = 1;
}
NSI_TASK(nrf_radio_init, HW_INIT, 100);
NSI_TASK(nhw_radio_init, HW_INIT, 100);
double nrf_radio_get_bpus(void) {
double nhw_radio_get_bpus(void) {
return bits_per_us;
}
static inline void nrfra_set_Timer_RADIO(bs_time_t t){
static inline void nhwra_set_Timer_RADIO(bs_time_t t){
Timer_RADIO = t;
nsi_hws_find_next_event();
}
static inline void nrfra_set_Timer_abort_reeval(bs_time_t t){
static inline void nhwra_set_Timer_abort_reeval(bs_time_t t){
Timer_RADIO_abort_reeval = t;
nsi_hws_find_next_event();
}
void nrf_radio_tasks_TXEN(void) {
void nhw_RADIO_TASK_TXEN(void) {
if ( ( radio_state != RAD_DISABLED )
&& ( radio_state != RAD_TXIDLE )
&& ( radio_state != RAD_RXIDLE ) ){
@ -266,10 +271,10 @@ void nrf_radio_tasks_TXEN(void) {
radio_state = RAD_TXRU;
NRF_RADIO_regs.STATE = RAD_TXRU;
nrfra_set_Timer_RADIO(nsi_hws_get_time() + nrfra_timings_get_rampup_time(1, from_hw_tifs));
nhwra_set_Timer_RADIO(nsi_hws_get_time() + nhwra_timings_get_rampup_time(1, from_hw_tifs));
}
void nrf_radio_tasks_RXEN(void) {
void nhw_RADIO_TASK_RXEN(void) {
if ( ( radio_state != RAD_DISABLED )
&& ( radio_state != RAD_TXIDLE )
&& ( radio_state != RAD_RXIDLE ) ){
@ -281,7 +286,7 @@ void nrf_radio_tasks_RXEN(void) {
TIFS_state = TIFS_DISABLE;
radio_state = RAD_RXRU;
NRF_RADIO_regs.STATE = RAD_RXRU;
nrfra_set_Timer_RADIO(nsi_hws_get_time() + nrfra_timings_get_rampup_time(0, from_hw_tifs));
nhwra_set_Timer_RADIO(nsi_hws_get_time() + nhwra_timings_get_rampup_time(0, from_hw_tifs));
}
static void abort_if_needed(void) {
@ -303,12 +308,12 @@ static void abort_if_needed(void) {
}
}
void nrf_radio_tasks_START(void) {
void nhw_RADIO_TASK_START(void) {
if ( radio_state == RAD_TXIDLE ) {
bs_time_t Tx_start_time = nsi_hws_get_time() + nrfra_timings_get_TX_chain_delay();
bs_time_t Tx_start_time = nsi_hws_get_time() + nhwra_timings_get_TX_chain_delay();
radio_state = RAD_TXSTARTING;
NRF_RADIO_regs.STATE = RAD_TX;
nrfra_set_Timer_RADIO(Tx_start_time);
nhwra_set_Timer_RADIO(Tx_start_time);
} else if ( radio_state == RAD_RXIDLE ) {
start_Rx();
} else {
@ -318,7 +323,7 @@ void nrf_radio_tasks_START(void) {
}
}
void nrf_radio_tasks_CCASTART(void) {
void nhw_RADIO_TASK_CCASTART(void) {
if ((radio_state != RAD_RXIDLE)){
bs_trace_warning_line_time(
"NRF_RADIO: CCASTART received when the radio was not RXIDLE but in state %i. "
@ -329,13 +334,13 @@ void nrf_radio_tasks_CCASTART(void) {
start_CCA_ED(1);
}
void nrf_radio_tasks_CCASTOP(void) {
void nhw_RADIO_TASK_CCASTOP(void) {
if (( radio_state == RAD_CCA_ED ) && ( cca_status.CCA_notED )) {
abort_if_needed();
radio_state = RAD_RXIDLE;
NRF_RADIO_regs.STATE = RAD_RXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nrf_radio_signal_CCASTOPPED();
nhwra_set_Timer_RADIO(TIME_NEVER);
nhw_RADIO_signal_EVENTS_CCASTOPPED(0);
} else {
bs_trace_info_line_time(3,
"NRF_RADIO: TASK_CCASTOP received while the radio was not on a CCA procedure (was %i, %i). "
@ -344,7 +349,7 @@ void nrf_radio_tasks_CCASTOP(void) {
}
}
void nrf_radio_tasks_EDSTART(void) {
void nhw_RADIO_TASK_EDSTART(void) {
if ((radio_state != RAD_RXIDLE)){
bs_trace_warning_line_time(
"NRF_RADIO: EDSTART received when the radio was not RXIDLE but in state %i. "
@ -355,13 +360,13 @@ void nrf_radio_tasks_EDSTART(void) {
start_CCA_ED(0);
}
void nrf_radio_tasks_EDSTOP(void) {
void nhw_RADIO_TASK_EDSTOP(void) {
if (( radio_state == RAD_CCA_ED ) && ( cca_status.CCA_notED == 0)) {
abort_if_needed();
radio_state = RAD_RXIDLE;
NRF_RADIO_regs.STATE = RAD_RXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nrf_radio_signal_EDSTOPPED();
nhwra_set_Timer_RADIO(TIME_NEVER);
nhw_RADIO_signal_EVENTS_EDSTOPPED(0);
} else {
bs_trace_info_line_time(3,
"NRF_RADIO: TASK_EDSTOP received while the radio was not on a ED procedure (was %i, %i). "
@ -370,8 +375,8 @@ void nrf_radio_tasks_EDSTOP(void) {
}
}
void nrf_radio_tasks_STOP(void) {
nrf_radio_stop_bit_counter();
void nhw_RADIO_TASK_STOP(void) {
nhw_radio_stop_bit_counter();
if ((radio_state == RAD_TX) || (radio_state == RAD_TXSTARTING)) {
if (radio_state == RAD_TX) {
@ -379,12 +384,12 @@ void nrf_radio_tasks_STOP(void) {
}
radio_state = RAD_TXIDLE;
NRF_RADIO_regs.STATE = RAD_TXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
} else if ( radio_state == RAD_RX ){
abort_if_needed();
radio_state = RAD_RXIDLE;
NRF_RADIO_regs.STATE = RAD_RXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
} else if ( radio_state == RAD_CCA_ED ){
//The documentation is not clear about what happens if we get a STOP during a CCA or ED procedure,
//but it seems for CCA it can cause a bit of a mess depending on CCA mode.
@ -395,7 +400,7 @@ void nrf_radio_tasks_STOP(void) {
abort_if_needed();
radio_state = RAD_RXIDLE;
NRF_RADIO_regs.STATE = RAD_RXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
} else {
bs_trace_warning_line_time(
"NRF_RADIO: TASK_STOP received while the radio was not on either TX or RX but in state %i. "
@ -404,8 +409,8 @@ void nrf_radio_tasks_STOP(void) {
}
}
void nrf_radio_tasks_DISABLE(void) {
nrf_radio_stop_bit_counter();
void nhw_RADIO_TASK_DISABLE(void) {
nhw_radio_stop_bit_counter();
if ((radio_state == RAD_TX) || (radio_state == RAD_TXSTARTING)) {
if (radio_state == RAD_TX) {
@ -427,7 +432,7 @@ void nrf_radio_tasks_DISABLE(void) {
if (TIFS_state != TIFS_DISABLE) {
TIFS_state = TIFS_DISABLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
Timer_TIFS = TIME_NEVER;
}
@ -435,43 +440,28 @@ void nrf_radio_tasks_DISABLE(void) {
radio_state = RAD_TXDISABLE;
NRF_RADIO_regs.STATE = RAD_TXDISABLE;
TIFS_state = TIFS_DISABLE;
nrfra_set_Timer_RADIO(nsi_hws_get_time() + nrfra_timings_get_TX_rampdown_time());
nhwra_set_Timer_RADIO(nsi_hws_get_time() + nhwra_timings_get_TX_rampdown_time());
} else if ( ( radio_state == RAD_RXRU ) || ( radio_state == RAD_RXIDLE ) ) {
radio_state = RAD_RXDISABLE;
NRF_RADIO_regs.STATE = RAD_RXDISABLE;
TIFS_state = TIFS_DISABLE;
nrfra_set_Timer_RADIO(nsi_hws_get_time() + nrfra_timings_get_RX_rampdown_time());
nhwra_set_Timer_RADIO(nsi_hws_get_time() + nhwra_timings_get_RX_rampdown_time());
} else if ( radio_state == RAD_DISABLED ) {
//It seems the radio will also signal a DISABLED event even if it was already disabled
nrf_radio_stop_bit_counter();
nrf_radio_signal_DISABLED();
nhw_radio_stop_bit_counter();
nhw_RADIO_signal_EVENTS_DISABLED(0);
}
}
void nrf_radio_tasks_RSSISTART(void) {
void nhw_RADIO_TASK_RSSISTART(void) {
rssi_sampling_on = true;
}
void nrf_radio_tasks_RSSISTOP(void) {
void nhw_RADIO_TASK_RSSISTOP(void) {
rssi_sampling_on = false;
}
void nrf_radio_regw_sideeffects_INTENSET(void) {
if ( NRF_RADIO_regs.INTENSET ){
NRF_RADIO_INTEN |= NRF_RADIO_regs.INTENSET;
NRF_RADIO_regs.INTENSET = NRF_RADIO_INTEN;
}
}
void nrf_radio_regw_sideeffects_INTENCLR(void) {
if ( NRF_RADIO_regs.INTENCLR ){
NRF_RADIO_INTEN &= ~NRF_RADIO_regs.INTENCLR;
NRF_RADIO_regs.INTENSET = NRF_RADIO_INTEN;
NRF_RADIO_regs.INTENCLR = 0;
}
}
void nrf_radio_regw_sideeffects_POWER(void) {
void nhw_RADIO_regw_sideeffects_POWER(void) {
if ( NRF_RADIO_regs.POWER == 0 ){
radio_on = false;
} else {
@ -487,10 +477,10 @@ void nrf_radio_regw_sideeffects_POWER(void) {
/**
* This is a fake task meant to start a HW timer for the TX->RX or RX->TX TIFS
*/
void nrf_radio_fake_task_TRXEN_TIFS(void) {
void nhw_RADIO_fake_task_TRXEN_TIFS(void) {
if ( TIFS_state == TIFS_WAITING_FOR_DISABLE ) {
TIFS_state = TIFS_TRIGGERING_TRX_EN;
nrfra_set_Timer_RADIO(Timer_TIFS);
nhwra_set_Timer_RADIO(Timer_TIFS);
if ( Timer_RADIO < nsi_hws_get_time() ){
bs_trace_warning_line_time("NRF_RADIO: TIFS Ups: The Ramp down from Rx/Tx into a Tx/Rx takes more than the programmed TIFS time\n");
}
@ -506,7 +496,7 @@ void nrf_radio_fake_task_TRXEN_TIFS(void) {
*/
void maybe_prepare_TIFS(bool Tx_Not_Rx){
bs_time_t delta;
if ( !nrfra_is_HW_TIFS_enabled() ) {
if ( !nhwra_is_HW_TIFS_enabled() ) {
TIFS_state = TIFS_DISABLE;
return;
}
@ -517,9 +507,9 @@ void maybe_prepare_TIFS(bool Tx_Not_Rx){
}
if ( Tx_Not_Rx ){ //End of Tx
delta = NRF_RADIO_regs.TIFS + nrfra_timings_get_TX_chain_delay() - nrfra_timings_get_rampup_time(0, 1) - 3; /*open slightly earlier to have jitter margin*/
delta = NRF_RADIO_regs.TIFS + nhwra_timings_get_TX_chain_delay() - nhwra_timings_get_rampup_time(0, 1) - 3; /*open slightly earlier to have jitter margin*/
} else { //End of Rx
delta = NRF_RADIO_regs.TIFS - nrfra_timings_get_Rx_chain_delay() - nrfra_timings_get_TX_chain_delay() - nrfra_timings_get_rampup_time(1, 1) + 1;
delta = NRF_RADIO_regs.TIFS - nhwra_timings_get_Rx_chain_delay() - nhwra_timings_get_TX_chain_delay() - nhwra_timings_get_rampup_time(1, 1) + 1;
}
Timer_TIFS = nsi_hws_get_time() + delta;
TIFS_state = TIFS_WAITING_FOR_DISABLE; /* In Timer_TIFS we will trigger a TxEN or RxEN */
@ -531,71 +521,71 @@ void maybe_prepare_TIFS(bool Tx_Not_Rx){
* (typically do something at the end/start of a state, set the new state
* and schedule further the next state change)
*/
static void nrf_radio_timer_triggered(void) {
static void nhw_radio_timer_triggered(void) {
if ( radio_state == RAD_TXRU ){
radio_state = RAD_TXIDLE;
NRF_RADIO_regs.STATE = RAD_TXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nrf_radio_signal_READY();
nrf_radio_signal_TXREADY();
nhwra_set_Timer_RADIO(TIME_NEVER);
nhw_RADIO_signal_EVENTS_READY(0);
nhw_RADIO_signal_EVENTS_TXREADY(0);
} else if ( radio_state == RAD_RXRU ){
radio_state = RAD_RXIDLE;
NRF_RADIO_regs.STATE = RAD_RXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nrf_radio_signal_READY();
nrf_radio_signal_RXREADY();
nhwra_set_Timer_RADIO(TIME_NEVER);
nhw_RADIO_signal_EVENTS_READY(0);
nhw_RADIO_signal_EVENTS_RXREADY(0);
} else if ( radio_state == RAD_TXSTARTING ){
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
start_Tx();
} else if ( radio_state == RAD_TX ){
if ( radio_sub_state == TX_WAIT_FOR_ADDRESS_END ){
radio_sub_state = TX_WAIT_FOR_PAYLOAD_END;
nrfra_set_Timer_RADIO(tx_status.PAYLOAD_end_time);
nrf_radio_signal_ADDRESS();
nrf_radio_signal_FRAMESTART(); //See note on FRAMESTART
nhwra_set_Timer_RADIO(tx_status.PAYLOAD_end_time);
nhw_RADIO_signal_EVENTS_ADDRESS(0);
nhw_RADIO_signal_EVENTS_FRAMESTART(0); //See note on FRAMESTART
} else if ( radio_sub_state == TX_WAIT_FOR_PAYLOAD_END ) {
radio_sub_state = TX_WAIT_FOR_CRC_END;
nrfra_set_Timer_RADIO(tx_status.CRC_end_time);
nrf_radio_signal_PAYLOAD();
nhwra_set_Timer_RADIO(tx_status.CRC_end_time);
nhw_RADIO_signal_EVENTS_PAYLOAD(0);
} else if ( radio_sub_state == TX_WAIT_FOR_CRC_END ) {
radio_sub_state = SUB_STATE_INVALID;
radio_state = RAD_TXIDLE;
NRF_RADIO_regs.STATE = RAD_TXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nrf_radio_stop_bit_counter();
nrf_radio_signal_END();
nrf_radio_signal_PHYEND(); //See note on EVENTS_PHYEND
nhwra_set_Timer_RADIO(TIME_NEVER);
nhw_radio_stop_bit_counter();
nhw_RADIO_signal_EVENTS_END(0);
nhw_RADIO_signal_EVENTS_PHYEND(0); //See note on EVENTS_PHYEND
maybe_prepare_TIFS(true);
} else { //SUB_STATE_INVALID
bs_trace_error_time_line("programming error\n");
}
} else if ( radio_state == RAD_RX ){
if ( radio_sub_state == RX_WAIT_FOR_ADDRESS_END ) {
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
nsi_hws_find_next_event();
nrf_radio_signal_SYNC(); //See note on EVENTS_SYNC
nrf_radio_signal_ADDRESS();
nrf_radio_signal_FRAMESTART(); //See note on FRAMESTART
nhw_RADIO_signal_EVENTS_SYNC(0); //See note on EVENTS_SYNC
nhw_RADIO_signal_EVENTS_ADDRESS(0);
nhw_RADIO_signal_EVENTS_FRAMESTART(0); //See note on FRAMESTART
Rx_Addr_received();
radio_sub_state = RX_WAIT_FOR_PAYLOAD_END;
nrfra_set_Timer_RADIO(rx_status.PAYLOAD_End_Time);
nhwra_set_Timer_RADIO(rx_status.PAYLOAD_End_Time);
} else if ( radio_sub_state == RX_WAIT_FOR_PAYLOAD_END ) {
radio_sub_state = RX_WAIT_FOR_CRC_END;
nrfra_set_Timer_RADIO(rx_status.CRC_End_Time);
nrf_radio_signal_PAYLOAD();
nhwra_set_Timer_RADIO(rx_status.CRC_End_Time);
nhw_RADIO_signal_EVENTS_PAYLOAD(0);
} else if ( radio_sub_state == RX_WAIT_FOR_CRC_END ) {
radio_sub_state = SUB_STATE_INVALID;
radio_state = RAD_RXIDLE;
NRF_RADIO_regs.STATE = RAD_RXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
if ( rx_status.CRC_OK ) {
nrf_radio_signal_CRCOK();
nhw_RADIO_signal_EVENTS_CRCOK(0);
} else {
nrf_radio_signal_CRCERROR();
nhw_RADIO_signal_EVENTS_CRCERROR(0);
}
nrf_radio_stop_bit_counter();
nrf_radio_signal_PHYEND(); //See note on EVENTS_PHYEND
nrf_radio_signal_END();
nhw_radio_stop_bit_counter();
nhw_RADIO_signal_EVENTS_PHYEND(0); //See note on EVENTS_PHYEND
nhw_RADIO_signal_EVENTS_END(0);
maybe_prepare_TIFS(false);
} else { //SUB_STATE_INVALID
bs_trace_error_time_line("programming error\n");
@ -603,40 +593,40 @@ static void nrf_radio_timer_triggered(void) {
} else if ( radio_state == RAD_CCA_ED ){
radio_state = RAD_RXIDLE;
NRF_RADIO_regs.STATE = RAD_RXIDLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
if (cca_status.CCA_notED) { //CCA procedure ended
if (cca_status.is_busy) {
nrf_radio_signal_CCABUSY();
nhw_RADIO_signal_EVENTS_CCABUSY(0);
} else {
nrf_radio_signal_CCAIDLE();
nhw_RADIO_signal_EVENTS_CCAIDLE(0);
}
} else { //ED procedure ended
nrf_radio_signal_EDEND();
nhw_RADIO_signal_EVENTS_EDEND(0);
}
} else if ( radio_state == RAD_TXDISABLE ){
radio_state = RAD_DISABLED;
NRF_RADIO_regs.STATE = RAD_DISABLED;
nrfra_set_Timer_RADIO(TIME_NEVER);
nrf_radio_stop_bit_counter();
nrf_radio_signal_DISABLED();
nhwra_set_Timer_RADIO(TIME_NEVER);
nhw_radio_stop_bit_counter();
nhw_RADIO_signal_EVENTS_DISABLED(0);
} else if ( radio_state == RAD_RXDISABLE ){
radio_state = RAD_DISABLED;
NRF_RADIO_regs.STATE = RAD_DISABLED;
nrfra_set_Timer_RADIO(TIME_NEVER);
nrf_radio_stop_bit_counter();
nrf_radio_signal_DISABLED();
nhwra_set_Timer_RADIO(TIME_NEVER);
nhw_radio_stop_bit_counter();
nhw_RADIO_signal_EVENTS_DISABLED(0);
} else {
if ( ( radio_state == RAD_DISABLED ) && ( TIFS_state == TIFS_TRIGGERING_TRX_EN ) ) {
if ( Timer_RADIO != Timer_TIFS ){
bs_trace_warning_line_time("NRF_RADIO: TIFS Ups 3\n");
}
TIFS_state = TIFS_DISABLE;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
from_hw_tifs = true;
if ( TIFS_ToTxNotRx ) {
nrf_radio_tasks_TXEN();
nhw_RADIO_TASK_TXEN();
} else {
nrf_radio_tasks_RXEN();
nhw_RADIO_TASK_RXEN();
}
from_hw_tifs = false;
} else {
@ -647,14 +637,14 @@ static void nrf_radio_timer_triggered(void) {
}
}
NSI_HW_EVENT(Timer_RADIO, nrf_radio_timer_triggered, 990 /*We want the radio to be one of the very last to avoid unnecessary abort re-evaluations to the Phy*/);
NSI_HW_EVENT(Timer_RADIO, nhw_radio_timer_triggered, 990 /*We want the radio to be one of the very last to avoid unnecessary abort re-evaluations to the Phy*/);
/**
* The abort reevaluation timer has just triggered,
* => we can now respond to the Phy with our abort decision
*/
static void nrf_radio_timer_abort_reeval_triggered(void) {
nrfra_set_Timer_abort_reeval(TIME_NEVER);
static void nhw_radio_timer_abort_reeval_triggered(void) {
nhwra_set_Timer_abort_reeval(TIME_NEVER);
if ( abort_fsm_state == Tx_Abort_reeval ){
abort_fsm_state = No_pending_abort_reeval;
@ -670,7 +660,7 @@ static void nrf_radio_timer_abort_reeval_triggered(void) {
}
}
NSI_HW_EVENT(Timer_RADIO_abort_reeval, nrf_radio_timer_abort_reeval_triggered, 999 /* Purposely the last (all other events must have been evaluated before) */);
NSI_HW_EVENT(Timer_RADIO_abort_reeval, nhw_radio_timer_abort_reeval_triggered, 999 /* Purposely the last (all other events must have been evaluated before) */);
/**
* Handle all possible responses to a Tx request from the Phy
@ -686,7 +676,7 @@ static void handle_Tx_response(int ret){
} else if ( ret == P2G4_MSG_ABORTREEVAL ) {
phy_sync_ctrl_set_last_phy_sync_time( next_recheck_time );
abort_fsm_state = Tx_Abort_reeval;
nrfra_set_Timer_abort_reeval(next_recheck_time);
nhwra_set_Timer_abort_reeval(next_recheck_time);
}
}
@ -733,14 +723,14 @@ static void start_Tx(void) {
radio_state = RAD_TX;
NRF_RADIO_regs.STATE = RAD_TX;
nrfra_check_packet_conf();
nhwra_check_packet_conf();
//TOLOW: Add support for other packet formats and bitrates
uint8_t preamble_len = 0;
uint8_t address_len = 0;
uint8_t header_len = 0;
uint payload_len = 0;
uint8_t crc_len = nrfra_get_crc_length();
uint8_t crc_len = nhwra_get_crc_length();
if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit) {
preamble_len = 1; //1 byte
@ -759,7 +749,7 @@ static void start_Tx(void) {
bits_per_us = 0.25;
}
payload_len = nrfra_tx_copy_payload(tx_buf);
payload_len = nhwra_tx_copy_payload(tx_buf);
/* This code should be generalized to support any CRC configuration (CRCCNF, CRCINIT AND CRCPOLY)
* When doing so, we should still calculate the ble and 154 crc's with their optimized table implementations
@ -779,7 +769,7 @@ static void start_Tx(void) {
packet_duration /= bits_per_us;
uint packet_size = header_len + payload_len + crc_len;
nrfra_prep_tx_request(&tx_status.tx_req, packet_size, packet_duration);
nhwra_prep_tx_request(&tx_status.tx_req, packet_size, packet_duration);
update_abort_struct(&tx_status.tx_req.abort, &next_recheck_time);
@ -787,26 +777,26 @@ static void start_Tx(void) {
int ret = p2G4_dev_req_txv2_nc_b(&tx_status.tx_req, tx_buf, &tx_status.tx_resp);
handle_Tx_response(ret);
tx_status.ADDRESS_end_time = nsi_hws_get_time() + (bs_time_t)((preamble_len*8 + address_len*8)/bits_per_us) - nrfra_timings_get_TX_chain_delay();
tx_status.ADDRESS_end_time = nsi_hws_get_time() + (bs_time_t)((preamble_len*8 + address_len*8)/bits_per_us) - nhwra_timings_get_TX_chain_delay();
tx_status.PAYLOAD_end_time = tx_status.ADDRESS_end_time + (bs_time_t)(8*(header_len + payload_len)/bits_per_us);
tx_status.CRC_end_time = tx_status.PAYLOAD_end_time + (bs_time_t)(crc_len*8/bits_per_us);
radio_sub_state = TX_WAIT_FOR_ADDRESS_END;
nrfra_set_Timer_RADIO(tx_status.ADDRESS_end_time);
nhwra_set_Timer_RADIO(tx_status.ADDRESS_end_time);
}
static void Rx_handle_end_response(bs_time_t end_time) {
if (rx_status.rx_resp.status != P2G4_RXSTATUS_HEADER_ERROR) {
rx_status.CRC_End_Time = end_time + nrfra_timings_get_Rx_chain_delay();
rx_status.CRC_End_Time = end_time + nhwra_timings_get_Rx_chain_delay();
} //Otherwise we do not really now how the Nordic RADIO behaves depending on
//where the biterrors are and so forth. So let's always behave like if the
//packet lenght was received correctly, and just report a CRC error at the
//end of the CRC
if ( rx_status.rx_resp.status == P2G4_RXSTATUS_OK ){
NRF_RADIO_regs.RXCRC = nrfra_get_rx_crc_value(rx_buf, rx_status.rx_resp.packet_size);
NRF_RADIO_regs.RXCRC = nhwra_get_rx_crc_value(rx_buf, rx_status.rx_resp.packet_size);
rx_status.CRC_OK = 1;
NRF_RADIO_regs.CRCSTATUS = 1;
}
@ -817,10 +807,10 @@ static void Rx_handle_end_response(bs_time_t end_time) {
static void Rx_handle_address_end_response(bs_time_t address_time) {
rx_status.ADDRESS_End_Time = address_time + nrfra_timings_get_Rx_chain_delay();
rx_status.ADDRESS_End_Time = address_time + nhwra_timings_get_Rx_chain_delay();
uint length = nrfra_get_payload_length(rx_buf);
uint max_length = nrfra_get_MAXLEN();
uint length = nhwra_get_payload_length(rx_buf);
uint max_length = nhwra_get_MAXLEN();
if (length > max_length) {
// We reject the packet right away, setting the CRC error, and timers as expected
@ -844,7 +834,7 @@ static void Rx_handle_address_end_response(bs_time_t address_time) {
payload_end = rx_status.rx_resp.rx_time_stamp + (bs_time_t)((1+length)*8/bits_per_us);
} //Eventually this should be generalized with the packet configuration
rx_status.PAYLOAD_End_Time = nrfra_timings_get_Rx_chain_delay() +
rx_status.PAYLOAD_End_Time = nhwra_timings_get_Rx_chain_delay() +
hwll_dev_time_from_phy(payload_end);
rx_status.CRC_End_Time = rx_status.PAYLOAD_End_Time + rx_status.CRC_duration; //Provisional value (if we are accepting the packet)
@ -871,7 +861,7 @@ static void Rx_handle_address_end_response(bs_time_t address_time) {
//The real HW only copies the LQI value after the payload in this mode
//Note that doing it this early is a cheat
double RSSI = p2G4_RSSI_value_to_dBm(rx_status.rx_resp.rssi.RSSI);
uint8_t LQI = nrfra_dBm_to_modem_LQIformat(RSSI);
uint8_t LQI = nhwra_dBm_to_modem_LQIformat(RSSI);
//Eventually this should be generalized with the packet configuration:
((uint8_t*)NRF_RADIO_regs.PACKETPTR)[1 + rx_status.S1Offset + length] = LQI;
}
@ -890,7 +880,7 @@ static void handle_Rx_response(int ret){
phy_sync_ctrl_set_last_phy_sync_time( next_recheck_time );
abort_fsm_state = Rx_Abort_reeval;
nrfra_set_Timer_abort_reeval( BS_MAX(next_recheck_time,nsi_hws_get_time()) );
nhwra_set_Timer_abort_reeval( BS_MAX(next_recheck_time,nsi_hws_get_time()) );
} else if ( ( ret == P2G4_MSG_RXV2_ADDRESSFOUND ) && ( radio_state == RAD_RX /*if we havent aborted*/ ) ) {
@ -898,7 +888,7 @@ static void handle_Rx_response(int ret){
phy_sync_ctrl_set_last_phy_sync_time(address_time);
Rx_handle_address_end_response(address_time);
radio_sub_state = RX_WAIT_FOR_ADDRESS_END;
nrfra_set_Timer_RADIO(rx_status.ADDRESS_End_Time);
nhwra_set_Timer_RADIO(rx_status.ADDRESS_End_Time);
} else if ( ( ret == P2G4_MSG_RXV2_END ) && ( radio_state == RAD_RX /*if we havent aborted*/ ) ) {
@ -929,7 +919,7 @@ static void start_Rx(void) {
#define RX_N_ADDR 8 /* How many addresses we can search in parallel */
p2G4_address_t rx_addresses[RX_N_ADDR];
nrfra_check_packet_conf();
nhwra_check_packet_conf();
radio_state = RAD_RX;
NRF_RADIO_regs.STATE = RAD_RX;
@ -948,12 +938,12 @@ static void start_Rx(void) {
} else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ieee802154_250Kbit) {
bits_per_us = 0.25;
}
rx_status.CRC_duration = nrfra_get_crc_length()*8/bits_per_us;
rx_status.CRC_duration = nhwra_get_crc_length()*8/bits_per_us;
rx_status.CRC_OK = false;
rx_status.rx_resp.status = P2G4_RXSTATUS_NOSYNC;
nrfra_prep_rx_request(&rx_status.rx_req, rx_addresses);
nhwra_prep_rx_request(&rx_status.rx_req, rx_addresses);
update_abort_struct(&rx_status.rx_req.abort, &next_recheck_time);
@ -965,7 +955,7 @@ static void start_Rx(void) {
_NRF_MAX_PACKET_SIZE);
radio_sub_state = SUB_STATE_INVALID;
nrfra_set_Timer_RADIO(TIME_NEVER);
nhwra_set_Timer_RADIO(TIME_NEVER);
handle_Rx_response(ret);
}
@ -983,8 +973,8 @@ static void Rx_Addr_received(void) {
bool accept_packet = !rx_status.packet_rejected;
if ( rssi_sampling_on ){
NRF_RADIO_regs.RSSISAMPLE = nrfra_RSSI_value_to_modem_format(p2G4_RSSI_value_to_dBm(rx_status.rx_resp.rssi.RSSI));
nrf_radio_signal_RSSIEND();
NRF_RADIO_regs.RSSISAMPLE = nhwra_RSSI_value_to_modem_format(p2G4_RSSI_value_to_dBm(rx_status.rx_resp.rssi.RSSI));
nhw_RADIO_signal_EVENTS_RSSIEND(0);
}
NRF_RADIO_regs.RXMATCH = 0; //The only we support so far
@ -997,7 +987,7 @@ static void Rx_Addr_received(void) {
* If this is a problem, add a new timer and Rx state and delay raising the event
* until then
*/
nrf_radio_device_address_match(rx_buf);
nhw_radio_device_address_match(rx_buf);
}
update_abort_struct(&rx_status.rx_req.abort, &next_recheck_time);
@ -1009,7 +999,7 @@ static void Rx_Addr_received(void) {
//We said we don't want to continue => there will be no response (ret==0 always). We just close the reception like if the phy finished on its own even though we finished it
//We do what would correspond to Rx_handle_end_response() as it won't get called
NRF_RADIO_regs.RXCRC = nrfra_get_rx_crc_value(rx_buf, rx_status.rx_resp.packet_size);
NRF_RADIO_regs.RXCRC = nhwra_get_rx_crc_value(rx_buf, rx_status.rx_resp.packet_size);
nhw_ccm_radio_received_packet(!rx_status.CRC_OK);
}
}
@ -1025,7 +1015,7 @@ static void Rx_Addr_received(void) {
* the address is assumed to be the first 48 bits after the 2 byte header
* and the TxAddr bit to be 7th bit in 1st header byte as per the BT Core spec.
*/
static void nrf_radio_device_address_match(uint8_t rx_buf[]) {
static void nhw_radio_device_address_match(uint8_t rx_buf[]) {
bool match_found = false;
bool nomatch;
int TxAdd;
@ -1055,9 +1045,9 @@ static void nrf_radio_device_address_match(uint8_t rx_buf[]) {
}
if (match_found) {
nrf_radio_signal_DEVMATCH();
nhw_RADIO_signal_EVENTS_DEVMATCH(0);
} else {
nrf_radio_signal_DEVMISS();
nhw_RADIO_signal_EVENTS_DEVMISS(0);
}
}
@ -1085,7 +1075,7 @@ static void CCA_handle_end_response(void) {
}
} else { // Ending an ED procedure
double RSSI = p2G4_RSSI_value_to_dBm(cca_status.cca_resp.RSSI_max);
NRF_RADIO_regs.EDSAMPLE = nrfra_dBm_to_modem_LQIformat(RSSI);
NRF_RADIO_regs.EDSAMPLE = nhwra_dBm_to_modem_LQIformat(RSSI);
}
}
@ -1101,13 +1091,13 @@ static void handle_CCA_response(int ret){
phy_sync_ctrl_set_last_phy_sync_time( end_time );
cca_status.CCA_end_time = end_time;
if (radio_state == RAD_CCA_ED) { /*if we haven't aborted*/
nrfra_set_Timer_RADIO(cca_status.CCA_end_time);
nhwra_set_Timer_RADIO(cca_status.CCA_end_time);
}
CCA_handle_end_response();
} else if ( ret == P2G4_MSG_ABORTREEVAL ) {
phy_sync_ctrl_set_last_phy_sync_time( next_recheck_time );
abort_fsm_state = CCA_Abort_reeval;
nrfra_set_Timer_abort_reeval(next_recheck_time);
nhwra_set_Timer_abort_reeval(next_recheck_time);
}
}
@ -1137,13 +1127,13 @@ static void start_CCA_ED(bool CCA_not_ED){
cca_status.CCA_notED = CCA_not_ED;
cca_status.is_busy = false;
nrfra_prep_cca_request(&cca_status.cca_req, CCA_not_ED);
nhwra_prep_cca_request(&cca_status.cca_req, CCA_not_ED);
update_abort_struct(&cca_status.cca_req.abort, &next_recheck_time);
//Expected end time; note that it may be shorter if detect over threshold is set
cca_status.CCA_end_time = nsi_hws_get_time() + cca_status.cca_req.scan_duration;
nrfra_set_Timer_RADIO(cca_status.CCA_end_time);
nhwra_set_Timer_RADIO(cca_status.CCA_end_time);
//Request the CCA from the Phy:
int ret = p2G4_dev_req_cca_nc_b(&cca_status.cca_req, &cca_status.cca_resp);

70
src/HW_models/NHW_RADIO.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2017 Oticon A/S
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _NRF_RADIO_H
#define _NRF_RADIO_H
#ifdef __cplusplus
extern "C"{
#endif
void nhw_RADIO_TASK_TXEN(void);
void nhw_RADIO_TASK_RXEN(void);
void nhw_RADIO_TASK_START(void);
void nhw_RADIO_TASK_CCASTART(void);
void nhw_RADIO_TASK_CCASTOP(void);
void nhw_RADIO_TASK_EDSTART(void);
void nhw_RADIO_TASK_EDSTOP(void);
void nhw_RADIO_TASK_STOP() ;
void nhw_RADIO_TASK_DISABLE(void);
void nhw_RADIO_TASK_RSSISTART(void);
void nhw_RADIO_TASK_RSSISTOP(void);
void nhw_RADIO_TASK_BCSTART(void);
void nhw_RADIO_TASK_BCSTOP(void);
void nhw_RADIO_regw_sideeffects_BCC(void);
void nhw_RADIO_regw_sideeffects_POWER(void);
void nhw_RADIO_regw_sideeffects_TASKS_TXEN(void);
void nhw_RADIO_regw_sideeffects_TASKS_RXEN(void);
void nhw_RADIO_regw_sideeffects_TASKS_START(void);
void nhw_RADIO_regw_sideeffects_TASKS_STOP(void);
void nhw_RADIO_regw_sideeffects_TASKS_DISABLE(void);
void nhw_RADIO_regw_sideeffects_TASKS_RSSISTART(void);
void nhw_RADIO_regw_sideeffects_TASKS_RSSISTOP(void);
void nhw_RADIO_regw_sideeffects_TASKS_BCSTART(void);
void nhw_RADIO_regw_sideeffects_TASKS_BCSTOP(void);
void nhw_RADIO_regw_sideeffects_TASKS_EDSTART(void);
void nhw_RADIO_regw_sideeffects_TASKS_EDSTOP(void);
void nhw_RADIO_regw_sideeffects_TASKS_CCASTART(void);
void nhw_RADIO_regw_sideeffects_TASKS_CCASTOP(void);
void nhw_RADIO_regw_sideeffects_INTENSET(void);
void nhw_RADIO_regw_sideeffects_INTENCLR(void);
void nhw_RADIO_regw_sideeffects_EVENTS_all(unsigned int inst);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_TXEN(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_RXEN(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_START(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_STOP(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_DISABLE(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_RSSISTART(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_RSSISTOP(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_BCSTART(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_BCSTOP(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_EDSTART(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_EDSTOP(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_CCASTART(unsigned int);
void nhw_RADIO_regw_sideeffects_SUBSCRIBE_CCASTOP(unsigned int);
/*
* Internal interface to bitcounter
*/
double nhw_radio_get_bpus(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -12,8 +12,8 @@
#include "NHW_common_types.h"
#include "NHW_config.h"
#include "NHW_peri_types.h"
#include "NRF_RADIO.h"
#include "NRF_RADIO_signals.h"
#include "NHW_RADIO.h"
#include "NHW_RADIO_signals.h"
#include "nsi_hw_scheduler.h"
#include "nsi_tasks.h"
#include "nsi_hws_models_if.h"
@ -23,8 +23,10 @@ static bs_time_t Timer_RADIO_bitcounter = TIME_NEVER;
static bs_time_t Time_BitCounterStarted = TIME_NEVER;
static bool bit_counter_running = false;
extern NRF_RADIO_Type NRF_RADIO_regs;
static void nrf_radio_bitcounter_timer_triggered(void) {
nrf_radio_signal_BCMATCH();
nhw_RADIO_signal_EVENTS_BCMATCH(0);
Timer_RADIO_bitcounter = TIME_NEVER;
nsi_hws_find_next_event();
//Note that we leave the bit counter running, so a new BCC can be programmed to make it trigger later
@ -32,7 +34,7 @@ static void nrf_radio_bitcounter_timer_triggered(void) {
NSI_HW_EVENT(Timer_RADIO_bitcounter, nrf_radio_bitcounter_timer_triggered, 50);
void nrf_radio_tasks_BCSTART(void) {
void nhw_RADIO_TASK_BCSTART(void) {
/* Note that we do not validate that the end of the address has been received */
if (bit_counter_running) {
@ -42,11 +44,11 @@ void nrf_radio_tasks_BCSTART(void) {
}
bit_counter_running = true;
Time_BitCounterStarted = nsi_hws_get_time();
Timer_RADIO_bitcounter = Time_BitCounterStarted + NRF_RADIO_regs.BCC/nrf_radio_get_bpus();
Timer_RADIO_bitcounter = Time_BitCounterStarted + NRF_RADIO_regs.BCC/nhw_radio_get_bpus();
nsi_hws_find_next_event();
}
void nrf_radio_stop_bit_counter(void) {
void nhw_radio_stop_bit_counter(void) {
if (!bit_counter_running){
return;
}
@ -57,15 +59,15 @@ void nrf_radio_stop_bit_counter(void) {
}
}
void nrf_radio_tasks_BCSTOP(void) {
nrf_radio_stop_bit_counter();
void nhw_RADIO_TASK_BCSTOP(void) {
nhw_radio_stop_bit_counter();
}
void nrf_radio_regw_sideeffects_BCC(void) {
void nhw_RADIO_regw_sideeffects_BCC(void) {
if (!bit_counter_running){
return;
}
Timer_RADIO_bitcounter = Time_BitCounterStarted + NRF_RADIO_regs.BCC/nrf_radio_get_bpus();
Timer_RADIO_bitcounter = Time_BitCounterStarted + NRF_RADIO_regs.BCC/nhw_radio_get_bpus();
if (Timer_RADIO_bitcounter < nsi_hws_get_time()) {
bs_trace_warning_line_time("NRF_RADIO: Reprogrammed bitcounter with a BCC which has already"
"passed (%"PRItime") => we ignore it\n",

View File

@ -13,7 +13,7 @@
extern "C"{
#endif
void nrf_radio_stop_bit_counter(void);
void nhw_radio_stop_bit_counter(void);
#ifdef __cplusplus
}

View File

@ -0,0 +1,245 @@
/*
* Copyright (c) 2017 Oticon A/S
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* This file includes the RADIO event & signals functionality,
* the registers writes sideeffects for tasks, subscriptions, events,
* and interrupt masks.
* For signals, when a signal is generated:
* Setting the EVENTS registers
* Sending the signal to the PPI
* Generating the corresponding interrupts
* Calling tasks if the corresponding shortcuts are enabled
*
*
*/
#include "NHW_common_types.h"
#include "NHW_templates.h"
#include "NHW_config.h"
#include "NHW_peri_types.h"
#include "NHW_RADIO.h"
#include "NHW_RADIO_utils.h"
#include "NHW_xPPI.h"
#include "irq_ctrl.h"
#include "bs_tracing.h"
#if (NHW_HAS_DPPI)
/* Mapping of peripheral instance to DPPI instance */
static uint nhw_RADIO_dppi_map[NHW_RADIO_TOTAL_INST] = NHW_RADIO_DPPI_MAP;
#endif
static uint32_t RADIO_INTEN; //interrupt enable
extern NRF_RADIO_Type NRF_RADIO_regs;
extern void nhw_RADIO_fake_task_TRXEN_TIFS(void);
void nhwra_signalif_reset(void){
RADIO_INTEN = 0;
}
static void nhw_RADIO_eval_interrupt(uint inst) {
static bool radio_int_line[NHW_RADIO_TOTAL_INST]; /* Is the RADIO currently driving its interrupt line high */
/* Mapping of peripheral instance to {int controller instance, int number} */
static struct nhw_irq_mapping nhw_radio_irq_map[NHW_RADIO_TOTAL_INST] = NHW_RADIO_INT_MAP;
bool new_int_line = false;
NHW_CHECK_INTERRUPT_si(RADIO, READY, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, ADDRESS, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, PAYLOAD, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, END, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, DISABLED, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, DEVMATCH, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, DEVMISS, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, RSSIEND, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, BCMATCH, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, CRCOK, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, CRCERROR, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, FRAMESTART, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, EDEND, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, EDSTOPPED, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, CCAIDLE, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, CCABUSY, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, CCASTOPPED, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, RATEBOOST, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, TXREADY, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, RXREADY, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, MHRMATCH, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, SYNC, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, PHYEND, RADIO_INTEN)
NHW_CHECK_INTERRUPT_si(RADIO, CTEPRESENT, RADIO_INTEN)
hw_irq_ctrl_toggle_level_irq_line_if(&radio_int_line[inst],
new_int_line,
&nhw_radio_irq_map[inst]);
}
NHW_SIDEEFFECTS_INTSET_si(RADIO, NRF_RADIO_regs., RADIO_INTEN)
NHW_SIDEEFFECTS_INTCLR_si(RADIO, NRF_RADIO_regs., RADIO_INTEN)
NHW_SIDEEFFECTS_EVENTS(RADIO)
static NHW_SIGNAL_EVENT_ns_si(RADIO, READY)
static NHW_SIGNAL_EVENT_ns_si(RADIO, ADDRESS)
NHW_SIGNAL_EVENT_si(RADIO, PAYLOAD)
static NHW_SIGNAL_EVENT_ns_si(RADIO, END)
static NHW_SIGNAL_EVENT_ns_si(RADIO, DISABLED)
NHW_SIGNAL_EVENT_si(RADIO, DEVMATCH)
NHW_SIGNAL_EVENT_si(RADIO, DEVMISS)
NHW_SIGNAL_EVENT_si(RADIO, RSSIEND)
NHW_SIGNAL_EVENT_si(RADIO, BCMATCH)
NHW_SIGNAL_EVENT_si(RADIO, CRCOK)
NHW_SIGNAL_EVENT_si(RADIO, CRCERROR)
static NHW_SIGNAL_EVENT_ns_si(RADIO, FRAMESTART)
static NHW_SIGNAL_EVENT_ns_si(RADIO, EDEND)
NHW_SIGNAL_EVENT_si(RADIO, EDSTOPPED)
static NHW_SIGNAL_EVENT_ns_si(RADIO, CCAIDLE)
static NHW_SIGNAL_EVENT_ns_si(RADIO, CCABUSY)
NHW_SIGNAL_EVENT_si(RADIO, CCASTOPPED)
NHW_SIGNAL_EVENT_si(RADIO, RATEBOOST)
static NHW_SIGNAL_EVENT_ns_si(RADIO, TXREADY)
static NHW_SIGNAL_EVENT_ns_si(RADIO, RXREADY)
NHW_SIGNAL_EVENT_si(RADIO, MHRMATCH)
NHW_SIGNAL_EVENT_si(RADIO, SYNC)
static NHW_SIGNAL_EVENT_ns_si(RADIO, PHYEND)
NHW_SIGNAL_EVENT_si(RADIO, CTEPRESENT)
void nhw_RADIO_signal_EVENTS_READY(unsigned int inst) {
nhw_RADIO_signal_EVENTS_READY_noshort(inst);
NHW_SHORT_si(RADIO, READY, START)
NHW_SHORT_si(RADIO, READY, EDSTART)
}
void nhw_RADIO_signal_EVENTS_ADDRESS(unsigned int inst) {
nhw_RADIO_signal_EVENTS_ADDRESS_noshort(inst);
NHW_SHORT_si(RADIO, ADDRESS, RSSISTART)
NHW_SHORT_si(RADIO, ADDRESS, BCSTART)
}
void nhw_RADIO_signal_EVENTS_END(unsigned int inst) {
nhw_RADIO_signal_EVENTS_END_noshort(inst);
NHW_SHORT_si(RADIO, END, DISABLE)
NHW_SHORT_si(RADIO, END, START)
}
void nhw_RADIO_signal_EVENTS_DISABLED(unsigned int inst) {
nhw_RADIO_signal_EVENTS_DISABLED_noshort(inst);
/*
* Everything indicates that, when the HW TIFS is enabled
* what happens is that these DISABLED_[TR]XEN shorts are
* effectively disabled and the tasks_[TR]XEN is instead
* triggered when a HW counter/timer triggers a bit later
*/
if (nhwra_is_HW_TIFS_enabled()) {
/* This is a fake task meant to start a HW timer for the TIFS
* which has effect only if the TIFS was enabled.
* In that case, the TXEN or RXEN will be triggered in a small
* while (as per the TIFS configuration/Timer_TIFS), instead of right now */
nhw_RADIO_fake_task_TRXEN_TIFS();
} else {
/* Otherwise the normal TXEN/RXEN shortcuts apply */
NHW_SHORT_si(RADIO, DISABLED, TXEN)
NHW_SHORT_si(RADIO, DISABLED, RXEN)
}
NHW_SHORT_si(RADIO, DISABLED, RSSISTOP)
}
void nhw_RADIO_signal_EVENTS_FRAMESTART(unsigned int inst) {
nhw_RADIO_signal_EVENTS_FRAMESTART_noshort(inst);
NHW_SHORT_si(RADIO, FRAMESTART, BCSTART)
}
void nhw_RADIO_signal_EVENTS_EDEND(unsigned int inst) {
nhw_RADIO_signal_EVENTS_EDEND_noshort(inst);
NHW_SHORT_si(RADIO, EDEND, DISABLE)
}
void nhw_RADIO_signal_EVENTS_CCAIDLE(unsigned int inst) {
nhw_RADIO_signal_EVENTS_CCAIDLE_noshort(inst);
NHW_SHORT_si(RADIO, CCAIDLE, STOP)
NHW_SHORT_si(RADIO, CCAIDLE, TXEN)
}
void nhw_RADIO_signal_EVENTS_CCABUSY(unsigned int inst) {
nhw_RADIO_signal_EVENTS_CCABUSY_noshort(inst);
NHW_SHORT_si(RADIO, CCABUSY, DISABLE)
}
void nhw_RADIO_signal_EVENTS_TXREADY(unsigned int inst) {
nhw_RADIO_signal_EVENTS_TXREADY_noshort(inst);
NHW_SHORT_si(RADIO, TXREADY, START)
}
void nhw_RADIO_signal_EVENTS_RXREADY(unsigned int inst) {
nhw_RADIO_signal_EVENTS_RXREADY_noshort(inst);
NHW_SHORT_si(RADIO, RXREADY, START)
NHW_SHORT_si(RADIO, RXREADY, CCASTART)
}
void nhw_RADIO_signal_EVENTS_PHYEND(unsigned int inst) {
nhw_RADIO_signal_EVENTS_PHYEND_noshort(inst);
NHW_SHORT_si(RADIO, PHYEND, DISABLE)
NHW_SHORT_si(RADIO, PHYEND, START)
}
extern NRF_RADIO_Type NRF_RADIO_regs;
NHW_SIDEEFFECTS_TASKS_si(RADIO, TXEN)
NHW_SIDEEFFECTS_TASKS_si(RADIO, RXEN)
NHW_SIDEEFFECTS_TASKS_si(RADIO, START)
NHW_SIDEEFFECTS_TASKS_si(RADIO, STOP)
NHW_SIDEEFFECTS_TASKS_si(RADIO, DISABLE)
void nhw_RADIO_regw_sideeffects_TASKS_RSSISTART(void) {
//We don't need to model this yet
if ( NRF_RADIO_regs.TASKS_RSSISTART ){
NRF_RADIO_regs.TASKS_RSSISTART = 0;
bs_trace_warning_line_time("RADIO: Sampling RSSI by writing to TASK_RSSISTART register is not supported by the model yet\n");
}
}
void nhw_RADIO_regw_sideeffects_TASKS_RSSISTOP(void) {
//We don't need to model this yet
if ( NRF_RADIO_regs.TASKS_RSSISTOP ){
NRF_RADIO_regs.TASKS_RSSISTOP = 0;
bs_trace_warning_line_time("RADIO: Sampling RSSI by writing to TASK_RSSISTOP register is not supported by the model yet\n");
}
}
NHW_SIDEEFFECTS_TASKS_si(RADIO, BCSTART)
NHW_SIDEEFFECTS_TASKS_si(RADIO, BCSTOP)
NHW_SIDEEFFECTS_TASKS_si(RADIO, EDSTART)
NHW_SIDEEFFECTS_TASKS_si(RADIO, EDSTOP)
NHW_SIDEEFFECTS_TASKS_si(RADIO, CCASTART)
NHW_SIDEEFFECTS_TASKS_si(RADIO, CCASTOP)
#if (NHW_HAS_DPPI)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, TXEN)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, RXEN)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, START)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, STOP)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, DISABLE)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, RSSISTART)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, RSSISTOP)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, BCSTART)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, BCSTOP)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, EDSTART)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, EDSTOP)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, CCASTART)
NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, CCASTOP)
#endif /* NHW_HAS_DPPI */

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* Note: This header is private to the RADIO HW model
*/
#ifndef _NRF_RADIO_SIGNALS_H
#define _NRF_RADIO_SIGNALS_H
#ifdef __cplusplus
extern "C"{
#endif
void nhw_RADIO_signal_EVENTS_READY(unsigned int inst);
void nhw_RADIO_signal_EVENTS_ADDRESS(unsigned int inst);
void nhw_RADIO_signal_EVENTS_PAYLOAD(unsigned int inst);
void nhw_RADIO_signal_EVENTS_END(unsigned int inst);
void nhw_RADIO_signal_EVENTS_DISABLED(unsigned int inst);
void nhw_RADIO_signal_EVENTS_DEVMATCH(unsigned int inst);
void nhw_RADIO_signal_EVENTS_DEVMISS(unsigned int inst);
void nhw_RADIO_signal_EVENTS_RSSIEND(unsigned int inst);
void nhw_RADIO_signal_EVENTS_BCMATCH(unsigned int inst);
void nhw_RADIO_signal_EVENTS_CRCOK(unsigned int inst);
void nhw_RADIO_signal_EVENTS_CRCERROR(unsigned int inst);
void nhw_RADIO_signal_EVENTS_FRAMESTART(unsigned int inst);
void nhw_RADIO_signal_EVENTS_EDEND(unsigned int inst);
void nhw_RADIO_signal_EVENTS_EDSTOPPED(unsigned int inst);
void nhw_RADIO_signal_EVENTS_CCAIDLE(unsigned int inst);
void nhw_RADIO_signal_EVENTS_CCABUSY(unsigned int inst);
void nhw_RADIO_signal_EVENTS_CCASTOPPED(unsigned int inst);
//void nhw_RADIO_signal_EVENTS_RATEBOOST(unsigned int inst);
void nhw_RADIO_signal_EVENTS_TXREADY(unsigned int inst);
void nhw_RADIO_signal_EVENTS_RXREADY(unsigned int inst);
//void nhw_RADIO_signal_EVENTS_MHRMATCH(unsigned int inst);
void nhw_RADIO_signal_EVENTS_SYNC(unsigned int inst);
void nhw_RADIO_signal_EVENTS_PHYEND(unsigned int inst);
//void nhw_RADIO_signal_EVENTS_CTEPRESENT(unsigned int inst);
void nhwra_signalif_reset(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -13,8 +13,10 @@
#include "NHW_common_types.h"
#include "NHW_config.h"
#include "NHW_peri_types.h"
#include "NRF_RADIO.h"
#include "NRF_RADIO_utils.h"
#include "NHW_RADIO.h"
#include "NHW_RADIO_utils.h"
extern NRF_RADIO_Type NRF_RADIO_regs;
static struct {
/*Ramp up times*/
@ -77,7 +79,7 @@ void nrfra_timings_init(void) {
/**
* Return the Rx chain delay given the configured MODE
*/
bs_time_t nrfra_timings_get_Rx_chain_delay(void) {
bs_time_t nhwra_timings_get_Rx_chain_delay(void) {
int mod_idx = 0;
if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit) {
mod_idx = 1;
@ -94,7 +96,7 @@ bs_time_t nrfra_timings_get_Rx_chain_delay(void) {
* switching during its auto IFS mechanism
* returns the requested rampup time
*/
bs_time_t nrfra_timings_get_rampup_time(bool TxNotRx, bool from_hw_TIFS) {
bs_time_t nhwra_timings_get_rampup_time(bool TxNotRx, bool from_hw_TIFS) {
int fast = 0;
int mod_idx = 0;
int HWTIFS= 0;
@ -102,7 +104,7 @@ bs_time_t nrfra_timings_get_rampup_time(bool TxNotRx, bool from_hw_TIFS) {
if ( NRF_RADIO_regs.MODECNF0 & 1 ){ /* MODECNF0.RU */
fast = 1;
} else {
HWTIFS = from_hw_TIFS | nrfra_is_HW_TIFS_enabled();
HWTIFS = from_hw_TIFS | nhwra_is_HW_TIFS_enabled();
}
if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit) {
mod_idx = 1;
@ -116,11 +118,11 @@ bs_time_t nrfra_timings_get_rampup_time(bool TxNotRx, bool from_hw_TIFS) {
}
}
bs_time_t nrfra_timings_get_RX_rampdown_time(void){
bs_time_t nhwra_timings_get_RX_rampdown_time(void){
return radio_timings.RX_RD_time;
}
bs_time_t nrfra_timings_get_TX_rampdown_time(void){
bs_time_t nhwra_timings_get_TX_rampdown_time(void){
int mod_idx = 0;
if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit) {
mod_idx = 1;
@ -130,7 +132,7 @@ bs_time_t nrfra_timings_get_TX_rampdown_time(void){
return radio_timings.TX_RD_time[mod_idx];
}
bs_time_t nrfra_timings_get_TX_chain_delay(void){
bs_time_t nhwra_timings_get_TX_chain_delay(void){
return radio_timings.TX_chain_delay;
}

View File

@ -17,11 +17,11 @@ extern "C"{
#endif
void nrfra_timings_init(void);
bs_time_t nrfra_timings_get_rampup_time(bool TxNotRx, bool from_hw_TIFS);
bs_time_t nrfra_timings_get_Rx_chain_delay(void);
bs_time_t nrfra_timings_get_RX_rampdown_time(void);
bs_time_t nrfra_timings_get_TX_rampdown_time(void);
bs_time_t nrfra_timings_get_TX_chain_delay(void);
bs_time_t nhwra_timings_get_rampup_time(bool TxNotRx, bool from_hw_TIFS);
bs_time_t nhwra_timings_get_Rx_chain_delay(void);
bs_time_t nhwra_timings_get_RX_rampdown_time(void);
bs_time_t nhwra_timings_get_TX_rampdown_time(void);
bs_time_t nhwra_timings_get_TX_chain_delay(void);
#ifdef __cplusplus
}

View File

@ -15,11 +15,13 @@
#include "NHW_common_types.h"
#include "NHW_config.h"
#include "NHW_peri_types.h"
#include "NRF_RADIO.h"
#include "NHW_RADIO.h"
#include "NHW_RADIO_timings.h"
#include "NRF_HWLowL.h"
#include "NRF_RADIO_timings.h"
#include "nsi_hw_scheduler.h"
extern NRF_RADIO_Type NRF_RADIO_regs;
static void nrfra_check_crc_conf_ble(void) {
if ( (NRF_RADIO_regs.CRCCNF & RADIO_CRCCNF_LEN_Msk)
!= (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) ) {
@ -154,7 +156,7 @@ static void nrfra_check_802154_conf(void){
/*
* A few checks to ensure the model is only used with the currently supported packet format
*/
void nrfra_check_packet_conf(void){
void nhwra_check_packet_conf(void){
if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit) {
nrfra_check_ble1M_conf();
@ -169,13 +171,13 @@ void nrfra_check_packet_conf(void){
}
}
uint32_t nrfra_RSSI_value_to_modem_format(double rssi_value){
uint32_t nhwra_RSSI_value_to_modem_format(double rssi_value){
rssi_value = -BS_MAX(rssi_value,-127);
rssi_value = BS_MAX(rssi_value,0);
return (uint32_t)rssi_value;
}
uint8_t nrfra_dBm_to_modem_LQIformat(double rssi_value){
uint8_t nhwra_dBm_to_modem_LQIformat(double rssi_value){
//PRF[dBm] = ED_RSSIOFFS + VALHARDWARE
//ED_RSSIOFFS = -93
//=> VALHARDWARE = PRF[dBm] - ED_RSSIOFFS = PRF[dBm] + 93
@ -191,7 +193,7 @@ double nrfra_LQIformat_to_dBm(uint value){
return (double)value - 93;
}
int nrfra_is_HW_TIFS_enabled(void) {
int nhwra_is_HW_TIFS_enabled(void) {
if ( ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_END_DISABLE_Msk )
&& ( ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_DISABLED_RXEN_Msk )
|| ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_DISABLED_TXEN_Msk ) )
@ -208,7 +210,7 @@ int nrfra_is_HW_TIFS_enabled(void) {
*
* Note: The abort substructure is NOT filled.
*/
void nrfra_prep_rx_request(p2G4_rxv2_t *rx_req, p2G4_address_t *rx_addresses) {
void nhwra_prep_rx_request(p2G4_rxv2_t *rx_req, p2G4_address_t *rx_addresses) {
//TOLOW: Add support for other packet formats and bitrates
uint8_t preamble_length = 0;
@ -294,7 +296,7 @@ void nrfra_prep_rx_request(p2G4_rxv2_t *rx_req, p2G4_address_t *rx_addresses) {
*
* Note: The abort substructure is NOT filled.
*/
void nrfra_prep_tx_request(p2G4_txv2_t *tx_req, uint packet_size, bs_time_t packet_duration) {
void nhwra_prep_tx_request(p2G4_txv2_t *tx_req, uint packet_size, bs_time_t packet_duration) {
if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit) {
tx_req->radio_params.modulation = P2G4_MOD_BLE;
@ -346,7 +348,7 @@ void nrfra_prep_tx_request(p2G4_txv2_t *tx_req, uint packet_size, bs_time_t pack
*
* Note: The abort substructure is NOT filled.
*/
void nrfra_prep_cca_request(p2G4_cca_t *cca_req, bool CCA_not_ED) {
void nhwra_prep_cca_request(p2G4_cca_t *cca_req, bool CCA_not_ED) {
cca_req->start_time = hwll_phy_time_from_dev(nsi_hws_get_time()); //We start right now
cca_req->antenna_gain = 0;
@ -408,20 +410,20 @@ void nrfra_prep_cca_request(p2G4_cca_t *cca_req, bool CCA_not_ED) {
/**
* Return the CRC length in bytes
*/
uint nrfra_get_crc_length(void) {
uint nhwra_get_crc_length(void) {
return (NRF_RADIO_regs.CRCCNF & RADIO_CRCCNF_LEN_Msk) >> RADIO_CRCCNF_LEN_Pos;
}
uint nrfra_get_MAXLEN(void) {
return (NRF_RADIO_regs.PCNF1 & NFCT_MAXLEN_MAXLEN_Msk) >> NFCT_MAXLEN_MAXLEN_Pos;
uint nhwra_get_MAXLEN(void) {
return (NRF_RADIO_regs.PCNF1 & RADIO_PCNF1_MAXLEN_Msk) >> RADIO_PCNF1_MAXLEN_Pos;
}
/*
* Return the payload length, NOT including the CRC length
* (and NOT adding S0 or S1 lengths)
*/
uint nrfra_get_payload_length(uint8_t *buf){
uint nhwra_get_payload_length(uint8_t *buf){
int S0Len;
int LFLenb, LFLenB;
uint payload_len = 0;
@ -435,7 +437,7 @@ uint nrfra_get_payload_length(uint8_t *buf){
}
if (NRF_RADIO_regs.PCNF0 & RADIO_PCNF0_CRCINC_Msk) {
int crc_len = nrfra_get_crc_length();
int crc_len = nhwra_get_crc_length();
if (payload_len >= crc_len) {
payload_len -= crc_len;
} else {
@ -448,8 +450,8 @@ uint nrfra_get_payload_length(uint8_t *buf){
}
uint nrfra_get_capped_payload_length(uint8_t *buf) {
uint payload_lenght = nrfra_get_payload_length(buf);
uint max_length = nrfra_get_MAXLEN();
uint payload_lenght = nhwra_get_payload_length(buf);
uint max_length = nhwra_get_MAXLEN();
return BS_MIN(payload_lenght, max_length);
}
@ -459,9 +461,9 @@ uint nrfra_get_capped_payload_length(uint8_t *buf) {
* rx_buf: Pointer to the received buffer
* rx_packet_size: Number of input bytes in rx_buf
*/
uint32_t nrfra_get_rx_crc_value(uint8_t *rx_buf, size_t rx_packet_size) {
uint32_t nhwra_get_rx_crc_value(uint8_t *rx_buf, size_t rx_packet_size) {
uint32_t crc = 0;
uint crc_len = nrfra_get_crc_length();
uint crc_len = nhwra_get_crc_length();
uint payload_len = nrfra_get_capped_payload_length(rx_buf);
//Eventually this should be generalized with the packet configuration
@ -489,7 +491,7 @@ uint32_t nrfra_get_rx_crc_value(uint8_t *rx_buf, size_t rx_packet_size) {
* this needs to be reworked together with the start_Tx()
* function, as it is all way too interdependent
*/
uint nrfra_tx_copy_payload(uint8_t *tx_buf){
uint nhwra_tx_copy_payload(uint8_t *tx_buf){
int S0Len, S1LenB, LFLenB; //All in bytes
int LFLenb, S1LenAirb;
int i;
@ -527,10 +529,10 @@ uint nrfra_tx_copy_payload(uint8_t *tx_buf){
*/
}
payload_len = nrfra_get_payload_length(tx_buf);
payload_len = nhwra_get_payload_length(tx_buf);
/* Note that we assume if CRCINC=1, CRCLEN is deducted from the length field
* before capping the length to MAXLEN */
maxlen = nrfra_get_MAXLEN();
maxlen = nhwra_get_MAXLEN();
if (payload_len > maxlen) {
bs_trace_error_time_line("NRF_RADIO: Transmitting a packet longer than the configured MAXLEN (%i>%i). "
"This would truncate it and a corrupted packet will be transmitted. "

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* Note: This header is private to the RADIO HW model
*/
#ifndef _NRF_RADIO_UTILS_H
#define _NRF_RADIO_UTILS_H
#include <stdint.h>
#include "bs_pc_2G4_types.h"
#ifdef __cplusplus
extern "C"{
#endif
void nhwra_check_packet_conf(void);
uint32_t nhwra_RSSI_value_to_modem_format(double rssi_value);
uint8_t nhwra_dBm_to_modem_LQIformat(double rssi_value);
int nhwra_is_HW_TIFS_enabled(void);
void nhwra_prep_rx_request(p2G4_rxv2_t *ongoing_rx, p2G4_address_t *rx_addresses);
void nhwra_prep_tx_request(p2G4_txv2_t *ongoing_tx, uint packet_size, bs_time_t packet_duration);
void nhwra_prep_cca_request(p2G4_cca_t *cca_req, bool CCA_not_ED);
uint nhwra_tx_copy_payload(uint8_t *tx_buf);
uint nhwra_get_payload_length(uint8_t *buf);
uint32_t nhwra_get_rx_crc_value(uint8_t *rx_buf, size_t rx_packet_size);
uint nhwra_get_crc_length(void);
uint nhwra_get_MAXLEN(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -320,6 +320,11 @@
#define NHW_CORE_NAMES {"Application", "Network"}
#define NHW_RADIO_TOTAL_INST 1
#define NHW_RADIO_NET0 0
#define NHW_RADIO_INT_MAP {{1 , 8}} /*Net core,RADIO_IRQn*/
#define NHW_RADIO_DPPI_MAP {1} /*Network core*/
#define NHW_RNG_TOTAL_INST 1
#define NHW_RNG_NET_0 0
#define NHW_RNG_INT_MAP {{1, 9}} /*Network core, "RNG_IRQn"*/

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
#include "NHW_RTC.h"
#include "NHW_TIMER.h"
#include "NHW_CLOCK.h"
#include "NRF_RADIO.h"
#include "NHW_RADIO.h"
#include "NHW_EGU.h"
#include "bs_tracing.h"
#include "bs_oswrap.h"
@ -99,19 +99,19 @@ static const ppi_tasks_table_t ppi_tasks_table[]={ //just the ones we may use
{ (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_CTSTOP , nhw_clock0_TASKS_CTSTOP},
//RADIO:
{ (void*)&NRF_RADIO_regs.TASKS_TXEN, nrf_radio_tasks_TXEN},
{ (void*)&NRF_RADIO_regs.TASKS_RXEN, nrf_radio_tasks_RXEN},
{ (void*)&NRF_RADIO_regs.TASKS_START, nrf_radio_tasks_START},
{ (void*)&NRF_RADIO_regs.TASKS_STOP, nrf_radio_tasks_STOP},
{ (void*)&NRF_RADIO_regs.TASKS_DISABLE, nrf_radio_tasks_DISABLE},
{ (void*)&NRF_RADIO_regs.TASKS_RSSISTART, nrf_radio_tasks_RSSISTART},
{ (void*)&NRF_RADIO_regs.TASKS_RSSISTOP, nrf_radio_tasks_RSSISTOP},
{ (void*)&NRF_RADIO_regs.TASKS_BCSTART, nrf_radio_tasks_BCSTART},
{ (void*)&NRF_RADIO_regs.TASKS_BCSTOP, nrf_radio_tasks_BCSTOP},
{ (void*)&NRF_RADIO_regs.TASKS_EDSTART, nrf_radio_tasks_EDSTART},
{ (void*)&NRF_RADIO_regs.TASKS_EDSTOP, nrf_radio_tasks_EDSTOP},
{ (void*)&NRF_RADIO_regs.TASKS_CCASTART, nrf_radio_tasks_CCASTART},
{ (void*)&NRF_RADIO_regs.TASKS_CCASTOP, nrf_radio_tasks_CCASTOP},
{ (void*)&NRF_RADIO_regs.TASKS_TXEN, nhw_RADIO_TASK_TXEN},
{ (void*)&NRF_RADIO_regs.TASKS_RXEN, nhw_RADIO_TASK_RXEN},
{ (void*)&NRF_RADIO_regs.TASKS_START, nhw_RADIO_TASK_START},
{ (void*)&NRF_RADIO_regs.TASKS_STOP, nhw_RADIO_TASK_STOP},
{ (void*)&NRF_RADIO_regs.TASKS_DISABLE, nhw_RADIO_TASK_DISABLE},
{ (void*)&NRF_RADIO_regs.TASKS_RSSISTART, nhw_RADIO_TASK_RSSISTART},
{ (void*)&NRF_RADIO_regs.TASKS_RSSISTOP, nhw_RADIO_TASK_RSSISTOP},
{ (void*)&NRF_RADIO_regs.TASKS_BCSTART, nhw_RADIO_TASK_BCSTART},
{ (void*)&NRF_RADIO_regs.TASKS_BCSTOP, nhw_RADIO_TASK_BCSTOP},
{ (void*)&NRF_RADIO_regs.TASKS_EDSTART, nhw_RADIO_TASK_EDSTART},
{ (void*)&NRF_RADIO_regs.TASKS_EDSTOP, nhw_RADIO_TASK_EDSTOP},
{ (void*)&NRF_RADIO_regs.TASKS_CCASTART, nhw_RADIO_TASK_CCASTART},
{ (void*)&NRF_RADIO_regs.TASKS_CCASTOP, nhw_RADIO_TASK_CCASTOP},
//UART
//SPI0
//TWI0
@ -565,15 +565,15 @@ static void set_fixed_channel_routes(void) {
//Set the fixed channels configuration:
// 20 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 20 );
ppi_ch_tasks[20].tep_f = nrf_radio_tasks_TXEN; //RADIO->TASKS_TXEN
ppi_ch_tasks[20].tep_f = nhw_RADIO_TASK_TXEN; //RADIO->TASKS_TXEN
// 21 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 21 );
ppi_ch_tasks[21].tep_f = nrf_radio_tasks_RXEN; //RADIO->TASKS_RXEN
ppi_ch_tasks[21].tep_f = nhw_RADIO_TASK_RXEN; //RADIO->TASKS_RXEN
// 22 TIMER0->EVENTS_COMPARE[1] RADIO->TASKS_DISABLE
ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_1].channels_mask |= ( 1 << 22 );
ppi_ch_tasks[22].tep_f = nrf_radio_tasks_DISABLE; //RADIO->TASKS_DISABLE
ppi_ch_tasks[22].tep_f = nhw_RADIO_TASK_DISABLE; //RADIO->TASKS_DISABLE
// 23 RADIO->EVENTS_BCMATCH AAR->TASKS_START
ppi_evt_to_ch[RADIO_EVENTS_BCMATCH].channels_mask |= ( 1 << 23 );
@ -597,11 +597,11 @@ static void set_fixed_channel_routes(void) {
// 28 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 28 );
ppi_ch_tasks[28].tep_f = nrf_radio_tasks_TXEN; //RADIO->TASKS_TXEN
ppi_ch_tasks[28].tep_f = nhw_RADIO_TASK_TXEN; //RADIO->TASKS_TXEN
// 29 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 29 );
ppi_ch_tasks[29].tep_f = nrf_radio_tasks_RXEN; //RADIO->TASKS_RXEN
ppi_ch_tasks[29].tep_f = nhw_RADIO_TASK_RXEN; //RADIO->TASKS_RXEN
// 30 RTC0->EVENTS_COMPARE[0] TIMER0->TASKS_CLEAR
ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 30 );

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2017 Oticon A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _NRF_RADIO_H
#define _NRF_RADIO_H
#ifdef __cplusplus
extern "C"{
#endif
void nrf_radio_tasks_TXEN(void);
void nrf_radio_tasks_RXEN(void);
void nrf_radio_tasks_START(void);
void nrf_radio_tasks_CCASTART(void);
void nrf_radio_tasks_CCASTOP(void);
void nrf_radio_tasks_EDSTART(void);
void nrf_radio_tasks_EDSTOP(void);
void nrf_radio_tasks_STOP() ;
void nrf_radio_tasks_DISABLE(void);
void nrf_radio_tasks_RSSISTART(void);
void nrf_radio_tasks_RSSISTOP(void);
void nrf_radio_tasks_BCSTART(void);
void nrf_radio_tasks_BCSTOP(void);
void nrf_radio_regw_sideeffects_BCC(void);
void nrf_radio_regw_sideeffects_POWER(void);
void nrf_radio_regw_sideeffects_TASKS_TXEN(void);
void nrf_radio_regw_sideeffects_TASKS_RXEN(void);
void nrf_radio_regw_sideeffects_TASKS_START(void);
void nrf_radio_regw_sideeffects_TASKS_STOP(void);
void nrf_radio_regw_sideeffects_TASKS_DISABLE(void);
void nrf_radio_regw_sideeffects_TASKS_RSSISTART(void);
void nrf_radio_regw_sideeffects_TASKS_RSSISTOP(void);
void nrf_radio_regw_sideeffects_TASKS_BCSTART(void);
void nrf_radio_regw_sideeffects_TASKS_BCSTOP(void);
void nrf_radio_regw_sideeffects_TASKS_EDSTART(void);
void nrf_radio_regw_sideeffects_TASKS_EDSTOP(void);
void nrf_radio_regw_sideeffects_TASKS_CCASTART(void);
void nrf_radio_regw_sideeffects_TASKS_CCASTOP(void);
void nrf_radio_regw_sideeffects_INTENSET(void);
void nrf_radio_regw_sideeffects_INTENCLR(void);
/*
* Internal interface to bitcounter
*/
double nrf_radio_get_bpus(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,354 +0,0 @@
/*
* Copyright (c) 2017 Oticon A/S
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* This file includes the RADIO event & signals functionality
* That is, when a signal is generated:
* Setting the EVENTS registers
* Sending the signal to the PPI
* Generating the corresponding interrupts
* Calling tasks if the corresponding shortcuts are enabled
*
* There should not be any logic beyond that here.
*/
#include "NHW_common_types.h"
#include "NHW_config.h"
#include "NHW_peri_types.h"
#include "NRF_RADIO.h"
#include "NRF_RADIO_utils.h"
#include "NRF_PPI.h"
#include "irq_ctrl.h"
#include "bs_tracing.h"
extern uint32_t NRF_RADIO_INTEN; //interrupt enable
/* Mapping of peripheral instance to {int controller instance, int number} */
static struct nhw_irq_mapping nhw_radio_irq_map[NHW_RADIO_TOTAL_INST] = NHW_RADIO_INT_MAP;
extern void nrf_radio_fake_task_TRXEN_TIFS(void);
void nrf_radio_signal_READY(void) {
NRF_RADIO_regs.EVENTS_READY = 1;
nrf_ppi_event(RADIO_EVENTS_READY);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_READY_START_Msk ) {
nrf_radio_tasks_START();
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_READY_EDSTART_Msk ) {
nrf_radio_tasks_EDSTART();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_READY_Msk ){
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_ADDRESS(void) {
NRF_RADIO_regs.EVENTS_ADDRESS = 1;
nrf_ppi_event(RADIO_EVENTS_ADDRESS);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_ADDRESS_RSSISTART_Msk ) {
nrf_radio_tasks_RSSISTART();
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_ADDRESS_BCSTART_Msk ) {
nrf_radio_tasks_BCSTART();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_ADDRESS_Msk ){
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_PAYLOAD(void) {
NRF_RADIO_regs.EVENTS_PAYLOAD = 1;
nrf_ppi_event(RADIO_EVENTS_PAYLOAD);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_PAYLOAD_Msk ){
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_END(void) {
NRF_RADIO_regs.EVENTS_END = 1;
nrf_ppi_event(RADIO_EVENTS_END);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_END_DISABLE_Msk ) {
nrf_radio_tasks_DISABLE();
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_END_START_Msk ) {
nrf_radio_tasks_START();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_END_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_DISABLED(void) {
NRF_RADIO_regs.EVENTS_DISABLED = 1;
nrf_ppi_event(RADIO_EVENTS_DISABLED);
/*
* Everything indicates that, when the HW TIFS is enabled
* what happens is that these DISABLED_[TR]XEN shorts are
* effectively disabled and the tasks_[TR]XEN is instead
* triggered when a HW counter/timer triggers a bit later
*/
if (nrfra_is_HW_TIFS_enabled()) {
/* This is a fake task meant to start a HW timer for the TIFS
* which has effect only if the TIFS was enabled.
* In that case, the TXEN or RXEN will be triggered in a small
* while (as per the TIFS configuration/Timer_TIFS), instead of right now */
nrf_radio_fake_task_TRXEN_TIFS();
} else {
/* Otherwise the normal TXEN/RXEN shortcuts apply */
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_DISABLED_TXEN_Msk ) {
nrf_radio_tasks_TXEN();
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_DISABLED_RXEN_Msk ) {
nrf_radio_tasks_RXEN();
}
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_DISABLED_RSSISTOP_Msk ) {
nrf_radio_tasks_RSSISTOP();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_DISABLED_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_DEVMATCH(void) {
NRF_RADIO_regs.EVENTS_DEVMATCH = 1;
nrf_ppi_event(RADIO_EVENTS_DEVMATCH);
if (NRF_RADIO_INTEN & RADIO_INTENSET_DEVMATCH_Msk) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_DEVMISS(void) {
NRF_RADIO_regs.EVENTS_DEVMISS = 1;
nrf_ppi_event(RADIO_EVENTS_DEVMISS);
if (NRF_RADIO_INTEN & RADIO_INTENSET_DEVMISS_Msk) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_RSSIEND(void) {
NRF_RADIO_regs.EVENTS_RSSIEND = 1;
nrf_ppi_event(RADIO_EVENTS_RSSIEND);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_RSSIEND_Msk ){
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_BCMATCH(void) {
NRF_RADIO_regs.EVENTS_BCMATCH = 1;
nrf_ppi_event(RADIO_EVENTS_BCMATCH);
if (NRF_RADIO_INTEN & RADIO_INTENSET_BCMATCH_Msk) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_CRCOK(void) {
NRF_RADIO_regs.EVENTS_CRCOK = 1;
nrf_ppi_event(RADIO_EVENTS_CRCOK);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_CRCOK_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_CRCERROR(void) {
NRF_RADIO_regs.EVENTS_CRCERROR = 1;
nrf_ppi_event(RADIO_EVENTS_CRCERROR);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_CRCERROR_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_FRAMESTART(void) {
NRF_RADIO_regs.EVENTS_FRAMESTART = 1;
nrf_ppi_event(RADIO_EVENTS_FRAMESTART);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_FRAMESTART_BCSTART_Msk ) {
nrf_radio_tasks_BCSTART();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_FRAMESTART_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_EDEND(void) {
NRF_RADIO_regs.EVENTS_EDEND = 1;
nrf_ppi_event(RADIO_EVENTS_EDEND);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_EDEND_DISABLE_Msk ) {
nrf_radio_tasks_DISABLE();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_EDEND_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_EDSTOPPED(void) {
NRF_RADIO_regs.EVENTS_EDSTOPPED = 1;
nrf_ppi_event(RADIO_EVENTS_EDSTOPPED);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_EDSTOPPED_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_CCAIDLE(void) {
NRF_RADIO_regs.EVENTS_CCAIDLE = 1;
nrf_ppi_event(RADIO_EVENTS_CCAIDLE);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_CCAIDLE_STOP_Msk ) {
nrf_radio_tasks_STOP();
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_CCAIDLE_TXEN_Msk ) {
nrf_radio_tasks_TXEN();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_CCAIDLE_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_CCABUSY(void) {
NRF_RADIO_regs.EVENTS_CCABUSY = 1;
nrf_ppi_event(RADIO_EVENTS_CCABUSY);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_CCABUSY_DISABLE_Msk ) {
nrf_radio_tasks_DISABLE();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_CCABUSY_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_CCASTOPPED(void) {
NRF_RADIO_regs.EVENTS_CCASTOPPED = 1;
nrf_ppi_event(RADIO_EVENTS_CCASTOPPED);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_CCASTOPPED_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_RATEBOOST(void) {
NRF_RADIO_regs.EVENTS_RATEBOOST = 1;
nrf_ppi_event(RADIO_EVENTS_RATEBOOST);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_RATEBOOST_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_TXREADY(void) {
NRF_RADIO_regs.EVENTS_TXREADY = 1;
nrf_ppi_event(RADIO_EVENTS_TXREADY);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_TXREADY_START_Msk ) {
nrf_radio_tasks_START();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_TXREADY_Msk ){
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_RXREADY(void) {
NRF_RADIO_regs.EVENTS_RXREADY = 1;
nrf_ppi_event(RADIO_EVENTS_RXREADY);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_RXREADY_START_Msk ) {
nrf_radio_tasks_START();
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_RXREADY_CCASTART_Msk ) {
nrf_radio_tasks_CCASTART();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_RXREADY_Msk ){
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_MHRMATCH(void) {
NRF_RADIO_regs.EVENTS_MHRMATCH = 1;
nrf_ppi_event(RADIO_EVENTS_MHRMATCH);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_MHRMATCH_Msk ){
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_SYNC(void) {
NRF_RADIO_regs.EVENTS_SYNC = 1;
nrf_ppi_event(RADIO_EVENTS_SYNC);
if (NRF_RADIO_INTEN & RADIO_INTENSET_SYNC_Msk) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_PHYEND(void) {
NRF_RADIO_regs.EVENTS_PHYEND = 1;
nrf_ppi_event(RADIO_EVENTS_PHYEND);
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_PHYEND_DISABLE_Msk ) {
nrf_radio_tasks_DISABLE();
}
if ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_PHYEND_START_Msk ) {
nrf_radio_tasks_START();
}
if ( NRF_RADIO_INTEN & RADIO_INTENSET_PHYEND_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}
void nrf_radio_signal_CTEPRESENT(void) {
NRF_RADIO_regs.EVENTS_CTEPRESENT = 1;
nrf_ppi_event(RADIO_EVENTS_CTEPRESENT);
if ( NRF_RADIO_INTEN & RADIO_INTENSET_CTEPRESENT_Msk ) {
hw_irq_ctrl_set_irq(nhw_radio_irq_map[0].cntl_inst,
nhw_radio_irq_map[0].int_nbr);
}
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* Note: This header is private to the RADIO HW model
*/
#ifndef _NRF_RADIO_SIGNALS_H
#define _NRF_RADIO_SIGNALS_H
#ifdef __cplusplus
extern "C"{
#endif
void nrf_radio_signal_READY(void);
void nrf_radio_signal_ADDRESS(void);
void nrf_radio_signal_PAYLOAD(void);
void nrf_radio_signal_END(void);
void nrf_radio_signal_DISABLED(void);
void nrf_radio_signal_DEVMATCH(void);
void nrf_radio_signal_DEVMISS(void);
void nrf_radio_signal_RSSIEND(void);
void nrf_radio_signal_BCMATCH(void);
void nrf_radio_signal_CRCOK(void);
void nrf_radio_signal_CRCERROR(void);
void nrf_radio_signal_FRAMESTART(void);
void nrf_radio_signal_EDEND(void);
void nrf_radio_signal_EDSTOPPED(void);
void nrf_radio_signal_CCAIDLE(void);
void nrf_radio_signal_CCABUSY(void);
void nrf_radio_signal_CCASTOPPED(void);
//void nrf_radio_signal_RATEBOOST(void);
void nrf_radio_signal_TXREADY(void);
void nrf_radio_signal_RXREADY(void);
//void nrf_radio_signal_MHRMATCH(void);
void nrf_radio_signal_SYNC(void);
void nrf_radio_signal_PHYEND(void);
//void nrf_radio_signal_CTEPRESENT(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2017 Oticon A/S
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* This file includes the RADIO TASKS registers side-effecting functions
* The actual tasks logic does not below here.
*/
#include "NHW_common_types.h"
#include "NHW_config.h"
#include "NHW_peri_types.h"
#include "NRF_RADIO.h"
#include "bs_tracing.h"
#define RADIO_TASK_SIDEFFECT_FUNC(x) \
void nrf_radio_regw_sideeffects_TASKS_##x() { \
if (NRF_RADIO_regs.TASKS_##x ) { \
NRF_RADIO_regs.TASKS_##x = 0; \
nrf_radio_tasks_##x(); \
}\
}
RADIO_TASK_SIDEFFECT_FUNC(TXEN)
RADIO_TASK_SIDEFFECT_FUNC(RXEN)
RADIO_TASK_SIDEFFECT_FUNC(START)
RADIO_TASK_SIDEFFECT_FUNC(STOP)
RADIO_TASK_SIDEFFECT_FUNC(DISABLE)
void nrf_radio_regw_sideeffects_TASKS_RSSISTART(void) {
//We don't need to model this yet
if ( NRF_RADIO_regs.TASKS_RSSISTART ){
NRF_RADIO_regs.TASKS_RSSISTART = 0;
bs_trace_warning_line_time("RADIO: Sampling RSSI by writing to TASK_RSSISTART register is not supported by the model yet\n");
}
}
void nrf_radio_regw_sideeffects_TASKS_RSSISTOP(void) {
//We don't need to model this yet
if ( NRF_RADIO_regs.TASKS_RSSISTOP ){
NRF_RADIO_regs.TASKS_RSSISTOP = 0;
bs_trace_warning_line_time("RADIO: Sampling RSSI by writing to TASK_RSSISTOP register is not supported by the model yet\n");
}
}
RADIO_TASK_SIDEFFECT_FUNC(BCSTART)
RADIO_TASK_SIDEFFECT_FUNC(BCSTOP)
RADIO_TASK_SIDEFFECT_FUNC(EDSTART)
RADIO_TASK_SIDEFFECT_FUNC(EDSTOP)
RADIO_TASK_SIDEFFECT_FUNC(CCASTART)
RADIO_TASK_SIDEFFECT_FUNC(CCASTOP)

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* Note: This header is private to the RADIO HW model
*/
#ifndef _NRF_RADIO_UTILS_H
#define _NRF_RADIO_UTILS_H
#include <stdint.h>
#include "bs_pc_2G4_types.h"
#ifdef __cplusplus
extern "C"{
#endif
void nrfra_check_packet_conf(void);
uint32_t nrfra_RSSI_value_to_modem_format(double rssi_value);
uint8_t nrfra_dBm_to_modem_LQIformat(double rssi_value);
int nrfra_is_HW_TIFS_enabled(void);
void nrfra_prep_rx_request(p2G4_rxv2_t *ongoing_rx, p2G4_address_t *rx_addresses);
void nrfra_prep_tx_request(p2G4_txv2_t *ongoing_tx, uint packet_size, bs_time_t packet_duration);
void nrfra_prep_cca_request(p2G4_cca_t *cca_req, bool CCA_not_ED);
uint nrfra_tx_copy_payload(uint8_t *tx_buf);
uint nrfra_get_payload_length(uint8_t *buf);
uint32_t nrfra_get_rx_crc_value(uint8_t *rx_buf, size_t rx_packet_size);
uint nrfra_get_crc_length(void);
uint nrfra_get_MAXLEN(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2017 Oticon A/S
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
@ -7,7 +8,7 @@
*/
#include "hal/nrf_radio.h"
#include "bs_tracing.h"
#include "NRF_RADIO.h"
#include "NHW_RADIO.h"
void nrf_radio_task_trigger(NRF_RADIO_Type * p_reg, nrf_radio_task_t task)
{
@ -15,7 +16,7 @@ void nrf_radio_task_trigger(NRF_RADIO_Type * p_reg, nrf_radio_task_t task)
#define CASE_CALL_SIDEEFFECT(x) \
case NRF_RADIO_TASK_##x :\
nrf_radio_regw_sideeffects_TASKS_##x();\
nhw_RADIO_regw_sideeffects_TASKS_##x();\
break
switch (task) {
@ -36,28 +37,87 @@ void nrf_radio_task_trigger(NRF_RADIO_Type * p_reg, nrf_radio_task_t task)
bs_trace_error_line_time("%s: Not supported task %i started\n", __func__, task);
break;
}
#undef CASE_CALL_SIDEEFFECT
}
void nrf_radio_int_enable(NRF_RADIO_Type * p_reg, uint32_t mask)
{
p_reg->INTENSET = mask;
nrf_radio_regw_sideeffects_INTENSET();
nhw_RADIO_regw_sideeffects_INTENSET();
}
void nrf_radio_int_disable(NRF_RADIO_Type * p_reg, uint32_t mask)
{
p_reg->INTENCLR = mask;
nrf_radio_regw_sideeffects_INTENCLR();
nhw_RADIO_regw_sideeffects_INTENCLR();
}
void nrf_radio_bcc_set(NRF_RADIO_Type * p_reg, uint32_t radio_bcc)
{
p_reg->BCC = radio_bcc;
nrf_radio_regw_sideeffects_BCC();
nhw_RADIO_regw_sideeffects_BCC();
}
void nrf_radio_power_set(NRF_RADIO_Type * p_reg, bool radio_power)
{
p_reg->POWER = (uint32_t) radio_power;
nrf_radio_regw_sideeffects_POWER();
nhw_RADIO_regw_sideeffects_POWER();
}
void nrf_radio_event_clear(NRF_RADIO_Type * p_reg, nrf_radio_event_t event)
{
*((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
nhw_RADIO_regw_sideeffects_EVENTS_all(0);
}
#if defined(DPPI_PRESENT)
static void nrf_radio_subscribe_common(NRF_RADIO_Type * p_reg,
nrf_radio_task_t task)
{
#define CASE_CALL_SIDEEFFECT(x) \
case NRF_RADIO_TASK_##x :\
nhw_RADIO_regw_sideeffects_SUBSCRIBE_##x(0);\
break
switch (task) {
CASE_CALL_SIDEEFFECT(TXEN);
CASE_CALL_SIDEEFFECT(RXEN);
CASE_CALL_SIDEEFFECT(START);
CASE_CALL_SIDEEFFECT(STOP);
CASE_CALL_SIDEEFFECT(DISABLE);
CASE_CALL_SIDEEFFECT(RSSISTART);
CASE_CALL_SIDEEFFECT(RSSISTOP);
CASE_CALL_SIDEEFFECT(BCSTART);
CASE_CALL_SIDEEFFECT(BCSTOP);
CASE_CALL_SIDEEFFECT(EDSTART);
CASE_CALL_SIDEEFFECT(EDSTOP);
CASE_CALL_SIDEEFFECT(CCASTART);
CASE_CALL_SIDEEFFECT(CCASTOP);
default:
bs_trace_error_line_time("%s: Attempted to subscribe to a not-supported task in the nrf_radio (%i)\n",
__func__, task);
break;
}
#undef CASE_CALL_SIDEEFFECT
}
void nrf_radio_subscribe_set(NRF_RADIO_Type * p_reg,
nrf_radio_task_t task,
uint8_t channel)
{
*((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + NRF_RADIO_DPPI_OFFSET)) =
((uint32_t)channel | NRF_SUBSCRIBE_PUBLISH_ENABLE);
nrf_radio_subscribe_common(p_reg, task);
}
void nrf_radio_subscribe_clear(NRF_RADIO_Type * p_reg,
nrf_radio_task_t task)
{
*((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + NRF_RADIO_DPPI_OFFSET)) = 0;
nrf_radio_subscribe_common(p_reg, task);
}
#endif /* defined(DPPI_PRESENT) */

View File

@ -122,8 +122,9 @@ extern NRF_RESET_Type *NRF_RESET_regs[];
#define NRF_RESET_NS_BASE (NRF_RESET_regs[NHW_CLKPWR_NET0])
#undef NRF_CTRLAP_NS_BASE
#define NRF_CTRLAP_NS_BASE NULL
extern NRF_RADIO_Type NRF_RADIO_regs;
#undef NRF_RADIO_NS_BASE
#define NRF_RADIO_NS_BASE NULL
#define NRF_RADIO_NS_BASE (&NRF_RADIO_regs)
extern NRF_RNG_Type NRF_RNG_regs;
#undef NRF_RNG_NS_BASE
#define NRF_RNG_NS_BASE (&NRF_RNG_regs)