初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

View File

@@ -0,0 +1,559 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "nrf21540.h"
#include "nrf_assert.h"
#include "nrf21540_defs.h"
#include "nrf21540_macro.h"
#include "nrf_radio.h"
#include "nrf_ppi.h"
#include "nrf_gpiote.h"
#include "nrf_timer.h"
#include "boards.h"
#if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#include "nrf_egu.h"
#endif
#define NRF21540_BUSY_CHECK(mode) \
if (mode == NRF21540_EXEC_MODE_BLOCKING) \
{ \
while(is_driver_busy()) \
{ \
\
} \
} \
else if (is_driver_busy()) \
{ \
return NRF_ERROR_BUSY; \
}
#define NRF21540_ERROR_CHECK(invalid_state_condition) \
if (device_state_get() == NRF21540_STATE_ERROR) \
{ \
m_nrf21540_data.busy = false; \
return NRF_ERROR_INTERNAL; \
} \
if (invalid_state_condition) \
{ \
m_nrf21540_data.busy = false; \
return NRF_ERROR_INVALID_STATE; \
}
/**@brief nRF21540 chip state.
*
* @details driver state variable possible values.
*/
typedef enum {
NRF21540_STATE_OFF, ///< Chip inactive, line PDN is low, SPI communication impossible.
NRF21540_STATE_READY, ///< SPI is active, but nether transmit nor receive can be performed.
NRF21540_STATE_TX, ///< Transmit state - chip can perform transmiting data.
NRF21540_STATE_RX, ///< Receive state - chip can receive data.
NRF21540_STATE_ERROR, ///< Invalid state - requires reinit.
} nrf21540_state_t;
/**@brief nRF21540 static data. */
static struct
{
volatile nrf21540_state_t cur_state; ///< driver state variable.
volatile nrf21540_trx_t cur_direction; ///< currently serviced radio communication direction.
volatile bool busy; ///< driver is busy at the moment (during changing state phase).
#if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
volatile uint32_t shorts;
#endif
} m_nrf21540_data;
/**@brief Function checks if nRF21540 driver is busy now.
*
* @details Based on driver busy variable.
*
* @return true if nRF21540 driver is busy.
*/
static inline bool is_driver_busy(void)
{
return m_nrf21540_data.busy;
}
/**@brief Function checks if nRF21540 is powered down.
*
* @details Based on driver state variable.
*
* @return true if nRF21540 is in power down state.
*/
static inline bool is_device_off(void)
{
return m_nrf21540_data.cur_state == NRF21540_STATE_OFF;
}
/**@brief Function checks if nRF21540 is powered up state.
*
* @details Based on driver state variable.
*
* @return true if nRF21540 is in power up state.
*/
static inline bool is_device_on(void)
{
return m_nrf21540_data.cur_state != NRF21540_STATE_OFF;
}
/**@brief Function checks if nRF21540 can transmit or receive data.
*
* @details Based on driver state variable.
*
* @return true if nRF21540 is in TX or RX mode.
*/
static inline bool is_device_ready_for_transmission(void)
{
return (m_nrf21540_data.cur_state == NRF21540_STATE_TX ||
m_nrf21540_data.cur_state == NRF21540_STATE_RX);
}
/**@brief Function changes driver state.
*
* @details Changes driver state variable value.
*
* @param[in] new_state state that will be store.
*/
static inline void device_state_set(nrf21540_state_t new_state)
{
m_nrf21540_data.cur_state = new_state;
}
/**@brief Function returns driver state variable value.
*
* @details Based on driver state variable.
*
* @return @ref nrf21540_state_t based state variable value.
*/
static inline nrf21540_state_t device_state_get(void)
{
return m_nrf21540_data.cur_state;
}
/**@brief Function returns task related to transmission direction.
*
* @param[in] dir direction of radio transfer. See @nrf21540_trx_t.
*
* @return task corresponding to given transmission direction.
*/
static inline nrf_radio_task_t nrf21540_task_get(nrf21540_trx_t dir)
{
return dir == NRF21540_TX ? NRF_RADIO_TASK_TXEN : NRF_RADIO_TASK_RXEN;
}
/**@brief Function clears and disbles all PPI connections used by nRF21540 driver.
*
* @details Changes driver state variable value.
*/
static void ppi_cleanup(void)
{
nrf_ppi_channel_disable(NRF21540_PDN_PPI_CHANNEL);
nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
nrf_ppi_channel_disable(NRF21540_TRX_PPI_CHANNEL);
nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_PDN_PPI_CHANNEL, 0, 0, 0);
nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_USER_PPI_CHANNEL, 0, 0, 0);
nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_TRX_PPI_CHANNEL, 0, 0, 0);
}
/**@brief Function clears nRF21540 driver events. */
static void events_clear()
{
nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_START_TO_PDN_UP_EVENT);
NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_READY);
NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_DISABLED);
}
/**@brief Timer interrupt handler.
*
* @details checking time related events occurences and changing driver state if necessary.
*/
void NRF21540_TIMER_IRQ_HANDLER(void)
{
if (nrf_timer_event_check(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT))
{
nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
if (is_device_off() && nrf_gpio_pin_read(NRF21540_PDN_PIN) == 1)
{
device_state_set(NRF21540_STATE_READY);
}
else if (is_device_on() && nrf_gpio_pin_read(NRF21540_PDN_PIN) == 0)
{
device_state_set(NRF21540_STATE_OFF);
ppi_cleanup();
m_nrf21540_data.busy = false;
}
else
{
device_state_set(NRF21540_STATE_ERROR);
ppi_cleanup();
m_nrf21540_data.busy = false;
}
}
}
/**@brief nRF21540 interrupt handler.
*
* @details checking radio related events occurences and changing driver state if necessary.
*/
void NRF21540_RADIO_IRQ_HANDLER(void)
{
if (NRF21540_RADIO_EVENT_CHECK(NRF21540_RADIO_EVENT_READY))
{
NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_READY);
nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
#if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
if (NRF21540_RADIO_SHORTS_ENABLE_CHECK(RADIO_SHORTS_READY_START_Msk))
{
nrf_radio_task_trigger(NRF_RADIO_TASK_START);
}
#endif
if (device_state_get() == NRF21540_STATE_READY)
{
device_state_set(m_nrf21540_data.cur_direction == NRF21540_TX ?
NRF21540_STATE_TX : NRF21540_STATE_RX);
ppi_cleanup();
NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_READY_Msk);
m_nrf21540_data.busy = false;
}
}
if (NRF21540_RADIO_EVENT_CHECK(NRF21540_RADIO_EVENT_DISABLED))
{
NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_DISABLED);
nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
if (is_device_ready_for_transmission())
{
NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_DISABLED_Msk);
device_state_set(NRF21540_STATE_READY);
}
}
}
/**@brief Function resets nRF21540 driver.
*
* @details sets driver state variable to NRF21540_STATE_OFF value,
* cleans all used PPIs and events.
*/
static void driver_reset(void)
{
device_state_set(NRF21540_STATE_OFF);
ppi_cleanup();
events_clear();
NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_INTERRUPT_MASK);
m_nrf21540_data.busy = false;
}
/**@brief Function sets either TX or RX direction.
*
* @details Configuration of all necessarily peripherals to transmit or receive data,
* dependenly on interface used (SPI, or GPIO). Procedure configures nRF21540 chip and
* starts transmitting/receiving. Procedure will be started immediately if
* @ref trigger_event is 0. Otherwise event which address is @ref trigger_event value
* will start procedure.
*
* @param[in] dir RX or TX communication that will be performed.
* @param[in] trigger_event address of event which will trigger the procedure.
* @param[in] mode if NRF21540_EXEC_MODE_BLOCKING the function will wait for tx/rx
* possibility.
* @return NRF_ERROR_INTERNAL when driver is in error state.
* Reinitialization is required.
* NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
* to perform the operation (@sa nrf21540_state_t).
* NRF_ERROR_BUSY when driver performs another operation at
* the moment.
* NRF_SUCCESS on success.
*/
static ret_code_t trx_set(nrf21540_trx_t dir, uint32_t trigger_event,
nrf21540_execution_mode_t mode)
{
ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && trigger_event != 0));
NRF21540_BUSY_CHECK(mode);
NRF21540_ERROR_CHECK((dir == NRF21540_TX && device_state_get() == NRF21540_STATE_TX) ||
(dir == NRF21540_RX && device_state_get() == NRF21540_STATE_RX));
uint32_t ramp_up_time = nrf_radio_modecnf0_ru_get() ? FAST_RAMP_UP_TIME : RAMP_UP_TIME;
nrf_radio_task_t radio_task_to_start = nrf21540_task_get(dir);
m_nrf21540_data.busy = true;
events_clear();
NRF21540_RADIO_INT_ENABLE(NRF21540_RADIO_READY_Msk);
if (is_device_off())
{
nrf_ppi_channel_endpoint_setup(NRF21540_PDN_PPI_CHANNEL,
(uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
NRF21540_TIMER_CC_START_TO_PDN_UP_EVENT),
nrf_gpiote_task_addr_get(NRF21540_PDN_GPIOTE_TASK_SET));
nrf_ppi_channel_enable(NRF21540_PDN_PPI_CHANNEL);
nrf_timer_cc_write(NRF21540_TIMER,
NRF21540_TIMER_CC_PD_PG_CHANNEL,
ramp_up_time - NRF21540_PA_PG_TRX_TIME_US);
nrf_timer_cc_write(NRF21540_TIMER,
NRF21540_TIMER_CC_START_TO_PDN_UP_CHANNEL,
ramp_up_time - NRF21540_PA_PG_TRX_TIME_US - NRF21540_PD_PG_TIME_US);
#if NRF21540_USE_GPIO_MANAGEMENT
nrf21540_gpio_trx_enable(dir);
#elif NRF21540_USE_SPI_MANAGEMENT
nrf21540_spim_for_trx_configure(dir, NRF21540_ENABLE);
#endif
nrf_timer_shorts_enable(NRF21540_TIMER,
NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
NRF21540_RADIO_SHORTS_ENABLE(RADIO_SHORTS_READY_START_Msk);
if (trigger_event == 0)
{
//start immediately.
nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
nrf_radio_task_trigger(radio_task_to_start);
}
else
{
//start when user event occurs.
nrf_ppi_channel_and_fork_endpoint_setup(
NRF21540_USER_PPI_CHANNEL,
trigger_event,
(uint32_t) nrf_timer_task_address_get(NRF21540_TIMER, NRF_TIMER_TASK_START),
(uint32_t) nrf_radio_task_address_get(radio_task_to_start));
nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
}
}
else
{
// at the moment we are not able to switch direction on the fly.
// @todo switching between RXEN and TXEN.
NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_RX);
if (trigger_event == 0)
{
nrf_radio_task_trigger(radio_task_to_start);
}
else
{
// start when user event occurs
nrf_ppi_channel_endpoint_setup(
NRF21540_USER_PPI_CHANNEL,
trigger_event,
(uint32_t) nrf_radio_task_address_get(radio_task_to_start));
nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
}
}
m_nrf21540_data.cur_direction = dir;
if (mode == NRF21540_EXEC_MODE_BLOCKING)
{
while (!is_device_ready_for_transmission());
}
return NRF_SUCCESS;
}
ret_code_t nrf21540_init(void)
{
driver_reset();
// GPIOTE for PDN pin configuration
nrf_gpiote_task_configure(NRF21540_PDN_GPIOTE_CHANNEL_NO,
NRF21540_PDN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_PDN_GPIOTE_CHANNEL_NO);
nrf21540_gpio_init();
NVIC_SetPriority(NRF21540_TIMER_IRQn, NRF21540_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(NRF21540_TIMER_IRQn);
nrf_timer_int_enable(NRF21540_TIMER, NRF21540_TIM_INTERRUPT_MASK);
#if NRF21540_USE_SPI_MANAGEMENT
ret_code_t ret = NRF_SUCCESS;
ret = nrf21540_spi_init();
if (ret != NRF_SUCCESS)
{
device_state_set(NRF21540_STATE_ERROR);
return ret;
}
#endif //NRF21540_USE_SPI_MANAGEMENT
#if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL,
nrf_radio_event_address_get(NRF_RADIO_EVENT_READY),
(uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_READY_EGU_TASK));
nrf_ppi_channel_enable(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL);
nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL,
nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED),
(uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_DISABLED_EGU_TASK));
nrf_ppi_channel_enable(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL);
#endif
NVIC_SetPriority(NRF21540_RADIO_IRQn, NRF21540_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(NRF21540_RADIO_IRQn);
return NRF_SUCCESS;
}
ret_code_t nrf21540_pdn_drive(bool state, nrf21540_execution_mode_t mode)
{
NRF21540_BUSY_CHECK(mode);
NRF21540_ERROR_CHECK((state == true && is_device_on()) ||
(state == false && is_device_off()));
nrf21540_state_t final_state;
if (state)
{
final_state = NRF21540_STATE_READY;
}
else
{
final_state = NRF21540_STATE_OFF;
}
nrf_timer_cc_write(NRF21540_TIMER,
NRF21540_TIMER_CC_PD_PG_CHANNEL,
state ? NRF21540_PD_PG_TIME_US : 0);
nrf_timer_shorts_enable(NRF21540_TIMER,
NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
nrf_gpiote_task_force(NRF21540_PDN_GPIOTE_CHANNEL_NO,
!state ? NRF_GPIOTE_INITIAL_VALUE_LOW : NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
if (mode == NRF21540_EXEC_MODE_BLOCKING)
{
while (device_state_get() != final_state)
{
}
}
return NRF_SUCCESS;
}
ret_code_t nrf21540_tx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
{
NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_TX);
return trx_set(NRF21540_TX, user_trigger_event, mode);
}
ret_code_t nrf21540_rx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
{
NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_RX);
return trx_set(NRF21540_RX, user_trigger_event, mode);
}
bool nrf21540_is_error(void)
{
return device_state_get() == NRF21540_STATE_ERROR ? true : false;
}
ret_code_t nrf21540_ant_set(nrf21540_antenna_t antenna)
{
NRF21540_BUSY_CHECK(NRF21540_EXEC_MODE_NON_BLOCKING);
return nrf21540_gpio_ant_set(antenna);
}
ret_code_t nrf21540_pwr_mode_set(nrf21540_pwr_mode_t mode)
{
NRF21540_BUSY_CHECK(NRF21540_EXEC_MODE_NON_BLOCKING);
#if NRF21540_USE_GPIO_MANAGEMENT
return nrf21540_gpio_pwr_mode_set(mode);
#elif NRF21540_USE_SPI_MANAGEMENT
return nrf21540_spi_pwr_mode_set(mode);
#endif
}
ret_code_t nrf21540_power_down(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
{
ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && user_trigger_event != 0));
NRF21540_ERROR_CHECK(is_device_off());
NRF21540_BUSY_CHECK(mode);
m_nrf21540_data.busy = true;
events_clear();
NRF21540_RADIO_INT_ENABLE(NRF21540_RADIO_DISABLED_Msk);
if (device_state_get() == NRF21540_STATE_READY)
{
// when device is in ready state we jus driving PDN line down and switch off the radio.
(void)nrf21540_pdn_drive(false, NRF21540_EXEC_MODE_NON_BLOCKING);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
}
else
{
// When device is in tx/rx state we have to leave it and then drive PDN down.
// Line PDN should be driven low after 5us from triggering TXEN/RXEN.
uint32_t * trx_drv_task_address;
nrf21540_trx_t cur_direction;
if (device_state_get() == NRF21540_STATE_TX)
{
cur_direction = NRF21540_TX;
}
else if (device_state_get() == NRF21540_STATE_RX)
{
cur_direction = NRF21540_RX;
}
else
{
return NRF_ERROR_INTERNAL;
}
nrf_ppi_channel_endpoint_setup(NRF21540_PDN_PPI_CHANNEL,
(uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
NRF21540_TIMER_CC_TRX_PG_EVENT),
nrf_gpiote_task_addr_get(NRF21540_PDN_GPIOTE_TASK_CLR));
nrf_ppi_channel_enable(NRF21540_PDN_PPI_CHANNEL);
nrf_timer_shorts_enable(NRF21540_TIMER,
NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
nrf_timer_cc_write(NRF21540_TIMER,
NRF21540_TIMER_CC_TRX_PG_CHANNEL,
NRF21540_TRX_PG_TIME_US);
#if NRF21540_USE_GPIO_MANAGEMENT
trx_drv_task_address = (uint32_t*) nrf21540_gpio_trx_task_start_address_get(cur_direction,
NRF21540_DISABLE);
#elif NRF21540_USE_SPI_MANAGEMENT
nrf21540_spim_for_trx_configure(cur_direction, NRF21540_DISABLE);
trx_drv_task_address = (uint32_t*) nrf21540_spim_trx_task_start_address_get();
#endif
if (user_trigger_event == 0)
{
*trx_drv_task_address = 1;
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
}
else
{
// start when user event occurs.
nrf_ppi_channel_and_fork_endpoint_setup(
NRF21540_USER_PPI_CHANNEL,
user_trigger_event,
(uint32_t)nrf_radio_task_address_get(NRF_RADIO_TASK_DISABLE),
(uint32_t) trx_drv_task_address);
nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
}
if (mode == NRF21540_EXEC_MODE_BLOCKING)
{
while (is_device_on());
}
}
return NRF_SUCCESS;
}

View File

@@ -0,0 +1,194 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF21540_H_
#define NRF21540_H_
#include <stdbool.h>
#include <stdint.h>
#include "nrf21540_spi.h"
#include "nrf21540_gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @file
* @brief nRF21540 front-end Bluetooth range extender.
*
*
* @defgroup nrf21540 nRF21540 front-end Bluetooth range extender.
* @{
* @ingroup ext_drivers
* @brief nRF21540 front-end Bluetooth range extender.
*/
#if NRF21540_USE_SPI_MANAGEMENT
#if NRF21540_USE_GPIO_MANAGEMENT
#error Only one management manner can be active
#endif
#elif !NRF21540_USE_GPIO_MANAGEMENT
#error At least one management manner must be active
#endif // NRF21540_USE_SPI_MANAGEMENT
/**@brief Initialization of modules needed by nRF21540:
* - SPI
* - GPIO
* - GPIOTE
* - PPI
* - RADIO
* - NVIC
*
* @return NRF based error code.
* NRF_ERROR_INTERNAL when driver is in error state,
* or SPI initialization has failed. Reinitialization is required.
* NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
* to perform the operation (@sa nrf21540_state_t).
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_init(void);
/**@brief Set nRF21540 to TX mode.
*
* @note Dependently on configuration GPIO or SPI interface will be used.
*
* @param[in] user_trigger_event event that triggers start of procedure - this event
* will be connected to appropriate PPI channel.
* @ref NRF21540_EXECUTE_NOW value causes start procedure
* immediately.
* @param[in] mode @ref NRF21540_EXEC_MODE_BLOCKING - function will wait for
* finishing configuration including settling times required
* by nRF21540 (waits till all procedure has finished).
* @ref NRF21540_EXEC_MODE_NON_BLOCKING - function will start
* procedure and set busy flag. User code can be executed
* at this time and busy flag will be unset when done.
* @return NRF based error code.
* NRF_ERROR_INTERNAL when driver is in error state.
* Reinitialization is required.
* NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
* to perform the operation (@sa nrf21540_state_t).
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_tx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode);
/**@brief Set nRF21540 to TX mode.
*
* @note Dependently on configuration GPIO or SPI interface will be used
* (NRF21540_USE_SPI_MANAGEMENT/NRF21540_USE_GPIO_MANAGEMENT).
*
* @param[in] user_trigger_event event that triggers start of procedure - this event
* will be connected to appropriate PPI channel.
* @ref NRF21540_EXECUTE_NOW value causes start procedure
* immediately.
* @param[in] mode @ref NRF21540_EXEC_MODE_BLOCKING - function will wait for
* finishing configuration including settling times required
* by nRF21540 (waits till all procedure has finished).
* @ref NRF21540_EXEC_MODE_NON_BLOCKING - function will start
* procedure and set busy flag. User code can be executed
* at this time and busy flag will be unset when done.
* @return NRF based error code.
* NRF_ERROR_INTERNAL when driver is in error state.
* Reinitialization is required.
* NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
* to perform the operation (@sa nrf21540_state_t).
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_rx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode);
/**@brief Function choses one of two physical antenna outputs.
*
* @param[in] antenna One of antenna outputs. See @ref nrf21540_antenna_t.
* @return NRF based error code.
* NRF_ERROR_BUSY when driver performs another operation at
* the moment.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_ant_set(nrf21540_antenna_t antenna);
/**@brief Function choses one of two predefined power modes in nRF21540.
*
* @details Refer to nRF21540 Objective Product Specification, section: TX power control.
*
* @param[in] mode Power mode. See @ref nrf21540_pwr_mode_t.
* @return NRF based error code.
* NRF_ERROR_BUSY when driver performs another operation at
* the moment.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_pwr_mode_set(nrf21540_pwr_mode_t mode);
/**@brief nRF21540 power down.
*
* @details Disables chip functionality and enter power save mode.
*
* @note Dependently on configuration GPIO or SPI interface will be used.
*
* @param[in] user_trigger_event event that triggers start of procedure - this event
* will be connected to appropriate PPI channel.
* @ref NRF21540_EXECUTE_NOW value causes start procedure
* immediately.
* @param[in] mode @ref NRF21540_EXEC_MODE_BLOCKING - function will wait for
* finishing configuration including settling times required
* by nRF21540 (waits till all procedure has finished).
* @ref NRF21540_EXEC_MODE_NON_BLOCKING - function will start
* procedure and set busy flag. User code can be executed
* at this time and busy flag will be unset when done.
* @return NRF_ERROR_INTERNAL when driver is in error state.
* Reinitialization is required then.
* NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
* to perform the operation (@sa nrf21540_state_t).
* NRF_ERROR_BUSY when driver performs another operation at
* the moment.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_power_down(uint32_t user_trigger_event, nrf21540_execution_mode_t mode);
/**@brief Checks if nRF21540 driver is in error state.
*
* @return true if driver is in error state and should be reinitialized.
*/
bool nrf21540_is_error(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF21540_H_

View File

@@ -0,0 +1,183 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF21540_DEFS_H_
#define NRF21540_DEFS_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Macros creating instance channels number dependent parameters.
*/
#define NRF21540_TIMER CONCAT_2(NRF_TIMER, NRF21540_TIMER_NO)
#define NRF21540_TIMER_IRQ_HANDLER CONCAT_3(TIMER, NRF21540_TIMER_NO, _IRQHandler)
#define NRF21540_TIMER_IRQn CONCAT_3(TIMER, NRF21540_TIMER_NO, _IRQn)
#define NRF21540_TIM_INTERRUPT_MASK CONCAT_3(TIMER_INTENSET_COMPARE, \
NRF21540_TIMER_CC_PD_PG_CHANNEL_NO, _Msk)
#if NRF21540_TIMER_CC_START_TO_PDN_UP_CHANNEL_NO == NRF21540_TIMER_CC_PD_PG_CHANNEL_NO
#error These CC channels must be different
#endif
#if (NRF21540_PDN_PPI_CHANNEL_NO == NRF21540_USER_PPI_CHANNEL_NO) || \
(NRF21540_PDN_PPI_CHANNEL_NO == NRF21540_TRX_PPI_CHANNEL_NO) || \
(NRF21540_TRX_PPI_CHANNEL_NO == NRF21540_USER_PPI_CHANNEL_NO)
#error These PPI channels must be different
#endif
#define NRF21540_USER_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_USER_PPI_CHANNEL_NO)
#define NRF21540_PDN_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_PDN_PPI_CHANNEL_NO)
#define NRF21540_TRX_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_TRX_PPI_CHANNEL_NO)
#define NRF21540_USER_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_USER_PPI_CHANNEL_NO)
#define NRF21540_PDN_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_PDN_PPI_CHANNEL_NO)
#define NRF21540_TRX_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_TRX_PPI_CHANNEL_NO)
#define NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK CONCAT_3(NRF_TIMER_SHORT_COMPARE, NRF21540_TIMER_CC_PD_PG_CHANNEL_NO, _STOP_MASK)
#define NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK CONCAT_3(NRF_TIMER_SHORT_COMPARE, NRF21540_TIMER_CC_PD_PG_CHANNEL_NO, _CLEAR_MASK)
#define NRF21540_TIMER_CC_START_TO_PDN_UP_CHANNEL CONCAT_2(NRF_TIMER_CC_CHANNEL, NRF21540_TIMER_CC_START_TO_PDN_UP_CHANNEL_NO)
#define NRF21540_TIMER_CC_PD_PG_CHANNEL CONCAT_2(NRF_TIMER_CC_CHANNEL, NRF21540_TIMER_CC_PD_PG_CHANNEL_NO)
#define NRF21540_TIMER_CC_TRX_PG_CHANNEL NRF21540_TIMER_CC_PD_PG_CHANNEL
#define NRF21540_TIMER_CC_START_TO_PDN_UP_EVENT CONCAT_2(NRF_TIMER_EVENT_COMPARE, NRF21540_TIMER_CC_START_TO_PDN_UP_CHANNEL_NO)
#define NRF21540_TIMER_CC_PD_PG_EVENT CONCAT_2(NRF_TIMER_EVENT_COMPARE, NRF21540_TIMER_CC_PD_PG_CHANNEL_NO)
#define NRF21540_TIMER_CC_TRX_PG_EVENT NRF21540_TIMER_CC_PD_PG_EVENT
#if (NRF21540_PDN_GPIOTE_CHANNEL_NO == NRF21540_PA_GPIOTE_CHANNEL_NO) || \
(NRF21540_PDN_GPIOTE_CHANNEL_NO == NRF21540_LNA_GPIOTE_CHANNEL_NO) || \
(NRF21540_LNA_GPIOTE_CHANNEL_NO == NRF21540_PA_GPIOTE_CHANNEL_NO)
#error These GPIOTE channels must be different
#endif
#define NRF21540_PDN_GPIOTE_TASK_CLR CONCAT_2(NRF_GPIOTE_TASKS_CLR_, NRF21540_PDN_GPIOTE_CHANNEL_NO)
#define NRF21540_LNA_GPIOTE_TASK_CLR CONCAT_2(NRF_GPIOTE_TASKS_CLR_, NRF21540_LNA_GPIOTE_CHANNEL_NO)
#define NRF21540_PA_GPIOTE_TASK_CLR CONCAT_2(NRF_GPIOTE_TASKS_CLR_, NRF21540_PA_GPIOTE_CHANNEL_NO)
#define NRF21540_PDN_GPIOTE_TASK_SET CONCAT_2(NRF_GPIOTE_TASKS_SET_, NRF21540_PDN_GPIOTE_CHANNEL_NO)
#define NRF21540_LNA_GPIOTE_TASK_SET CONCAT_2(NRF_GPIOTE_TASKS_SET_, NRF21540_LNA_GPIOTE_CHANNEL_NO)
#define NRF21540_PA_GPIOTE_TASK_SET CONCAT_2(NRF_GPIOTE_TASKS_SET_, NRF21540_PA_GPIOTE_CHANNEL_NO)
#define NRF21540_GPIO_TASK_SET(channel) CONCAT_2(NRF_GPIOTE_TASKS_SET_, channel)
#define NRF21540_GPIO_TASK_CLR(channel) CONCAT_2(NRF_GPIOTE_TASKS_CLR_, channel)
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_IRQ_HANDLER RADIO_IRQHandler
#define NRF21540_RADIO_IRQn RADIO_IRQn
#define NRF21540_RADIO_READY_Msk RADIO_INTENSET_READY_Msk
#define NRF21540_RADIO_EVENT_READY NRF_RADIO_EVENT_READY
#define NRF21540_RADIO_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk
#define NRF21540_RADIO_EVENT_DISABLED NRF_RADIO_EVENT_DISABLED
#else
#if (NRF21540_USER_PPI_CHANNEL_NO == NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL_NO) || \
(NRF21540_PDN_PPI_CHANNEL_NO == NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL_NO) || \
(NRF21540_TRX_PPI_CHANNEL_NO == NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL_NO) || \
(NRF21540_USER_PPI_CHANNEL_NO == NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL_NO) || \
(NRF21540_PDN_PPI_CHANNEL_NO == NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL_NO) || \
(NRF21540_TRX_PPI_CHANNEL_NO == NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL_NO) || \
(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL_NO == NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL_NO)
#error These PPI channels must be different
#endif
#if (NRF21540_RADIO_READY_EGU_CHANNEL_NO == NRF21540_RADIO_DISABLED_EGU_CHANNEL_NO)
#error These EGU channels must be different
#endif
#define NRF21540_EGU CONCAT_2(NRF_EGU, NRF21540_EGU_NO)
#define SWIx_EGU CONCAT_3(SWI, NRF21540_EGU_NO, _EGU)
#define NRF21540_RADIO_IRQ_HANDLER CONCAT_3(SWIx_EGU, NRF21540_EGU_NO, _IRQHandler)
#define NRF21540_RADIO_IRQn CONCAT_3(SWIx_EGU, NRF21540_EGU_NO, _IRQn)
#define NRF21540_RADIO_READY_Msk (1 << NRF21540_RADIO_READY_EGU_CHANNEL_NO)
#define NRF21540_RADIO_DISABLED_Msk (1 << NRF21540_RADIO_DISABLED_EGU_CHANNEL_NO)
#define NRF21540_RADIO_EVENT_READY CONCAT_2(NRF_EGU_EVENT_TRIGGERED, NRF21540_RADIO_READY_EGU_CHANNEL_NO)
#define NRF21540_RADIO_EVENT_DISABLED CONCAT_2(NRF_EGU_EVENT_TRIGGERED, NRF21540_RADIO_DISABLED_EGU_CHANNEL_NO)
#define NRF21540_RADIO_READY_EGU_TASK CONCAT_2(NRF_EGU_TASK_TRIGGER, NRF21540_RADIO_READY_EGU_CHANNEL_NO)
#define NRF21540_RADIO_DISABLED_EGU_TASK CONCAT_2(NRF_EGU_TASK_TRIGGER, NRF21540_RADIO_DISABLED_EGU_CHANNEL_NO)
#define NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL_NO)
#define NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL CONCAT_2(NRF_PPI_CHANNEL, NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL_NO)
#endif //!NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_INTERRUPT_MASK (NRF21540_RADIO_READY_Msk | NRF21540_RADIO_DISABLED_Msk)
/**@brief Time in microseconds when PA GPIO is activated before the radio is ready for
* transmission.
*/
#define NRF21540_PA_PG_TRX_TIME_US 13
/**@brief Time in microseconds when LNA GPIO is activated before the radio is ready for
* reception.
*/
#define NRF21540_LNA_PG_TRX_TIME_US 13
/**@brief The time between activating the PDN and asserting the RX_EN/TX_EN.
*/
#define NRF21540_PD_PG_TIME_US 18
/**@brief The time between deasserting the RX_EN/TX_EN and deactivating PDN.
*/
#define NRF21540_TRX_PG_TIME_US 5
/**@brief Timing definitions for radio peripheral on nRF uc.
*/
#define TX_FAST_RAMP_UP_TIME 40 ///< Radio fast ramp up time in us for tx
#define RX_FAST_RAMP_UP_TIME 40 ///< Radio fast ramp up time in us for rx
#define TX_RAMP_UP_TIME 130 ///< Radio normal ramp up time in us for tx
#define RX_RAMP_UP_TIME 130 ///< Radio normal ramp up time in us for rx
#if (TX_RAMP_UP_TIME == RX_RAMP_UP_TIME && TX_FAST_RAMP_UP_TIME == RX_FAST_RAMP_UP_TIME)
#define FAST_RAMP_UP_TIME TX_FAST_RAMP_UP_TIME
#define RAMP_UP_TIME TX_RAMP_UP_TIME
#else
#error ramp up times for rx and tx direction are different. Driver needs rework
#endif
#if (FAST_RAMP_UP_TIME < (NRF21540_PA_PG_TRX_TIME_US + NRF21540_PD_PG_TIME_US))
#error fast ramp up time must be greater or equal than (TPD->PG + TPG->TRX)
#endif
#if (FAST_RAMP_UP_TIME > RAMP_UP_TIME)
#error fast ramp up time connot be greater than ramp up time
#endif
#ifdef __cplusplus
}
#endif
#endif // NRF21540_DEFS_H_

View File

@@ -0,0 +1,126 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "nrf21540_gpio.h"
#include "nrf_assert.h"
#include "boards.h"
#include "nrf21540_defs.h"
#include "nrf_gpiote.h"
#include "nrf_ppi.h"
#include "nrf_timer.h"
void nrf21540_gpio_init(void)
{
nrf_gpio_cfg_output(NRF21540_ANTSEL_PIN);
#if NRF21540_USE_GPIO_MANAGEMENT
nrf_gpio_cfg_output(NRF21540_MODE_PIN);
//GPIOTE for TXEN pin configuration
nrf_gpiote_task_configure(NRF21540_PA_GPIOTE_CHANNEL_NO,
NRF21540_TXEN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_PA_GPIOTE_CHANNEL_NO);
//GPIOTE for RXEN pin configuration
nrf_gpiote_task_configure(NRF21540_LNA_GPIOTE_CHANNEL_NO,
NRF21540_RXEN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_LNA_GPIOTE_CHANNEL_NO);
#endif /*NRF21540_USE_GPIO_MANAGEMENT*/
}
ret_code_t nrf21540_gpio_ant_set(nrf21540_antenna_t antenna)
{
if (antenna == NRF21540_ANT1)
{
nrf_gpio_pin_clear(NRF21540_ANTSEL_PIN);
}
else if (antenna == NRF21540_ANT2)
{
nrf_gpio_pin_set(NRF21540_ANTSEL_PIN);
}
else
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
#if NRF21540_USE_GPIO_MANAGEMENT
uint32_t nrf21540_gpio_trx_task_start_address_get(nrf21540_trx_t dir,
nrf21540_bool_state_t required_state)
{
uint8_t gpiote_rx_tx_channel =
dir == NRF21540_TX ?
NRF21540_PA_GPIOTE_CHANNEL_NO :
NRF21540_LNA_GPIOTE_CHANNEL_NO;
return required_state == NRF21540_ENABLE ?
nrf_gpiote_task_addr_get(nrf_gpiote_set_task_get(gpiote_rx_tx_channel)) :
nrf_gpiote_task_addr_get(nrf_gpiote_clr_task_get(gpiote_rx_tx_channel));
}
void nrf21540_gpio_trx_enable(nrf21540_trx_t dir)
{
uint32_t gpiote_task_start = nrf21540_gpio_trx_task_start_address_get(dir, NRF21540_ENABLE);
nrf_ppi_channel_endpoint_setup(NRF21540_TRX_PPI_CHANNEL,
(uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
NRF21540_TIMER_CC_PD_PG_EVENT),
gpiote_task_start);
nrf_ppi_channel_enable(NRF21540_TRX_PPI_CHANNEL);
}
ret_code_t nrf21540_gpio_pwr_mode_set(nrf21540_pwr_mode_t mode)
{
if (mode == NRF21540_PWR_MODE_A)
{
nrf_gpio_pin_clear(NRF21540_MODE_PIN);
}
else if (mode == NRF21540_PWR_MODE_B)
{
nrf_gpio_pin_set(NRF21540_MODE_PIN);
}
else
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
#endif /*NRF21540_USE_GPIO_MANAGEMENT*/

View File

@@ -0,0 +1,97 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF21540_GPIO_H_
#define NRF21540_GPIO_H_
#include "nrf_gpio.h"
#include "nrf21540_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Function initializes GPIO interface.
*/
void nrf21540_gpio_init(void);
/**@brief Function choses one of two physical antenna outputs.
*
* @param[in] antenna one of antenna outputs. See @ref nrf21540_antenna_t.
* @return NRF_ERROR_INVALID_PARAM when invalid argument given.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_gpio_ant_set(nrf21540_antenna_t antenna);
#if NRF21540_USE_GPIO_MANAGEMENT
/**@brief Function returns address of task which triggers RX_EN/TX_EN pin
* to set nRF21540 radio trasfer direction.
*
* @param[in] dir Direction of the radio transmission. See @ref nrf21540_trx_t.
* @param[in] required_state State of RX/TX transfer. See @ref nrf21540_bool_state_t.
* @return Address of appropriate task.
*/
uint32_t nrf21540_gpio_trx_task_start_address_get(nrf21540_trx_t dir,
nrf21540_bool_state_t required_state);
/**@brief Function configures the chip and peripherals for TX/RX transfer purpose.
*
* @details enables/disables RX/TX transfers.
*
* @param[in] dir direction of radio transfer. See @ref nrf21540_trx_t.
*/
void nrf21540_gpio_trx_enable(nrf21540_trx_t dir);
/**@brief Function choses one of two predefined power modes in nRF21540.
*
* @details Refer to nRF21540 Objective Product Specification, section: TX power control.
*
* @param[in] mode Power mode. See @ref nrf21540_pwr_mode_t.
* @return NRF_ERROR_INVALID_PARAM when invalid argument given.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_gpio_pwr_mode_set(nrf21540_pwr_mode_t mode);
#endif /*NRF21540_USE_GPIO_MANAGEMENT*/
#ifdef __cplusplus
}
#endif
#endif // NRF21540_GPIO_H_

View File

@@ -0,0 +1,125 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF21540_MACRO_H_
#define NRF21540_MACRO_H_
#include "nrf21540_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Macro for retrieving the state of the nRF21540 radio event. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_EVENT_CHECK(event) \
nrf_radio_event_check(event)
#else
#define NRF21540_RADIO_EVENT_CHECK(event) \
nrf_egu_event_check(NRF21540_EGU, event)
#endif
/**@brief Macro for clearing the nRF21540 radio event. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_EVENT_CLEAR(event) \
nrf_radio_event_clear(event)
#else
#define NRF21540_RADIO_EVENT_CLEAR(event) \
nrf_egu_event_clear(NRF21540_EGU, event)
#endif
/**@brief Macro for triggering the nRF21540 radio task. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_TASK_TRIGGER(task) \
nrf_radio_task_trigger(event)
#else
#define NRF21540_RADIO_TASK_TRIGGER(task) \
nrf_egu_task_trigger(NRF21540_EGU, event)
#endif
/**@brief Macro for disabling the nRF21540 interrupts. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_INT_DISABLE(mask) \
nrf_radio_int_disable(mask)
#else
#define NRF21540_RADIO_INT_DISABLE(mask) \
nrf_egu_int_disable(NRF21540_EGU, mask)
#endif
/**@brief Macro for enabling the nRF21540 interrupts. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_INT_ENABLE(mask) \
nrf_radio_int_enable(mask)
#else
#define NRF21540_RADIO_INT_ENABLE(mask) \
nrf_egu_int_enable(NRF21540_EGU, mask)
#endif
/**@brief Macro for enabling the nRF21540 shorts. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_SHORTS_ENABLE(shorts_mask) \
nrf_radio_shorts_enable(shorts_mask)
#else
#define NRF21540_RADIO_SHORTS_ENABLE(shorts_mask) \
(m_nrf21540_data.shorts |= shorts_mask)
#endif
/**@brief Macro for disabling the nRF21540 shorts. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_SHORTS_DISABLE(shorts_mask) \
nrf_radio_shorts_disable(shorts_mask)
#else
#define NRF21540_RADIO_SHORTS_DISABLE(shorts_mask) \
(m_nrf21540_data.shorts &= ~shorts_mask)
#endif
/**@brief Macro for disabling the nRF21540 shorts. */
#if !NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
#define NRF21540_RADIO_SHORTS_ENABLE_CHECK(shorts_mask) \
(nrf_radio_shorts_get() && shorts_mask)
#else
#define NRF21540_RADIO_SHORTS_ENABLE_CHECK(shorts_mask) \
(m_nrf21540_data.shorts && shorts_mask)
#endif
#ifdef __cplusplus
}
#endif
#endif // NRF21540_MACRO_H_

View File

@@ -0,0 +1,269 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "nrf21540_spi.h"
#include <string.h>
#include "nrf_assert.h"
#include "boards.h"
#include "nrf_ppi.h"
#include "nrf21540_defs.h"
#include "nrf_timer.h"
#if NRF21540_USE_SPI_MANAGEMENT
static uint8_t m_spi_tx_data[NRF21540_SPI_LENGTH_BYTES]; ///< SPI tx buffer.
static uint8_t m_spi_rx_data[NRF21540_SPI_LENGTH_BYTES]; ///< SPI rx buffer.
static volatile bool m_spi_xfer_done; ///< Flag indicates that SPI completed the transfer.
/**@brief Structure keeps content of important registers of nRF21540.
*
* @details Driver keeps this data because it needs to operate at single bits
* included in these registers (otherwise it should read it content
* during every operation).
*/
static struct {
uint8_t CONFREG0; ///< CONFREG0 register's content.
uint8_t CONFREG1; ///< CONFREG1 register's content.
} m_confreg_statics;
static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(NRF21540_SPIM_NO); /**< SPI instance. */
/**@brief Function waits for SPI transfer has finished
*
* @details Used in blocking mode transfer
*/
static inline void wait_for_transfer_end(void)
{
while (!m_spi_xfer_done)
{}
m_spi_xfer_done = false;
}
/**@brief Handler called by nrfx driver when SPI event occurs.
*
* @param[in] p_event Event which triggers the handler.
* @param[in] p_context Context.
*/
static void spim_event_handler(nrfx_spim_evt_t const *p_event, void *p_context)
{
m_spi_xfer_done = true;
}
/**@brief Function reads the content of nRF21540 chip register.
*
* @details Preparation of read register operation. Every register has one byte size.
*
* @param[in] reg Register address to read.
* @param[in] mode if NRF21540_EXEC_MODE_BLOCKING the function will wait for data
* received.
* @param[in] start_now if enabled, transmision immediately initialized,
* otherwise transfer will be triggered by external event.
*/
static uint8_t spi_reg_read(nrf21540_reg_t reg, nrf21540_execution_mode_t mode, bool start_now)
{
ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && start_now == false));
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_spi_tx_data,
NRF21540_SPI_LENGTH_BYTES,
m_spi_rx_data,
NRF21540_SPI_LENGTH_BYTES);
m_spi_tx_data[NRF21540_SPI_COMMAND_ADDR_BYTE] =
(NRF21540_SPI_COMMAND_READ << NRF21540_SPI_COMMAND_Pos) | (reg << NRF21540_SPI_REG_Pos);
(void)nrfx_spim_xfer(&spi, &xfer_desc, 0);
if (mode == NRF21540_EXEC_MODE_BLOCKING)
{
wait_for_transfer_end();
}
return m_spi_rx_data[NRF21540_SPI_DATA_BYTE];
}
/**@brief Function writes the content of nRF21540 chip register.
*
* @details Preparation of data to send. Every register has one byte size.
*
* @param[in] reg Register address to write.
* @param[in] data Data to write.
* @param[in] mode if NRF21540_EXEC_MODE_BLOCKING the function will wait for transfer
* finished after sending data.
* @param[in] start_now if enabled, transmision immediately initialized,
* otherwise transfer will be triggered by external event.
*/
static void spi_reg_write(nrf21540_reg_t reg, uint8_t data, nrf21540_execution_mode_t mode, bool start_now)
{
ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && start_now == false));
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_spi_tx_data,
NRF21540_SPI_LENGTH_BYTES,
m_spi_rx_data,
NRF21540_SPI_LENGTH_BYTES);
m_spi_tx_data[NRF21540_SPI_COMMAND_ADDR_BYTE] =
(NRF21540_SPI_COMMAND_WRITE << NRF21540_SPI_COMMAND_Pos) | (reg << NRF21540_SPI_REG_Pos);
m_spi_tx_data[NRF21540_SPI_DATA_BYTE] = data;
uint32_t flags = start_now ? 0 : NRFX_SPIM_FLAG_HOLD_XFER;
(void)nrfx_spim_xfer(&spi, &xfer_desc, flags);
if (mode == NRF21540_EXEC_MODE_BLOCKING)
{
wait_for_transfer_end();
}
}
/**@brief Function reads content of important nRF21540's registers and stores
* it to dedicated structure (@ref m_confreg_statics).
*
* @return Return NRF based error code.
*/
static ret_code_t m_confreg_statics_content_update(void)
{
ret_code_t ret = nrf21540_pdn_drive(true, NRF21540_EXEC_MODE_BLOCKING);
if (ret != NRF_SUCCESS)
{
return ret;
}
m_confreg_statics.CONFREG0 = spi_reg_read(NRF21540_REG_CONFREG0,
NRF21540_EXEC_MODE_BLOCKING, true);
m_confreg_statics.CONFREG1 = spi_reg_read(NRF21540_REG_CONFREG1,
NRF21540_EXEC_MODE_BLOCKING, true);
return nrf21540_pdn_drive(false, NRF21540_EXEC_MODE_BLOCKING);
}
ret_code_t nrf21540_spi_init(void)
{
ret_code_t ret;
nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
spi_config.frequency = NRF_SPIM_FREQ_4M;
spi_config.ss_pin = NRF21540_CS_PIN;
spi_config.miso_pin = NRF21540_MISO_PIN;
spi_config.mosi_pin = NRF21540_MOSI_PIN;
spi_config.sck_pin = NRF21540_CLK_PIN;
spi_config.ss_active_high = false;
ret = nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL);
if (ret != NRFX_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
return m_confreg_statics_content_update();
}
/**@brief Function enables or disables nRF21540 TX mode.
*
* @details Preparation of appropriate register content and tranfer initialization.
*
* @param[in] state NRF21540_DISABLE/NRF21540_ENABLE causes TX mode disabled/enabled.
*/
static void tx_en_drive(nrf21540_bool_state_t state)
{
uint8_t reg_val;
if (state == NRF21540_ENABLE)
{
reg_val = m_confreg_statics.CONFREG0 | NRF21540_BITS_CONFREG0_TX_EN_Enable;
}
else
{
reg_val = m_confreg_statics.CONFREG0 &(~NRF21540_BITS_CONFREG0_TX_EN_Enable);
}
spi_reg_write(NRF21540_REG_CONFREG0, reg_val, NRF21540_EXEC_MODE_NON_BLOCKING, false);
}
/**@brief Function enables or disables nRF21540 RX mode.
*
* @details Preparation of appropriate register content and tranfer initialization.
*
* @param[in] state NRF21540_DISABLE/NRF21540_ENABLE causes RX mode disabled/enabled.
*/
static void rx_en_drive(nrf21540_bool_state_t state)
{
uint8_t reg_val;
if (state == NRF21540_ENABLE)
{
reg_val = m_confreg_statics.CONFREG1 | NRF21540_BITS_CONFREG1_RX_EN_Enable;
}
else
{
reg_val = m_confreg_statics.CONFREG1 &(~NRF21540_BITS_CONFREG1_RX_EN_Disable);
}
spi_reg_write(NRF21540_REG_CONFREG1, reg_val, NRF21540_EXEC_MODE_NON_BLOCKING, false);
}
inline uint32_t nrf21540_spim_trx_task_start_address_get(void)
{
return nrfx_spim_start_task_get(&spi);
}
void nrf21540_spim_for_trx_configure(nrf21540_trx_t dir, nrf21540_bool_state_t required_state)
{
if (dir == NRF21540_TX)
{
tx_en_drive(required_state);
}
else
{
rx_en_drive(required_state);
}
if (required_state == NRF21540_ENABLE)
{
uint32_t task_start_address = nrfx_spim_start_task_get(&spi);
nrf_ppi_channel_endpoint_setup(NRF21540_TRX_PPI_CHANNEL,
(uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
NRF21540_TIMER_CC_PD_PG_EVENT),
task_start_address);
nrf_ppi_channel_enable(NRF21540_TRX_PPI_CHANNEL);
}
}
ret_code_t nrf21540_spi_pwr_mode_set(nrf21540_pwr_mode_t mode)
{
if (mode == NRF21540_PWR_MODE_A)
{
spi_reg_write(NRF21540_REG_CONFREG0, NRF21540_BITS_CONFREG0_MODE_0,
NRF21540_EXEC_MODE_BLOCKING, true);
}
else if (mode == NRF21540_PWR_MODE_B)
{
spi_reg_write(NRF21540_REG_CONFREG0, NRF21540_BITS_CONFREG0_MODE_1,
NRF21540_EXEC_MODE_BLOCKING, true);
}
else
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
#endif /*NRF21540_USE_SPI_MANAGEMENT*/

View File

@@ -0,0 +1,213 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF21540_SPI_H_
#define NRF21540_SPI_H_
#include <stdbool.h>
#include <stdint.h>
#include "nrfx_spim.h"
#include "nrf21540_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief nRF21540 SPI interface parameters defines.
*/
#define NRF21540_SPI_LENGTH_BYTES 2 ///< SPI tx/rx buffer size in bytes.
#define NRF21540_SPI_COMMAND_ADDR_BYTE 0 ///< Position of command field in SPI frame.
#define NRF21540_SPI_DATA_BYTE 1 ///< Position of data field in SPI frame.
#define NRF21540_SPI_COMMAND_Pos 6 ///< Command code bit-position in command field.
#define NRF21540_SPI_REG_Pos 0 ///< Register address bit-position in command field.
#define NRF21540_SPI_COMMAND_NOP 0x00 ///< 'NOP' command code.
#define NRF21540_SPI_COMMAND_READ 0x02 ///< 'READ' command code.
#define NRF21540_SPI_COMMAND_WRITE 0x03 ///< 'WRITE' command code.
/**@brief CONFREG0 register bitfields.
*/
#define NRF21540_BITS_CONFREG0_TX_EN_Pos 0 ///< Position of TX_EN field.
#define NRF21540_BITS_CONFREG0_TX_EN_Msk (1 << NRF21540_BITS_CONFREG0_TX_EN_Pos) ///< Bit mask of TX_EN field.
#define NRF21540_BITS_CONFREG0_TX_EN_Disable 0 ///< Disable TX mode.
#define NRF21540_BITS_CONFREG0_TX_EN_Enable 1 ///< Enable TX mode.
#define NRF21540_BITS_CONFREG0_MODE_Pos 1 ///< Position of MODE field.
#define NRF21540_BITS_CONFREG0_MODE_Msk (1 << NRF21540_BITS_CONFREG0_MODE_Pos) ///< Bit mask of MODE field.
#define NRF21540_BITS_CONFREG0_MODE_0 0 ///< Selects MODE 0.
#define NRF21540_BITS_CONFREG0_MODE_1 1 ///< Selects MODE 1.
#define NRF21540_BITS_CONFREG0_TX_GAIN_Pos 2 ///< Position of TX_GAIN field.
#define NRF21540_BITS_CONFREG0_TX_GAIN_Msk (0x1F << NRF21540_BITS_CONFREG0_TX_GAIN_Pos) ///< Bit mask of TX_GAIN field.
#define NRF21540_BITS_CONFREG0_TX_GAIN_Min 0 ///< Minimum TX_GAIN register value
#define NRF21540_BITS_CONFREG0_TX_GAIN_Max 31 ///< Maximum TX_GAIN register value
/**@brief CONFREG1 register bitfields.
*/
#define NRF21540_BITS_CONFREG1_RX_EN_Pos 0 ///< Position of RX_EN field.
#define NRF21540_BITS_CONFREG1_RX_EN_Msk (1 << NRF21540_BITS_CONFREG1_RX_EN_Pos) ///< Bit mask of TX_EN field.
#define NRF21540_BITS_CONFREG1_RX_EN_Disable 0 ///< Disable RX mode.
#define NRF21540_BITS_CONFREG1_RX_EN_Enable 1 ///< Enable RX mode.
#define NRF21540_BITS_CONFREG1_UICR_EN_Pos 2 ///< Position of UICR_EN field.
#define NRF21540_BITS_CONFREG1_UICR_EN_Msk (1 << NRF21540_BITS_CONFREG1_UICR_EN_Pos) ///< Bit mask of UICR_EN field.
#define NRF21540_BITS_CONFREG1_UICR_EN_Disable 0 ///< Disable UICR program mode.
#define NRF21540_BITS_CONFREG1_UICR_EN_Enable 1 ///< Enable UICR program mode.
#define NRF21540_BITS_CONFREG1_KEY_Pos 4 ///< Position of KEY field.
#define NRF21540_BITS_CONFREG1_KEY_Msk (0x0F << NRF21540_BITS_CONFREG1_KEY_Pos) ///< Bit mask of KEY field.
#define NRF21540_BITS_CONFREG1_KEY_Enter 15 ///< Enter UICR program mode.
#define NRF21540_BITS_CONFREG1_KEY_Leave 0 ///< Leave UICR program mode.
/**@brief CONFREG2 register bitfields.
*/
#define NRF21540_BITS_CONFREG2_POUTA_UICR_Pos 0 ///< Position of POUTA_UICR field.
#define NRF21540_BITS_CONFREG2_POUTA_UICR_Msk (0x1F << NRF21540_BITS_CONFREG2_POUTA_UICR_Pos) ///< Bit mask of POUTA_UICR field.
#define NRF21540_BITS_CONFREG2_POUTA_UICR_Min 0 ///< Minimum POUTA_UICR register value
#define NRF21540_BITS_CONFREG2_POUTA_UICR_Max 31 ///< Maximum POUTA_UICR register value
#define NRF21540_BITS_CONFREG2_POUTA_SEL_Pos 5 ///< Position of POUTA_SEL field.
#define NRF21540_BITS_CONFREG2_POUTA_SEL_Msk (1 << NRF21540_BITS_CONFREG2_POUTA_SEL_Pos) ///< Bit mask of POUTA_SEL field.
#define NRF21540_BITS_CONFREG2_POUTA_SEL_PROD 0 ///< Initialize TX_GAIN register with 20dBm value.
#define NRF21540_BITS_CONFREG2_POUTA_SEL_UICR 1 ///< Initialize TX_GAIN register with POUTA_UICR value.
#define NRF21540_BITS_CONFREG2_WR_UICR_Pos 7 ///< Position of WR_UICR field.
#define NRF21540_BITS_CONFREG2_WR_UICR_Msk (1 << NRF21540_BITS_CONFREG2_WR_UICR_Pos) ///< Bit mask of WR_UICR field.
#define NRF21540_BITS_CONFREG2_WR_UICR_IDLE 0 ///< EFUSE idle .
#define NRF21540_BITS_CONFREG2_WR_UICR_WRITE 1 ///< EFUSE write.
/**@brief CONFREG3 register bitfields.
*/
#define NRF21540_BITS_CONFREG3_POUTB_UICR_Pos 0 ///< Position of POUTB_UICR field.
#define NRF21540_BITS_CONFREG3_POUTB_UICR_Msk (0x1F << NRF21540_BITS_CONFREG3_POUTB_SEL_Pos) ///< Bit mask of POUTB_UICR field.
#define NRF21540_BITS_CONFREG3_POUTB_UICR_Min 0 ///< Minimum POUTB_UICR register value
#define NRF21540_BITS_CONFREG3_POUTB_UICR_Max 31 ///< Maximum POUTB_UICR register value
#define NRF21540_BITS_CONFREG3_POUTB_SEL_Pos 5 ///< Position of POUTB_SEL field.
#define NRF21540_BITS_CONFREG3_POUTB_SEL_Msk (1 << NRF21540_BITS_CONFREG3_POUTB_SEL_Pos) ///< Bit mask of POUTB_SEL field.
#define NRF21540_BITS_CONFREG3_POUTB_SEL_PROD 0 ///< Initialize TX_GAIN register with 20dBm value.
#define NRF21540_BITS_CONFREG3_POUTB_SEL_UICR 1 ///< Initialize TX_GAIN register with POUTB_UICR value.
/**@brief PARTNUMBER register bitfields.
*/
#define NRF21540_PARTNUMBER_PARTNUMBER_Pos 0 ///< Position of PARTNUMBER field.
#define NRF21540_PARTNUMBER_PARTNUMBER_Msk (0xFF << NRF21540_PARTNUMBER_PARTNUMBER_Pos) ///< Bit mask of PARTNUMBER field.
/**@brief HW_REVISON register bitfields.
*/
#define NRF21540_HW_REVISON_HW_REVISION_Pos 4 ///< Position of HW_REVISON field.
#define NRF21540_HW_REVISON_HW_REVISION_Msk (0xF << NRF21540_HW_REVISON_HW_REVISION_Pos) ///< Bit mask of HW_REVISON field.
/**@brief HW_ID0 register bitfields.
*/
#define NRF21540_HW_ID0_Pos 0 ///< Position of HW_ID0 field.
#define NRF21540_HW_ID0_Msk (0xFF << NRF21540_HW_ID0_Pos) ///< Bit mask of HW_ID0 field.
/**@brief HW_ID1 register bitfields.
*/
#define NRF21540_HW_ID1_Pos 0 ///< Position of HW_ID1 field.
#define NRF21540_HW_ID1_Msk (0xFF << NRF21540_HW_ID1_Pos) ///< Bit mask of HW_ID1 field.
/**@brief nRF21540 internal registers.
*/
typedef enum
{
NRF21540_REG_CONFREG0 = 0x00, ///< CONFREG0 register address.
NRF21540_REG_CONFREG1 = 0x01, ///< CONFREG1 register address.
NRF21540_REG_CONFREG2 = 0x02, ///< CONFREG2 register address.
NRF21540_REG_CONFREG3 = 0x03, ///< CONFREG3 register address.
NRF21540_REG_PARTNUMBER = 0x14, ///< PARTNUMBER register address.
NRF21540_REG_HW_REVISION = 0x15, ///< HW_REVISION register address.
NRF21540_REG_HW_ID0 = 0x16, ///< HW_ID0 register address.
NRF21540_REG_HW_ID1 = 0x17, ///< HW_ID1 register address.
} nrf21540_reg_t;
/**@brief Function initializes SPI interface.
*
* @return NRF_ERROR_INTERNAL when SPIM driver initialization error occured.
* NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
* to perform the operation.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_spi_init(void);
/**@brief Function returns address of task which triggers SPI transfer.
*
* @return address of appropriate task.
*/
uint32_t nrf21540_spim_trx_task_start_address_get(void);
/**@brief Function configures the chip and peripherals for TX/RX transfer purpose.
*
* @details It can enable/disable RX/TX transfers.
*
* @param[in] dir Direction of the radio transmission. See @ref nrf21540_trx_t.
* @param[in] required_state State of RX/TX transfer. See @ref nrf21540_bool_state_t.
* chosen transfer type.
*/
void nrf21540_spim_for_trx_configure(nrf21540_trx_t dir, nrf21540_bool_state_t required_state);
/**@brief Function choses one of predefined power modes in nRF21540.
*
* @details Refer to nRF21540 Objective Product Specification, section: TX power control.
*
* @param[in] mode Power mode. See @ref nrf21540_pwr_mode_t.
* @return NRF_ERROR_INVALID_PARAM when invalid argument given.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_spi_pwr_mode_set(nrf21540_pwr_mode_t mode);
/**@brief Function sets nRF21540 power state by driving PDN pin.
*
* @param[in] state Required PDN pin state.
* @param[in] mode Execution mode. See @ref nrf21540_execution_mode_t.
* @return NRF_ERROR_INVALID_PARAM when invalid argument given.
* NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
* to perform the operation (@sa nrf21540_state_t).
* NRF_ERROR_INTERNAL when driver is in error state.
* Reinitialization is required.
* NRF_SUCCESS on success.
*/
ret_code_t nrf21540_pdn_drive(bool state, nrf21540_execution_mode_t mode);
#ifdef __cplusplus
}
#endif
#endif // NRF21540_SPI_H_

View File

@@ -0,0 +1,111 @@
/**
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF21540_TYPES_H_
#define NRF21540_TYPES_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
*
* @defgroup nrf21540_types nRF21540 front-end Bluetooth range extender types
* @{
* @ingroup nrf21540
*/
/**@brief Value used as event zero-address - for immediate function execution.
* This is useful in functions with 'user_trigger_event' input parameter.
*/
#define NRF21540_EXECUTE_NOW ((uint32_t)0)
/**@brief nRF21540 antenna outputs.
*
* @note Read more in the Product Specification.
*/
typedef enum
{
NRF21540_ANT1, ///< Antenna 1 output.
NRF21540_ANT2 ///< Antenna 2 output.
} nrf21540_antenna_t;
/**@brief nRF21540 power modes.
*
* @note Read more in the Product Specification.
*/
typedef enum
{
NRF21540_PWR_MODE_A, ///< Power mode A.
NRF21540_PWR_MODE_B ///< Power mode B.
} nrf21540_pwr_mode_t;
/**@brief nRF21540 transmission direction modes.
*/
typedef enum
{
NRF21540_TX, ///< Transmission direction mode transmit.
NRF21540_RX ///< Transmission direction mode receive.
} nrf21540_trx_t;
/**@brief State type for nRF21540 purposes.
*/
typedef enum
{
NRF21540_DISABLE, ///< State disable.
NRF21540_ENABLE ///< State enable.
} nrf21540_bool_state_t;
/**@brief Modes (blocking/non-blocking) for nRF21540 purposes.
*/
typedef enum
{
NRF21540_EXEC_MODE_NON_BLOCKING, ///< Non-blocking execution mode.
NRF21540_EXEC_MODE_BLOCKING ///< Blocking execution mode.
} nrf21540_execution_mode_t;
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF21540_TYPES_H_