Skip to content

Commit

Permalink
Merge pull request #218 from aabadie/nrf53_refactor_clock
Browse files Browse the repository at this point in the history
nrf53: rework clock handling and ipc mechanism
  • Loading branch information
aabadie authored Sep 7, 2023
2 parents ff73d86 + 90e9b8c commit fd64d80
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 269 deletions.
5 changes: 2 additions & 3 deletions bsp/bsp.emProject
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Name="Common"
project_directory="."
project_type="Library" />
<file file_name="nrf/$(ClockImplementationFile)" />
<file file_name="nrf/clock.c" />
<file file_name="clock.h" />
</project>
<project Name="00bsp_dotbot_board">
Expand Down Expand Up @@ -103,7 +103,7 @@
<project Name="00bsp_radio">
<configuration
Name="Common"
project_dependencies="00bsp_clock;00bsp_timer_hf(bsp)"
project_dependencies="00bsp_clock"
project_directory="."
project_type="Library" />
<file file_name="nrf/$(RadioImplementationFile)" />
Expand All @@ -112,7 +112,6 @@
<project Name="00bsp_rng">
<configuration
Name="Common"
project_dependencies="00bsp_timer_hf(bsp)"
project_directory="."
project_type="Library" />
<file file_name="nrf/$(RngImplementationFile)" />
Expand Down
6 changes: 5 additions & 1 deletion bsp/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
* @copyright Inria, 2022
*/

#if defined(NRF5340_XXAA) && defined(NRF_APPLICATION)
#if defined(NRF5340_XXAA)
#if defined(NRF_APPLICATION)
#define NRF_CLOCK NRF_CLOCK_S
#else
#define NRF_CLOCK NRF_CLOCK_NS
#endif
#endif

/**
Expand Down
70 changes: 34 additions & 36 deletions bsp/ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,22 @@
#define IPC_IRQ_PRIORITY (1)

typedef enum {
DB_IPC_NONE, ///< Sorry, but nothing
DB_IPC_NET_READY_ACK, ///< Network core is ready
DB_IPC_REQ_NONE, ///< Sorry, but nothing
DB_IPC_RADIO_INIT_REQ, ///< Request for radio initialization
DB_IPC_RADIO_INIT_ACK, ///< Acknowledment for radio initialization
DB_IPC_RADIO_FREQ_REQ, ///< Request for radio set frequency
DB_IPC_RADIO_FREQ_ACK, ///< Acknowledment for radio set frequency
DB_IPC_RADIO_CHAN_REQ, ///< Request for radio set channel
DB_IPC_RADIO_CHAN_ACK, ///< Acknowledment for radio set channel
DB_IPC_RADIO_ADDR_REQ, ///< Request for radio set network address
DB_IPC_RADIO_ADDR_ACK, ///< Acknowledment for radio set network address
DB_IPC_RADIO_RX_REQ, ///< Request for radio rx
DB_IPC_RADIO_RX_ACK, ///< Acknowledment for radio rx
DB_IPC_RADIO_DIS_REQ, ///< Request for radio disable
DB_IPC_RADIO_DIS_ACK, ///< Acknowledment for radio disable
DB_IPC_RADIO_TX_REQ, ///< Request for radio tx
DB_IPC_RADIO_TX_ACK, ///< Acknowledment for radio tx
DB_IPC_RADIO_RSSI_REQ, ///< Request for RSSI
DB_IPC_RADIO_RSSI_ACK, ///< Acknowledment for RSSI
DB_IPC_RNG_INIT_REQ, ///< Request for rng init
DB_IPC_RNG_INIT_ACK, ///< Acknowledment for rng init
DB_IPC_RNG_READ_REQ, ///< Request for rng read
DB_IPC_RNG_READ_ACK, ///< Acknowledment for rng read
} ipc_event_type_t;
} ipc_req_t;

typedef enum {
DB_IPC_CHAN_REQ = 0, ///< Channel used for request events
DB_IPC_CHAN_ACK = 1, ///< Channel used for acknownlegment events
DB_IPC_CHAN_RADIO_RX = 2, ///< Channel used for radio RX events
DB_IPC_CHAN_RADIO_RX = 1, ///< Channel used for radio RX events
} ipc_channels_t;

typedef struct __attribute__((packed)) {
Expand All @@ -77,11 +65,18 @@ typedef struct {
} ipc_rng_data_t;

typedef struct __attribute__((packed)) {
ipc_event_type_t event; ///< IPC event
ipc_radio_data_t radio; ///< Radio shared data
ipc_rng_data_t rng; ///< Rng share data
bool net_ready; ///< Network core is ready
bool net_ack; ///< Network core acked the latest request
ipc_req_t req; ///< IPC network request
ipc_radio_data_t radio; ///< Radio shared data
ipc_rng_data_t rng; ///< Rng share data
} ipc_shared_data_t;

/**
* @brief Variable in RAM containing the shared data structure
*/
volatile __attribute__((section(".ARM.__at_0x20004000"))) ipc_shared_data_t ipc_shared_data;

/**
* @brief Lock the mutex, blocks until the mutex is locked
*/
Expand All @@ -97,25 +92,28 @@ static inline void mutex_unlock(void) {
}

#if defined(NRF_APPLICATION)
static inline void power_on_network_core(void) {
NRF_POWER_S->TASKS_CONSTLAT = 1;
*(volatile uint32_t *)0x50005618ul = 1ul;
NRF_RESET_S->NETWORK.FORCEOFF = (RESET_NETWORK_FORCEOFF_FORCEOFF_Release << RESET_NETWORK_FORCEOFF_FORCEOFF_Pos);
db_timer_hf_delay_us(5); // Wait for at least five microseconds
NRF_RESET_S->NETWORK.FORCEOFF = (RESET_NETWORK_FORCEOFF_FORCEOFF_Hold << RESET_NETWORK_FORCEOFF_FORCEOFF_Pos);
db_timer_hf_delay_us(1); // Wait for at least one microsecond
NRF_RESET_S->NETWORK.FORCEOFF = (RESET_NETWORK_FORCEOFF_FORCEOFF_Release << RESET_NETWORK_FORCEOFF_FORCEOFF_Pos);
*(volatile uint32_t *)0x50005618ul = 0ul;
}

static inline bool is_network_core_powered_on(void) {
return NRF_RESET_S->NETWORK.FORCEOFF == (RESET_NETWORK_FORCEOFF_FORCEOFF_Release << RESET_NETWORK_FORCEOFF_FORCEOFF_Pos);
static inline void db_ipc_network_call(ipc_req_t req) {
if (req != DB_IPC_REQ_NONE) {
ipc_shared_data.req = req;
NRF_IPC_S->TASKS_SEND[DB_IPC_CHAN_REQ] = 1;
}
while (!ipc_shared_data.net_ack) {}
ipc_shared_data.net_ack = false;
};

static inline void release_network_core(void) {
// Do nothing if network core is already started and ready
if (!NRF_RESET_S->NETWORK.FORCEOFF && ipc_shared_data.net_ready) {
return;
} else if (!NRF_RESET_S->NETWORK.FORCEOFF) {
ipc_shared_data.net_ready = false;
}

NRF_POWER_S->TASKS_CONSTLAT = 1;
NRF_RESET_S->NETWORK.FORCEOFF = (RESET_NETWORK_FORCEOFF_FORCEOFF_Release << RESET_NETWORK_FORCEOFF_FORCEOFF_Pos);

while (!ipc_shared_data.net_ready) {}
}
#endif

/**
* @brief Variable in RAM containing the shared data structure
*/
volatile __attribute__((section(".ARM.__at_0x20004000"))) ipc_shared_data_t ipc_shared_data;

#endif
14 changes: 11 additions & 3 deletions bsp/nrf/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ void db_hfclk_init(void) {
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 1) {}

#if defined(NRF5340_XXAA)
#if defined(NRF_APPLICATION)
// Configure the 32MHz internal capacitance value (taken from crystal specs)
const uint32_t slope_sign = ((FICR_XOSC32MTRIM_SLOPE_Msk >> FICR_XOSC32MTRIM_SLOPE_Pos) - ((FICR_XOSC32MTRIM_SLOPE_Msk >> FICR_XOSC32MTRIM_SLOPE_Pos) >> 1));
const int32_t slope = (int32_t)(((NRF_FICR_S->XOSC32MTRIM & FICR_XOSC32MTRIM_SLOPE_Msk) >> FICR_XOSC32MTRIM_SLOPE_Pos) ^ slope_sign) - (int32_t)slope_sign;
const uint32_t offset = (uint32_t)(NRF_FICR_S->XOSC32MTRIM & FICR_XOSC32MTRIM_OFFSET_Msk) >> FICR_XOSC32MTRIM_OFFSET_Pos;
const uint32_t cap_value = ((((slope + 56) * (NRF53_XOSC32_CAPACITANCE_X2 - 14)) + ((offset - 8) << 4) + 32) >> 6);
NRF_OSCILLATORS_S->XOSC32MCAPS = (OSCILLATORS_XOSC32MCAPS_ENABLE_Enabled << OSCILLATORS_XOSC32MCAPS_ENABLE_Pos) | cap_value;
NRF_CLOCK->HFCLKSRC = CLOCK_HFCLKSRC_SRC_HFXO << CLOCK_HFCLKSRC_SRC_Pos;
#endif
NRF_CLOCK->HFCLKSRC = CLOCK_HFCLKSRC_SRC_HFXO << CLOCK_HFCLKSRC_SRC_Pos;
// Enable 128MHZ core clock, only possible with application core
NRF_CLOCK->HFCLKCTRL = CLOCK_HFCLKCTRL_HCLK_Div1 << CLOCK_HFCLKCTRL_HCLK_Pos;
#endif
Expand All @@ -69,7 +71,9 @@ void db_lfclk_init(void) {
}

NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;

#if defined(NRF5340_XXAA)
#if defined(NRF_APPLICATION)
// To use LFXO, P0.0 and P0.1 must use value Peripheral in MCUSEL bitfield
NRF_P0_S->PIN_CNF[0] = GPIO_PIN_CNF_MCUSEL_Peripheral << GPIO_PIN_CNF_MCUSEL_Pos;
NRF_P0_S->PIN_CNF[1] = GPIO_PIN_CNF_MCUSEL_Peripheral << GPIO_PIN_CNF_MCUSEL_Pos;
Expand All @@ -82,9 +86,13 @@ void db_lfclk_init(void) {
#endif

NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_LFXO << CLOCK_LFCLKSRC_SRC_Pos);
#else
#else // NRF_NETWORK use internal RC oscillator
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_LFRC << CLOCK_LFCLKSRC_SRC_Pos);
#endif // defined(NRF_APPLICATION)
#else // nrf52
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
#endif
#endif // defined(NRF5340_XXAA)

NRF_CLOCK->TASKS_LFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {}
_clock_state.lf_enabled = true;
Expand Down
35 changes: 0 additions & 35 deletions bsp/nrf/clock_nrf5340_net.c

This file was deleted.

67 changes: 10 additions & 57 deletions bsp/nrf/radio_nrf5340_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,9 @@

static radio_cb_t _radio_callback = NULL;

static bool _ack_received[] = {
[DB_IPC_NET_READY_ACK] = false,
[DB_IPC_RADIO_INIT_ACK] = false,
[DB_IPC_RADIO_FREQ_ACK] = false,
[DB_IPC_RADIO_CHAN_ACK] = false,
[DB_IPC_RADIO_ADDR_ACK] = false,
[DB_IPC_RADIO_RX_ACK] = false,
[DB_IPC_RADIO_DIS_ACK] = false,
[DB_IPC_RADIO_TX_ACK] = false,
[DB_IPC_RADIO_RSSI_ACK] = false,
[DB_IPC_RNG_INIT_ACK] = false,
[DB_IPC_RNG_READ_ACK] = false,
};

//========================== functions =========================================

static inline void _network_call(ipc_event_type_t req, ipc_event_type_t ack) {
if (req != DB_IPC_NONE) {
ipc_shared_data.event = req;
NRF_IPC_S->TASKS_SEND[DB_IPC_CHAN_REQ] = 1;
mutex_unlock();
}
while (!_ack_received[ack]) {}
_ack_received[ack] = false;
}

//=========================== public ===========================================

void db_radio_init(radio_cb_t callback, db_radio_ble_mode_t mode) {
// On nrf53 configure constant latency mode for better performances
NRF_POWER_S->TASKS_CONSTLAT = 1;

db_hfclk_init();

// Disable all DCDC regulators (use LDO)
Expand Down Expand Up @@ -85,80 +56,62 @@ void db_radio_init(radio_cb_t callback, db_radio_ble_mode_t mode) {
SPU_RAMREGION_PERM_WRITE_Enable << SPU_RAMREGION_PERM_WRITE_Pos |
SPU_RAMREGION_PERM_SECATTR_Non_Secure << SPU_RAMREGION_PERM_SECATTR_Pos);

NRF_IPC_S->INTENSET = (1 << DB_IPC_CHAN_ACK | 1 << DB_IPC_CHAN_RADIO_RX);
NRF_IPC_S->INTENSET = 1 << DB_IPC_CHAN_RADIO_RX;
NRF_IPC_S->SEND_CNF[DB_IPC_CHAN_REQ] = 1 << DB_IPC_CHAN_REQ;
NRF_IPC_S->RECEIVE_CNF[DB_IPC_CHAN_ACK] = 1 << DB_IPC_CHAN_ACK;
NRF_IPC_S->RECEIVE_CNF[DB_IPC_CHAN_RADIO_RX] = 1 << DB_IPC_CHAN_RADIO_RX;

NVIC_EnableIRQ(IPC_IRQn);
NVIC_ClearPendingIRQ(IPC_IRQn);
NVIC_SetPriority(IPC_IRQn, IPC_IRQ_PRIORITY);

// Start the network core
if (!is_network_core_powered_on()) {
power_on_network_core();
_network_call(DB_IPC_NONE, DB_IPC_NET_READY_ACK);
}
release_network_core();

if (callback) {
_radio_callback = callback;
}

mutex_lock();
ipc_shared_data.radio.mode = mode;
_network_call(DB_IPC_RADIO_INIT_REQ, DB_IPC_RADIO_INIT_ACK);
db_ipc_network_call(DB_IPC_RADIO_INIT_REQ);
}

void db_radio_set_frequency(uint8_t freq) {
mutex_lock();
ipc_shared_data.radio.frequency = freq;
_network_call(DB_IPC_RADIO_FREQ_REQ, DB_IPC_RADIO_FREQ_ACK);
db_ipc_network_call(DB_IPC_RADIO_FREQ_REQ);
}

void db_radio_set_channel(uint8_t channel) {
mutex_lock();
ipc_shared_data.radio.channel = channel;
_network_call(DB_IPC_RADIO_CHAN_REQ, DB_IPC_RADIO_CHAN_ACK);
db_ipc_network_call(DB_IPC_RADIO_CHAN_REQ);
}

void db_radio_set_network_address(uint32_t addr) {
mutex_lock();
ipc_shared_data.radio.addr = addr;
_network_call(DB_IPC_RADIO_ADDR_REQ, DB_IPC_RADIO_ADDR_ACK);
db_ipc_network_call(DB_IPC_RADIO_ADDR_REQ);
}

void db_radio_tx(uint8_t *tx_buffer, uint8_t length) {
mutex_lock();
ipc_shared_data.radio.tx_pdu.length = length;
memcpy((void *)ipc_shared_data.radio.tx_pdu.buffer, tx_buffer, length);
_network_call(DB_IPC_RADIO_TX_REQ, DB_IPC_RADIO_TX_ACK);
db_ipc_network_call(DB_IPC_RADIO_TX_REQ);
}

void db_radio_rx(void) {
mutex_lock();
_network_call(DB_IPC_RADIO_RX_REQ, DB_IPC_RADIO_RX_ACK);
db_ipc_network_call(DB_IPC_RADIO_RX_REQ);
}

int8_t db_radio_rssi(void) {
mutex_lock();
_network_call(DB_IPC_RADIO_RSSI_REQ, DB_IPC_RADIO_RSSI_ACK);
db_ipc_network_call(DB_IPC_RADIO_RSSI_REQ);
return ipc_shared_data.radio.rssi;
}

void db_radio_disable(void) {
mutex_lock();
_network_call(DB_IPC_RADIO_DIS_REQ, DB_IPC_RADIO_DIS_ACK);
db_ipc_network_call(DB_IPC_RADIO_DIS_REQ);
}

//=========================== interrupt handlers ===============================

void IPC_IRQHandler(void) {
if (NRF_IPC_S->EVENTS_RECEIVE[DB_IPC_CHAN_ACK]) {
NRF_IPC_S->EVENTS_RECEIVE[DB_IPC_CHAN_ACK] = 0;
mutex_lock();
_ack_received[ipc_shared_data.event] = true;
mutex_unlock();
}
if (NRF_IPC_S->EVENTS_RECEIVE[DB_IPC_CHAN_RADIO_RX]) {
NRF_IPC_S->EVENTS_RECEIVE[DB_IPC_CHAN_RADIO_RX] = 0;
if (_radio_callback) {
Expand Down
Loading

0 comments on commit fd64d80

Please sign in to comment.