初始版本
This commit is contained in:
159
modules/nrfx/drivers/include/nrf_bitmask.h
Normal file
159
modules/nrfx/drivers/include/nrf_bitmask.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 NRF_BITMASK_H
|
||||
#define NRF_BITMASK_H
|
||||
|
||||
#include <nrfx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrf_bitmask Bitmask module
|
||||
* @{
|
||||
* @ingroup nrfx
|
||||
* @brief Bitmask managing module.
|
||||
*/
|
||||
|
||||
/** @brief Macro for getting index of byte in byte stream where @c abs_bit is put. */
|
||||
#define BITMASK_BYTE_GET(abs_bit) ((abs_bit)/8)
|
||||
|
||||
/** @brief Macro for getting relative index of bit in byte. */
|
||||
#define BITMASK_RELBIT_GET(abs_bit) ((abs_bit) & 0x00000007)
|
||||
|
||||
/**
|
||||
* @brief Function for checking if bit in the multi-byte bit mask is set.
|
||||
*
|
||||
* @param[in] bit Bit index.
|
||||
* @param[in] p_mask Pointer to mask with bit fields.
|
||||
*
|
||||
* @return 0 if bit is not set, positive value otherwise.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrf_bitmask_bit_is_set(uint32_t bit, void const * p_mask)
|
||||
{
|
||||
uint8_t const * p_mask8 = (uint8_t const *)p_mask;
|
||||
uint32_t byte_idx = BITMASK_BYTE_GET(bit);
|
||||
bit = BITMASK_RELBIT_GET(bit);
|
||||
return (1 << bit) & p_mask8[byte_idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for setting a bit in the multi-byte bit mask.
|
||||
*
|
||||
* @param[in] bit Bit index.
|
||||
* @param[in] p_mask Pointer to mask with bit fields.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_bitmask_bit_set(uint32_t bit, void * p_mask)
|
||||
{
|
||||
uint8_t * p_mask8 = (uint8_t *)p_mask;
|
||||
uint32_t byte_idx = BITMASK_BYTE_GET(bit);
|
||||
bit = BITMASK_RELBIT_GET(bit);
|
||||
p_mask8[byte_idx] |= (1 << bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for clearing a bit in the multi-byte bit mask.
|
||||
*
|
||||
* @param[in] bit Bit index.
|
||||
* @param[in] p_mask Pointer to mask with bit fields.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_bitmask_bit_clear(uint32_t bit, void * p_mask)
|
||||
{
|
||||
uint8_t * p_mask8 = (uint8_t *)p_mask;
|
||||
uint32_t byte_idx = BITMASK_BYTE_GET(bit);
|
||||
bit = BITMASK_RELBIT_GET(bit);
|
||||
p_mask8[byte_idx] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for performing bitwise OR operation on two multi-byte bit masks.
|
||||
*
|
||||
* @param[in] p_mask1 Pointer to the first bit mask.
|
||||
* @param[in] p_mask2 Pointer to the second bit mask.
|
||||
* @param[in] p_out_mask Pointer to the output bit mask.
|
||||
* @param[in] length Length of output mask in bytes.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_bitmask_masks_or(void const * p_mask1,
|
||||
void const * p_mask2,
|
||||
void * p_out_mask,
|
||||
uint32_t length)
|
||||
{
|
||||
uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1;
|
||||
uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2;
|
||||
uint8_t * p_mask8_out = (uint8_t *)p_out_mask;
|
||||
uint32_t i;
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
p_mask8_out[i] = p_mask8_1[i] | p_mask8_2[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for performing bitwise AND operation on two multi-byte bit masks.
|
||||
*
|
||||
* @param[in] p_mask1 Pointer to the first bit mask.
|
||||
* @param[in] p_mask2 Pointer to the second bit mask.
|
||||
* @param[in] p_out_mask Pointer to the output bit mask.
|
||||
* @param[in] length Length of output mask in bytes.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_bitmask_masks_and(void const * p_mask1,
|
||||
void const * p_mask2,
|
||||
void * p_out_mask,
|
||||
uint32_t length)
|
||||
{
|
||||
uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1;
|
||||
uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2;
|
||||
uint8_t * p_mask8_out = (uint8_t *)p_out_mask;
|
||||
uint32_t i;
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
p_mask8_out[i] = p_mask8_1[i] & p_mask8_2[i];
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_BITMASK_H
|
||||
289
modules/nrfx/drivers/include/nrfx_adc.h
Normal file
289
modules/nrfx/drivers/include/nrfx_adc.h
Normal file
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_ADC_H__
|
||||
#define NRFX_ADC_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_adc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_adc ADC driver
|
||||
* @{
|
||||
* @ingroup nrf_adc
|
||||
* @brief Analog-to-Digital Converter (ADC) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Driver event types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_ADC_EVT_DONE, ///< Event generated when the buffer is filled with samples.
|
||||
NRFX_ADC_EVT_SAMPLE, ///< Event generated when the requested channel is sampled.
|
||||
} nrfx_adc_evt_type_t;
|
||||
|
||||
/** @brief ADC driver DONE event structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_adc_value_t * p_buffer; ///< Pointer to the buffer with converted samples.
|
||||
uint16_t size; ///< Number of samples in the buffer.
|
||||
} nrfx_adc_done_evt_t;
|
||||
|
||||
/** @brief SAMPLE event structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_adc_value_t sample; ///< Converted sample.
|
||||
} nrfx_adc_sample_evt_t;
|
||||
|
||||
/** @brief ADC driver event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_adc_evt_type_t type; ///< Event type.
|
||||
union
|
||||
{
|
||||
nrfx_adc_done_evt_t done; ///< Data for DONE event.
|
||||
nrfx_adc_sample_evt_t sample; ///< Data for SAMPLE event.
|
||||
} data; ///< Union to store event data.
|
||||
} nrfx_adc_evt_t;
|
||||
|
||||
/** @brief Macro for initializing the ADC channel with the default configuration. */
|
||||
#define NRFX_ADC_DEFAULT_CHANNEL(analog_input) \
|
||||
{ \
|
||||
NULL, \
|
||||
{ \
|
||||
.resolution = NRF_ADC_CONFIG_RES_10BIT, \
|
||||
.scaling = NRF_ADC_CONFIG_SCALING_INPUT_FULL_SCALE, \
|
||||
.reference = NRF_ADC_CONFIG_REF_VBG, \
|
||||
.input = (analog_input), \
|
||||
.extref = NRF_ADC_CONFIG_EXTREFSEL_NONE \
|
||||
} \
|
||||
}
|
||||
|
||||
/** @brief Forward declaration of the nrfx_adc_channel_t type. */
|
||||
typedef struct nrfx_adc_channel_s nrfx_adc_channel_t;
|
||||
|
||||
/**
|
||||
* @brief ADC channel.
|
||||
*
|
||||
* This structure is defined by the user and used by the driver. Therefore, it should
|
||||
* not be defined on the stack as a local variable.
|
||||
*/
|
||||
struct nrfx_adc_channel_s
|
||||
{
|
||||
nrfx_adc_channel_t * p_next; ///< Pointer to the next enabled channel (for internal use).
|
||||
nrf_adc_config_t config; ///< ADC configuration for the current channel.
|
||||
};
|
||||
|
||||
/** @brief ADC configuration. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t interrupt_priority; ///< Priority of ADC interrupt.
|
||||
} nrfx_adc_config_t;
|
||||
|
||||
/** @brief ADC default configuration. */
|
||||
#define NRFX_ADC_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.interrupt_priority = NRFX_ADC_CONFIG_IRQ_PRIORITY \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief User event handler prototype.
|
||||
*
|
||||
* This function is called when the requested number of samples has been processed.
|
||||
*
|
||||
* @param p_event Event.
|
||||
*/
|
||||
typedef void (*nrfx_adc_event_handler_t)(nrfx_adc_evt_t const * p_event);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the ADC.
|
||||
*
|
||||
* If a valid event handler is provided, the driver is initialized in non-blocking mode.
|
||||
* If event_handler is NULL, the driver works in blocking mode.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_adc_init(nrfx_adc_config_t const * p_config,
|
||||
nrfx_adc_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the ADC.
|
||||
*
|
||||
* This function stops all ongoing conversions and disables all channels.
|
||||
*/
|
||||
void nrfx_adc_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling an ADC channel.
|
||||
*
|
||||
* This function configures and enables the channel. When @ref nrfx_adc_buffer_convert is
|
||||
* called, all channels that have been enabled with this function are sampled.
|
||||
*
|
||||
* This function can be called only when there is no conversion in progress
|
||||
* (the ADC is not busy).
|
||||
*
|
||||
* @note The channel instance variable @p p_channel is used by the driver as an item
|
||||
* in a list. Therefore, it cannot be an automatic variable that is located on the stack.
|
||||
*
|
||||
* @param[in] p_channel Pointer to the channel instance.
|
||||
*/
|
||||
void nrfx_adc_channel_enable(nrfx_adc_channel_t * const p_channel);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling an ADC channel.
|
||||
*
|
||||
* This function can be called only when there is no conversion in progress
|
||||
* (the ADC is not busy).
|
||||
*
|
||||
* @param p_channel Pointer to the channel instance.
|
||||
*/
|
||||
void nrfx_adc_channel_disable(nrfx_adc_channel_t * const p_channel);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling all ADC channels.
|
||||
*
|
||||
* This function can be called only when there is no conversion in progress
|
||||
* (the ADC is not busy).
|
||||
*/
|
||||
void nrfx_adc_all_channels_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for starting ADC sampling.
|
||||
*
|
||||
* This function triggers single ADC sampling. If more than one channel is enabled, the driver
|
||||
* emulates scanning and all channels are sampled in the order they were enabled.
|
||||
*/
|
||||
void nrfx_adc_sample(void);
|
||||
|
||||
/**
|
||||
* @brief Function for executing a single ADC conversion.
|
||||
*
|
||||
* This function selects the desired input and starts a single conversion. If a valid pointer
|
||||
* is provided for the result, the function blocks until the conversion is completed. Otherwise, the
|
||||
* function returns when the conversion is started, and the result is provided in an event (driver
|
||||
* must be initialized in non-blocking mode, otherwise an assertion will fail). The function will
|
||||
* fail if ADC is busy. The channel does not need to be enabled to perform a single conversion.
|
||||
*
|
||||
* @param[in] p_channel Channel.
|
||||
* @param[out] p_value Pointer to the location where the result is to be placed. Unless NULL is
|
||||
* provided, the function is blocking.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Conversion was successful.
|
||||
* @retval NRFX_ERROR_BUSY The ADC driver is busy.
|
||||
*/
|
||||
nrfx_err_t nrfx_adc_sample_convert(nrfx_adc_channel_t const * const p_channel,
|
||||
nrf_adc_value_t * p_value);
|
||||
|
||||
/**
|
||||
* @brief Function for converting data to the buffer.
|
||||
*
|
||||
* If the driver is initialized in non-blocking mode, this function returns when the first
|
||||
* conversion is set up. When the buffer is filled, the application is notified by the event
|
||||
* handler. If the driver is initialized in blocking mode, the function returns when the buffer is
|
||||
* filled.
|
||||
*
|
||||
* Conversion is done on all enabled channels, but it is not triggered by this
|
||||
* function. This function will prepare the ADC for sampling and then
|
||||
* wait for the SAMPLE task. Sampling can be triggered manually by the @ref
|
||||
* nrfx_adc_sample function or by PPI using the @ref NRF_ADC_TASK_START task.
|
||||
*
|
||||
* @note If more than one channel is enabled, the function emulates scanning, and
|
||||
* a single START task will trigger conversion on all enabled channels. For example:
|
||||
* If 3 channels are enabled and the user requests 6 samples, the completion event
|
||||
* handler will be called after 2 START tasks.
|
||||
*
|
||||
* @note The application must adjust the sampling frequency. The maximum frequency
|
||||
* depends on the sampling timer and the maximum latency of the ADC interrupt. If
|
||||
* an interrupt is not handled before the next sampling is triggered, the sample
|
||||
* will be lost.
|
||||
*
|
||||
* @param[in] buffer Result buffer.
|
||||
* @param[in] size Buffer size in samples.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Conversion was successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is busy.
|
||||
*/
|
||||
nrfx_err_t nrfx_adc_buffer_convert(nrf_adc_value_t * buffer, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief Function for retrieving the ADC state.
|
||||
*
|
||||
* @retval true The ADC is busy.
|
||||
* @retval false The ADC is ready.
|
||||
*/
|
||||
bool nrfx_adc_is_busy(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the ADC START task.
|
||||
*
|
||||
* This function is used to get the address of the START task, which can be used to trigger ADC
|
||||
* conversion.
|
||||
*
|
||||
* @return Start task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_adc_start_task_get(void);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_adc_start_task_get(void)
|
||||
{
|
||||
return nrf_adc_task_address_get(NRF_ADC_TASK_START);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_adc_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_ADC_H__
|
||||
206
modules/nrfx/drivers/include/nrfx_clock.h
Normal file
206
modules/nrfx/drivers/include/nrfx_clock.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 NRFX_CLOCK_H__
|
||||
#define NRFX_CLOCK_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_clock.h>
|
||||
#include <nrfx_power_clock.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_clock CLOCK driver
|
||||
* @{
|
||||
* @ingroup nrf_clock
|
||||
* @brief CLOCK peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Clock events. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started.
|
||||
NRFX_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started.
|
||||
NRFX_CLOCK_EVT_CTTO, ///< Calibration timeout.
|
||||
NRFX_CLOCK_EVT_CAL_DONE ///< Calibration has been done.
|
||||
} nrfx_clock_evt_type_t;
|
||||
|
||||
/**
|
||||
* @brief Clock event handler.
|
||||
*
|
||||
* @param[in] event Event.
|
||||
*/
|
||||
typedef void (*nrfx_clock_event_handler_t)(nrfx_clock_evt_type_t event);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing internal structures in the nrfx_clock module.
|
||||
*
|
||||
* After initialization, the module is in power off state (clocks are not started).
|
||||
*
|
||||
* @param[in] event_handler Event handler provided by the user.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_ALREADY_INITIALIZED The driver is already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler);
|
||||
|
||||
/** @brief Function for enabling interrupts in the clock module. */
|
||||
void nrfx_clock_enable(void);
|
||||
|
||||
/** @brief Function for disabling interrupts in the clock module. */
|
||||
void nrfx_clock_disable(void);
|
||||
|
||||
/** @brief Function for uninitializing the clock module. */
|
||||
void nrfx_clock_uninit(void);
|
||||
|
||||
/** @brief Function for starting the LFCLK. */
|
||||
void nrfx_clock_lfclk_start(void);
|
||||
|
||||
/** @brief Function for stopping the LFCLK. */
|
||||
void nrfx_clock_lfclk_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Function for checking the LFCLK state.
|
||||
*
|
||||
* @retval true The LFCLK is running.
|
||||
* @retval false The LFCLK is not running.
|
||||
*/
|
||||
__STATIC_INLINE bool nrfx_clock_lfclk_is_running(void);
|
||||
|
||||
/** @brief Function for starting the high-accuracy source HFCLK. */
|
||||
void nrfx_clock_hfclk_start(void);
|
||||
|
||||
/** @brief Function for stopping the external high-accuracy source HFCLK. */
|
||||
void nrfx_clock_hfclk_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Function for checking the HFCLK state.
|
||||
*
|
||||
* @retval true The HFCLK is running (XTAL source).
|
||||
* @retval false The HFCLK is not running.
|
||||
*/
|
||||
__STATIC_INLINE bool nrfx_clock_hfclk_is_running(void);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the calibration of internal LFCLK.
|
||||
*
|
||||
* This function starts the calibration process. The process cannot be aborted. LFCLK and HFCLK
|
||||
* must be running before this function is called.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The low-frequency of high-frequency clock is off.
|
||||
* @retval NRFX_ERROR_BUSY Clock is in the calibration phase.
|
||||
*/
|
||||
nrfx_err_t nrfx_clock_calibration_start(void);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if calibration is in progress.
|
||||
*
|
||||
* This function indicates that the system is in calibration phase.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY Clock is in the calibration phase.
|
||||
*/
|
||||
nrfx_err_t nrfx_clock_is_calibrating(void);
|
||||
|
||||
/**
|
||||
* @brief Function for starting calibration timer.
|
||||
*
|
||||
* @param[in] interval Time after which the CTTO event and interrupt will be generated (in 0.25 s units).
|
||||
*/
|
||||
void nrfx_clock_calibration_timer_start(uint8_t interval);
|
||||
|
||||
/** @brief Function for stopping the calibration timer. */
|
||||
void nrfx_clock_calibration_timer_stop(void);
|
||||
|
||||
/**@brief Function for returning a requested task address for the clock driver module.
|
||||
*
|
||||
* @param[in] task One of the peripheral tasks.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_clock_ppi_task_addr(nrf_clock_task_t task);
|
||||
|
||||
/**@brief Function for returning a requested event address for the clock driver module.
|
||||
*
|
||||
* @param[in] event One of the peripheral events.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_clock_ppi_event_addr(nrf_clock_event_t event);
|
||||
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE uint32_t nrfx_clock_ppi_task_addr(nrf_clock_task_t task)
|
||||
{
|
||||
return nrf_clock_task_address_get(task);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_clock_ppi_event_addr(nrf_clock_event_t event)
|
||||
{
|
||||
return nrf_clock_event_address_get(event);
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool nrfx_clock_hfclk_is_running(void)
|
||||
{
|
||||
return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY);
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool nrfx_clock_lfclk_is_running(void)
|
||||
{
|
||||
return nrf_clock_lf_is_running();
|
||||
}
|
||||
#endif //SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_clock_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CLOCK_H__
|
||||
248
modules/nrfx/drivers/include/nrfx_comp.h
Normal file
248
modules/nrfx/drivers/include/nrfx_comp.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_COMP_H__
|
||||
#define NRFX_COMP_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_comp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_comp COMP driver
|
||||
* @{
|
||||
* @ingroup nrf_comp
|
||||
* @brief Comparator (COMP) peripheral driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Macro for converting the threshold voltage to an integer value
|
||||
* (needed by the COMP_TH register).
|
||||
*
|
||||
* @param[in] vol Voltage to be changed to COMP_TH register value. This value
|
||||
* must not be smaller than reference voltage divided by 64.
|
||||
* @param[in] ref Reference voltage.
|
||||
*/
|
||||
#define NRFX_VOLTAGE_THRESHOLD_TO_INT(vol, ref) \
|
||||
(uint8_t)(((vol) > ((ref) / 64)) ? (NRFX_ROUNDED_DIV((vol) * 64,(ref)) - 1) : 0)
|
||||
|
||||
/**
|
||||
* @brief COMP event handler function type.
|
||||
*
|
||||
* @param[in] event COMP event.
|
||||
*/
|
||||
typedef void (* nrfx_comp_event_handler_t)(nrf_comp_event_t event);
|
||||
|
||||
/** @brief COMP shortcut masks. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_COMP_SHORT_STOP_AFTER_CROSS_EVT = COMP_SHORTS_CROSS_STOP_Msk, /*!< Shortcut between the CROSS event and the STOP task. */
|
||||
NRFX_COMP_SHORT_STOP_AFTER_UP_EVT = COMP_SHORTS_UP_STOP_Msk, /*!< Shortcut between the UP event and the STOP task. */
|
||||
NRFX_COMP_SHORT_STOP_AFTER_DOWN_EVT = COMP_SHORTS_DOWN_STOP_Msk /*!< Shortcut between the DOWN event and the STOP task. */
|
||||
} nrfx_comp_short_mask_t;
|
||||
|
||||
/** @brief COMP events masks. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_COMP_EVT_EN_CROSS_MASK = COMP_INTENSET_CROSS_Msk, /*!< CROSS event (generated after VIN+ == VIN-). */
|
||||
NRFX_COMP_EVT_EN_UP_MASK = COMP_INTENSET_UP_Msk, /*!< UP event (generated when VIN+ crosses VIN- while increasing). */
|
||||
NRFX_COMP_EVT_EN_DOWN_MASK = COMP_INTENSET_DOWN_Msk, /*!< DOWN event (generated when VIN+ crosses VIN- while decreasing). */
|
||||
NRFX_COMP_EVT_EN_READY_MASK = COMP_INTENSET_READY_Msk /*!< READY event (generated when the module is ready). */
|
||||
} nrfx_comp_evt_en_mask_t;
|
||||
|
||||
/** @brief COMP configuration. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_comp_ref_t reference; /**< Reference selection. */
|
||||
nrf_comp_ext_ref_t ext_ref; /**< External analog reference selection. */
|
||||
nrf_comp_main_mode_t main_mode; /**< Main operation mode. */
|
||||
nrf_comp_th_t threshold; /**< Structure holding THDOWN and THUP values needed by the COMP_TH register. */
|
||||
nrf_comp_sp_mode_t speed_mode; /**< Speed and power mode. */
|
||||
nrf_comp_hyst_t hyst; /**< Comparator hysteresis. */
|
||||
#if defined (COMP_ISOURCE_ISOURCE_Msk) || defined (__NRFX_DOXYGEN__)
|
||||
nrf_isource_t isource; /**< Current source selected on analog input. */
|
||||
#endif
|
||||
nrf_comp_input_t input; /**< Input to be monitored. */
|
||||
uint8_t interrupt_priority; /**< Interrupt priority. */
|
||||
} nrfx_comp_config_t;
|
||||
|
||||
/** @brief COMP threshold default configuration. */
|
||||
#define NRFX_COMP_CONFIG_TH \
|
||||
{ \
|
||||
.th_down = NRFX_VOLTAGE_THRESHOLD_TO_INT(0.5, 1.8), \
|
||||
.th_up = NRFX_VOLTAGE_THRESHOLD_TO_INT(1.5, 1.8) \
|
||||
}
|
||||
|
||||
/** @brief COMP driver default configuration including the COMP HAL configuration. */
|
||||
#if defined (COMP_ISOURCE_ISOURCE_Msk) || defined (__NRFX_DOXYGEN__)
|
||||
#define NRFX_COMP_DEFAULT_CONFIG(_input) \
|
||||
{ \
|
||||
.reference = (nrf_comp_ref_t)NRFX_COMP_CONFIG_REF, \
|
||||
.ext_ref = NRF_COMP_EXT_REF_0, \
|
||||
.main_mode = (nrf_comp_main_mode_t)NRFX_COMP_CONFIG_MAIN_MODE, \
|
||||
.threshold = NRFX_COMP_CONFIG_TH, \
|
||||
.speed_mode = (nrf_comp_sp_mode_t)NRFX_COMP_CONFIG_SPEED_MODE, \
|
||||
.hyst = (nrf_comp_hyst_t)NRFX_COMP_CONFIG_HYST, \
|
||||
.isource = (nrf_isource_t)NRFX_COMP_CONFIG_ISOURCE, \
|
||||
.input = (nrf_comp_input_t)_input, \
|
||||
.interrupt_priority = NRFX_COMP_CONFIG_IRQ_PRIORITY \
|
||||
}
|
||||
#else
|
||||
#define NRFX_COMP_DEFAULT_CONFIG(_input) \
|
||||
{ \
|
||||
.reference = (nrf_comp_ref_t)NRFX_COMP_CONFIG_REF, \
|
||||
.ext_ref = NRF_COMP_EXT_REF_0, \
|
||||
.main_mode = (nrf_comp_main_mode_t)NRFX_COMP_CONFIG_MAIN_MODE, \
|
||||
.threshold = NRFX_COMP_CONFIG_TH, \
|
||||
.speed_mode = (nrf_comp_sp_mode_t)NRFX_COMP_CONFIG_SPEED_MODE, \
|
||||
.hyst = (nrf_comp_hyst_t)NRFX_COMP_CONFIG_HYST, \
|
||||
.input = (nrf_comp_input_t)_input, \
|
||||
.interrupt_priority = NRFX_COMP_CONFIG_IRQ_PRIORITY \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the COMP driver.
|
||||
*
|
||||
* This function initializes the COMP driver, but does not enable the peripheral or any interrupts.
|
||||
* To start the driver, call the function @ref nrfx_comp_start() after initialization.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver has already been initialized.
|
||||
* @retval NRFX_ERROR_BUSY The LPCOMP peripheral is already in use.
|
||||
* This is possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_comp_init(nrfx_comp_config_t const * p_config,
|
||||
nrfx_comp_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the COMP driver.
|
||||
*
|
||||
* This function uninitializes the COMP driver. The COMP peripheral and
|
||||
* its interrupts are disabled, and local variables are cleaned. After this call, you must
|
||||
* initialize the driver again by calling nrfx_comp_init() if you want to use it.
|
||||
*
|
||||
* @sa nrfx_comp_stop
|
||||
*/
|
||||
void nrfx_comp_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the analog input.
|
||||
*
|
||||
* @param[in] psel COMP analog pin selection.
|
||||
*/
|
||||
void nrfx_comp_pin_select(nrf_comp_input_t psel);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the COMP peripheral and interrupts.
|
||||
*
|
||||
* Before calling this function, the driver must be initialized. This function
|
||||
* enables the COMP peripheral and its interrupts.
|
||||
*
|
||||
* @param[in] comp_evt_en_mask Mask of events to be enabled. This parameter is to be built as
|
||||
* an OR of elements from @ref nrfx_comp_evt_en_mask_t.
|
||||
* @param[in] comp_shorts_mask Mask of shortcuts to be enabled. This parameter is to be built as
|
||||
* an OR of elements from @ref nrfx_comp_short_mask_t.
|
||||
*
|
||||
* @sa nrfx_comp_init
|
||||
*/
|
||||
void nrfx_comp_start(uint32_t comp_evt_en_mask, uint32_t comp_shorts_mask);
|
||||
|
||||
/**
|
||||
* @brief Function for stopping the COMP peripheral.
|
||||
*
|
||||
* Before calling this function, the driver must be enabled. This function disables the COMP
|
||||
* peripheral and its interrupts.
|
||||
*
|
||||
* @sa nrfx_comp_uninit
|
||||
*/
|
||||
void nrfx_comp_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Function for copying the current state of the comparator result to the RESULT register.
|
||||
*
|
||||
* @retval 0 The input voltage is below the threshold (VIN+ < VIN-).
|
||||
* @retval 1 The input voltage is above the threshold (VIN+ > VIN-).
|
||||
*/
|
||||
uint32_t nrfx_comp_sample(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of a COMP task.
|
||||
*
|
||||
* @param[in] task COMP task.
|
||||
*
|
||||
* @return Address of the given COMP task.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_comp_task_address_get(nrf_comp_task_t task)
|
||||
{
|
||||
return (uint32_t)nrf_comp_task_address_get(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of a COMP event.
|
||||
*
|
||||
* @param[in] event COMP event.
|
||||
*
|
||||
* @return Address of the given COMP event.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_comp_event_address_get(nrf_comp_event_t event)
|
||||
{
|
||||
return (uint32_t)nrf_comp_event_address_get(event);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_comp_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_COMP_H__
|
||||
185
modules/nrfx/drivers/include/nrfx_dppi.h
Normal file
185
modules/nrfx/drivers/include/nrfx_dppi.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* Copyright (c) 2018 - 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 NRFX_DPPI_H__
|
||||
#define NRFX_DPPI_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_dppi.h>
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_dppi DPPI allocator
|
||||
* @{
|
||||
* @ingroup nrf_dppi
|
||||
* @brief Distributed Programmable Peripheral Interconnect (DPPI) allocator.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Function for freeing all allocated channels and groups. */
|
||||
void nrfx_dppi_free(void);
|
||||
|
||||
/**
|
||||
* @brief Function for allocating a DPPI channel.
|
||||
* @details This function allocates the first unused DPPI channel.
|
||||
*
|
||||
* @param[out] p_channel Pointer to the DPPI channel number that has been allocated.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully allocated.
|
||||
* @retval NRFX_ERROR_NO_MEM There is no available channel to be used.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_channel_alloc(uint8_t * p_channel);
|
||||
|
||||
/**
|
||||
* @brief Function for freeing a DPPI channel.
|
||||
* @details This function also disables the chosen channel.
|
||||
*
|
||||
* @param[in] channel DPPI channel to be freed.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully freed.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified channel is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_channel_free(uint8_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling a DPPI channel.
|
||||
*
|
||||
* @param[in] channel DPPI channel to be enabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully enabled.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified channel is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_channel_enable(uint8_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling a DPPI channel.
|
||||
*
|
||||
* @param[in] channel DPPI channel to be disabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully disabled.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified channel is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_channel_disable(uint8_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for allocating a DPPI channel group.
|
||||
* @details This function allocates the first unused DPPI group.
|
||||
*
|
||||
* @param[out] p_group Pointer to the DPPI channel group that has been allocated.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel group was successfully allocated.
|
||||
* @retval NRFX_ERROR_NO_MEM There is no available channel group to be used.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_group_alloc(nrf_dppi_channel_group_t * p_group);
|
||||
|
||||
/**
|
||||
* @brief Function for freeing a DPPI channel group.
|
||||
* @details This function also disables the chosen group.
|
||||
*
|
||||
* @param[in] group DPPI channel group to be freed.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel group was successfully freed.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified group is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_group_free(nrf_dppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for including a DPPI channel in a channel group.
|
||||
*
|
||||
* @param[in] channel DPPI channel to be added.
|
||||
* @param[in] group Channel group in which to include the channel.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully included.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified group or channel is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_channel_include_in_group(uint8_t channel,
|
||||
nrf_dppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for removing a DPPI channel from a channel group.
|
||||
*
|
||||
* @param[in] channel DPPI channel to be removed.
|
||||
* @param[in] group Channel group from which to remove the channel.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully removed.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified group or channel is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_channel_remove_from_group(uint8_t channel,
|
||||
nrf_dppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for clearing a DPPI channel group.
|
||||
*
|
||||
* @param[in] group Channel group to be cleared.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The group was successfully cleared.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified group is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_group_clear(nrf_dppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling a DPPI channel group.
|
||||
*
|
||||
* @param[in] group Channel group to be enabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The group was successfully enabled.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified group is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_group_enable(nrf_dppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling a DPPI channel group.
|
||||
*
|
||||
* @param[in] group Channel group to be disabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The group was successfully disabled.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The specified group is not allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_dppi_group_disable(nrf_dppi_channel_group_t group);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_DPPI_H__
|
||||
494
modules/nrfx/drivers/include/nrfx_gpiote.h
Normal file
494
modules/nrfx/drivers/include/nrfx_gpiote.h
Normal file
@@ -0,0 +1,494 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_GPIOTE_H__
|
||||
#define NRFX_GPIOTE_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_gpiote.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_gpiote GPIOTE driver
|
||||
* @{
|
||||
* @ingroup nrf_gpiote
|
||||
* @brief GPIO Task Event (GPIOTE) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Input pin configuration. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_gpiote_polarity_t sense; /**< Transition that triggers the interrupt. */
|
||||
nrf_gpio_pin_pull_t pull; /**< Pulling mode. */
|
||||
bool is_watcher : 1; /**< True when the input pin is tracking an output pin. */
|
||||
bool hi_accuracy : 1; /**< True when high accuracy (IN_EVENT) is used. */
|
||||
bool skip_gpio_setup : 1; /**< Do not change GPIO configuration */
|
||||
} nrfx_gpiote_in_config_t;
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition.
|
||||
* @details Set hi_accu to true to use IN_EVENT.
|
||||
*/
|
||||
#define NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(hi_accu) \
|
||||
{ \
|
||||
.sense = NRF_GPIOTE_POLARITY_LOTOHI, \
|
||||
.pull = NRF_GPIO_PIN_NOPULL, \
|
||||
.is_watcher = false, \
|
||||
.hi_accuracy = hi_accu, \
|
||||
.skip_gpio_setup = false, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition.
|
||||
* @details Set hi_accu to true to use IN_EVENT.
|
||||
*/
|
||||
#define NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(hi_accu) \
|
||||
{ \
|
||||
.sense = NRF_GPIOTE_POLARITY_HITOLO, \
|
||||
.pull = NRF_GPIO_PIN_NOPULL, \
|
||||
.is_watcher = false, \
|
||||
.hi_accuracy = hi_accu, \
|
||||
.skip_gpio_setup = false, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin.
|
||||
* @details Set hi_accu to true to use IN_EVENT.
|
||||
*/
|
||||
#define NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(hi_accu) \
|
||||
{ \
|
||||
.sense = NRF_GPIOTE_POLARITY_TOGGLE, \
|
||||
.pull = NRF_GPIO_PIN_NOPULL, \
|
||||
.is_watcher = false, \
|
||||
.hi_accuracy = hi_accu, \
|
||||
.skip_gpio_setup = false, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition.
|
||||
* @details Set hi_accu to true to use IN_EVENT.
|
||||
* @note This macro prepares configuration that skips the GPIO setup.
|
||||
*/
|
||||
#define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI(hi_accu) \
|
||||
{ \
|
||||
.sense = NRF_GPIOTE_POLARITY_LOTOHI, \
|
||||
.pull = NRF_GPIO_PIN_NOPULL, \
|
||||
.is_watcher = false, \
|
||||
.hi_accuracy = hi_accu, \
|
||||
.skip_gpio_setup = true, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition.
|
||||
* @details Set hi_accu to true to use IN_EVENT.
|
||||
* @note This macro prepares configuration that skips the GPIO setup.
|
||||
*/
|
||||
#define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(hi_accu) \
|
||||
{ \
|
||||
.sense = NRF_GPIOTE_POLARITY_HITOLO, \
|
||||
.pull = NRF_GPIO_PIN_NOPULL, \
|
||||
.is_watcher = false, \
|
||||
.hi_accuracy = hi_accu, \
|
||||
.skip_gpio_setup = true, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin.
|
||||
* @details Set hi_accu to true to use IN_EVENT.
|
||||
* @note This macro prepares configuration that skips the GPIO setup.
|
||||
*/
|
||||
#define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE(hi_accu) \
|
||||
{ \
|
||||
.sense = NRF_GPIOTE_POLARITY_TOGGLE, \
|
||||
.pull = NRF_GPIO_PIN_NOPULL, \
|
||||
.is_watcher = false, \
|
||||
.hi_accuracy = hi_accu, \
|
||||
.skip_gpio_setup = true, \
|
||||
}
|
||||
|
||||
|
||||
/** @brief Output pin configuration. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_gpiote_polarity_t action; /**< Configuration of the pin task. */
|
||||
nrf_gpiote_outinit_t init_state; /**< Initial state of the output pin. */
|
||||
bool task_pin; /**< True if the pin is controlled by a GPIOTE task. */
|
||||
} nrfx_gpiote_out_config_t;
|
||||
|
||||
/** @brief Macro for configuring a pin to use as output. GPIOTE is not used for the pin. */
|
||||
#define NRFX_GPIOTE_CONFIG_OUT_SIMPLE(init_high) \
|
||||
{ \
|
||||
.action = NRF_GPIOTE_POLARITY_LOTOHI, \
|
||||
.init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \
|
||||
.task_pin = false, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from high to low.
|
||||
* @details The task will clear the pin. Therefore, the pin is set initially.
|
||||
*/
|
||||
#define NRFX_GPIOTE_CONFIG_OUT_TASK_LOW \
|
||||
{ \
|
||||
.init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \
|
||||
.task_pin = true, \
|
||||
.action = NRF_GPIOTE_POLARITY_HITOLO, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from low to high.
|
||||
* @details The task will set the pin. Therefore, the pin is cleared initially.
|
||||
*/
|
||||
#define NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH \
|
||||
{ \
|
||||
.action = NRF_GPIOTE_POLARITY_LOTOHI, \
|
||||
.init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \
|
||||
.task_pin = true, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for configuring a pin to use the GPIO OUT TASK to toggle the pin state.
|
||||
* @details The initial pin state must be provided.
|
||||
*/
|
||||
#define NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high) \
|
||||
{ \
|
||||
.action = NRF_GPIOTE_POLARITY_TOGGLE, \
|
||||
.init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \
|
||||
.task_pin = true, \
|
||||
}
|
||||
|
||||
/** @brief Pin. */
|
||||
typedef uint32_t nrfx_gpiote_pin_t;
|
||||
|
||||
/**
|
||||
* @brief Pin event handler prototype.
|
||||
*
|
||||
* @param[in] pin Pin that triggered this event.
|
||||
* @param[in] action Action that led to triggering this event.
|
||||
*/
|
||||
typedef void (*nrfx_gpiote_evt_handler_t)(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the GPIOTE module.
|
||||
*
|
||||
* @details Only static configuration is supported to prevent the shared
|
||||
* resource being customized by the initiator.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_gpiote_init(void);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the GPIOTE module is initialized.
|
||||
*
|
||||
* @details The GPIOTE module is a shared module. Therefore, check if
|
||||
* the module is already initialized and skip initialization if it is.
|
||||
*
|
||||
* @retval true The module is already initialized.
|
||||
* @retval false The module is not initialized.
|
||||
*/
|
||||
bool nrfx_gpiote_is_init(void);
|
||||
|
||||
/** @brief Function for uninitializing the GPIOTE module. */
|
||||
void nrfx_gpiote_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing a GPIOTE output pin.
|
||||
* @details The output pin can be controlled by the CPU or by PPI. The initial
|
||||
* configuration specifies which mode is used. If PPI mode is used, the driver
|
||||
* attempts to allocate one of the available GPIOTE channels. If no channel is
|
||||
* available, an error is returned.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
* @param[in] p_config Initial configuration.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is not initialized or the pin is already used.
|
||||
* @retval NRFX_ERROR_NO_MEM No GPIOTE channel is available.
|
||||
*/
|
||||
nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin,
|
||||
nrfx_gpiote_out_config_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing a GPIOTE output pin.
|
||||
* @details The driver frees the GPIOTE channel if the output pin was using one.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for setting a GPIOTE output pin.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for clearing a GPIOTE output pin.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for toggling a GPIOTE output pin.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling a GPIOTE output pin task.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling a GPIOTE output pin task.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the OUT task for the specified output pin.
|
||||
*
|
||||
* @details The returned task identifier can be used within @ref nrf_gpiote_hal,
|
||||
* for example, to configure a DPPI channel.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return OUT task associated with the specified output pin.
|
||||
*/
|
||||
nrf_gpiote_tasks_t nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the OUT task for the specified output pin.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return Address of OUT task.
|
||||
*/
|
||||
uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin);
|
||||
|
||||
#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for getting the SET task for the specified output pin.
|
||||
*
|
||||
* @details The returned task identifier can be used within @ref nrf_gpiote_hal,
|
||||
* for example, to configure a DPPI channel.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return SET task associated with the specified output pin.
|
||||
*/
|
||||
nrf_gpiote_tasks_t nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the SET task for the specified output pin.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return Address of SET task.
|
||||
*/
|
||||
uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin);
|
||||
#endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for getting the CLR task for the specified output pin.
|
||||
*
|
||||
* @details The returned task identifier can be used within @ref nrf_gpiote_hal,
|
||||
* for example, to configure a DPPI channel.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return CLR task associated with the specified output pin.
|
||||
*/
|
||||
nrf_gpiote_tasks_t nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the SET task for the specified output pin.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return Address of CLR task.
|
||||
*/
|
||||
uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin);
|
||||
#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
/**
|
||||
* @brief Function for initializing a GPIOTE input pin.
|
||||
* @details The input pin can act in two ways:
|
||||
* - lower accuracy but low power (high frequency clock not needed)
|
||||
* - higher accuracy (high frequency clock required)
|
||||
*
|
||||
* The initial configuration specifies which mode is used.
|
||||
* If high-accuracy mode is used, the driver attempts to allocate one
|
||||
* of the available GPIOTE channels. If no channel is
|
||||
* available, an error is returned.
|
||||
* In low accuracy mode SENSE feature is used. In this case, only one active pin
|
||||
* can be detected at a time. It can be worked around by setting all of the used
|
||||
* low accuracy pins to toggle mode.
|
||||
* For more information about SENSE functionality, refer to Product Specification.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
* @param[in] p_config Initial configuration.
|
||||
* @param[in] evt_handler User function to be called when the configured transition occurs.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is not initialized or the pin is already used.
|
||||
* @retval NRFX_ERROR_NO_MEM No GPIOTE channel is available.
|
||||
*/
|
||||
nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,
|
||||
nrfx_gpiote_in_config_t const * p_config,
|
||||
nrfx_gpiote_evt_handler_t evt_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing a GPIOTE input pin.
|
||||
* @details The driver frees the GPIOTE channel if the input pin was using one.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling sensing of a GPIOTE input pin.
|
||||
*
|
||||
* @details If the input pin is configured as high-accuracy pin, the function
|
||||
* enables an IN_EVENT. Otherwise, the function enables the GPIO sense mechanism.
|
||||
* The PORT event is shared between multiple pins, therefore the interrupt is always enabled.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
* @param[in] int_enable True to enable the interrupt. Always valid for a high-accuracy pin.
|
||||
*/
|
||||
void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling a GPIOTE input pin.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if a GPIOTE input pin is set.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @retval true The input pin is set.
|
||||
* @retval false The input pin is not set.
|
||||
*/
|
||||
bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the GPIOTE event for the specified input pin.
|
||||
*
|
||||
* @details The returned event identifier can be used within @ref nrf_gpiote_hal,
|
||||
* for example, to configure a DPPI channel.
|
||||
* If the pin is configured to use low-accuracy mode, the PORT event
|
||||
* is returned.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return Event associated with the specified input pin.
|
||||
*/
|
||||
nrf_gpiote_events_t nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of a GPIOTE input pin event.
|
||||
* @details If the pin is configured to use low-accuracy mode, the address of the PORT event is returned.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*
|
||||
* @return Address of the specified input pin event.
|
||||
*/
|
||||
uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin);
|
||||
|
||||
/**
|
||||
* @brief Function for forcing a specific state on the pin configured as task.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
* @param[in] state Pin state.
|
||||
*/
|
||||
void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state);
|
||||
|
||||
/**
|
||||
* @brief Function for triggering the task OUT manually.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin);
|
||||
|
||||
#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for triggering the task SET manually.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin);
|
||||
#endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for triggering the task CLR manually.
|
||||
*
|
||||
* @param[in] pin Pin.
|
||||
*/
|
||||
void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin);
|
||||
#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_gpiote_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_GPIOTE_H__
|
||||
253
modules/nrfx/drivers/include/nrfx_i2s.h
Normal file
253
modules/nrfx/drivers/include/nrfx_i2s.h
Normal file
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_I2S_H__
|
||||
#define NRFX_I2S_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_i2s.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_i2s I2S driver
|
||||
* @{
|
||||
* @ingroup nrf_i2s
|
||||
* @brief Inter-IC Sound (I2S) peripheral driver.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief This value can be provided instead of a pin number for the signals
|
||||
* SDOUT, SDIN, and MCK to specify that a given signal is not used
|
||||
* and therefore does not need to be connected to a pin.
|
||||
*/
|
||||
#define NRFX_I2S_PIN_NOT_USED 0xFF
|
||||
|
||||
/** @brief I2S driver configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t sck_pin; ///< SCK pin number.
|
||||
uint8_t lrck_pin; ///< LRCK pin number.
|
||||
uint8_t mck_pin; ///< MCK pin number.
|
||||
/**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint8_t sdout_pin; ///< SDOUT pin number.
|
||||
/**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint8_t sdin_pin; ///< SDIN pin number.
|
||||
/**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint8_t irq_priority; ///< Interrupt priority.
|
||||
|
||||
nrf_i2s_mode_t mode; ///< Mode of operation.
|
||||
nrf_i2s_format_t format; ///< Frame format.
|
||||
nrf_i2s_align_t alignment; ///< Alignment of sample within a frame.
|
||||
nrf_i2s_swidth_t sample_width; ///< Sample width.
|
||||
nrf_i2s_channels_t channels; ///< Enabled channels.
|
||||
nrf_i2s_mck_t mck_setup; ///< Master clock setup.
|
||||
nrf_i2s_ratio_t ratio; ///< MCK/LRCK ratio.
|
||||
} nrfx_i2s_config_t;
|
||||
|
||||
/** @brief I2S driver buffers structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t * p_rx_buffer; ///< Pointer to the buffer for received data.
|
||||
uint32_t const * p_tx_buffer; ///< Pointer to the buffer with data to be sent.
|
||||
} nrfx_i2s_buffers_t;
|
||||
|
||||
/** @brief I2S driver default configuration. */
|
||||
#define NRFX_I2S_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.sck_pin = NRFX_I2S_CONFIG_SCK_PIN, \
|
||||
.lrck_pin = NRFX_I2S_CONFIG_LRCK_PIN, \
|
||||
.mck_pin = NRFX_I2S_CONFIG_MCK_PIN, \
|
||||
.sdout_pin = NRFX_I2S_CONFIG_SDOUT_PIN, \
|
||||
.sdin_pin = NRFX_I2S_CONFIG_SDIN_PIN, \
|
||||
.irq_priority = NRFX_I2S_CONFIG_IRQ_PRIORITY, \
|
||||
.mode = (nrf_i2s_mode_t)NRFX_I2S_CONFIG_MASTER, \
|
||||
.format = (nrf_i2s_format_t)NRFX_I2S_CONFIG_FORMAT, \
|
||||
.alignment = (nrf_i2s_align_t)NRFX_I2S_CONFIG_ALIGN, \
|
||||
.sample_width = (nrf_i2s_swidth_t)NRFX_I2S_CONFIG_SWIDTH, \
|
||||
.channels = (nrf_i2s_channels_t)NRFX_I2S_CONFIG_CHANNELS, \
|
||||
.mck_setup = (nrf_i2s_mck_t)NRFX_I2S_CONFIG_MCK_SETUP, \
|
||||
.ratio = (nrf_i2s_ratio_t)NRFX_I2S_CONFIG_RATIO, \
|
||||
}
|
||||
|
||||
|
||||
#define NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED (1UL << 0)
|
||||
/**< The application must provide buffers that are to be used in the next
|
||||
* part of the transfer. A call to @ref nrfx_i2s_next_buffers_set must
|
||||
* be done before the currently used buffers are completely processed
|
||||
* (that is, the time remaining for supplying the next buffers depends on
|
||||
* the used size of the buffers). */
|
||||
|
||||
/**
|
||||
* @brief I2S driver data handler type.
|
||||
*
|
||||
* A data handling function of this type must be specified during the initialization
|
||||
* of the driver. The driver will call this function when it finishes using
|
||||
* buffers passed to it by the application, and when it needs to be provided
|
||||
* with buffers for the next part of the transfer.
|
||||
*
|
||||
* @note The @c p_released pointer passed to this function is temporary and
|
||||
* will be invalid after the function returns, hence it cannot be stored
|
||||
* and used later. If needed, the pointed content (that is, buffers pointers)
|
||||
* must be copied instead.
|
||||
*
|
||||
* @param[in] p_released Pointer to a structure with pointers to buffers
|
||||
* passed previously to the driver that will no longer
|
||||
* be accessed by it (they can be now safely released or
|
||||
* used for another purpose, in particular for a next
|
||||
* part of the transfer).
|
||||
* This pointer will be NULL if the application did not
|
||||
* supply the buffers for the next part of the transfer
|
||||
* (via a call to @ref nrfx_i2s_next_buffers_set) since
|
||||
* the previous time the data handler signaled such need.
|
||||
* This means that data corruption occurred (the previous
|
||||
* buffers are used for the second time) and no buffers
|
||||
* can be released at the moment.
|
||||
* Both pointers in this structure are NULL when the
|
||||
* handler is called for the first time after a transfer
|
||||
* is started, because no data has been transferred yet
|
||||
* at this point. In all successive calls the pointers
|
||||
* specify what has been sent (TX) and what has been
|
||||
* received (RX) in the part of transfer that has just
|
||||
* been completed (provided that a given direction is
|
||||
* enabled, see @ref nrfx_i2s_start).
|
||||
* @param[in] status Bit field describing the current status of the transfer.
|
||||
* It can be 0 or a combination of the following flags:
|
||||
* - @ref NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED
|
||||
*/
|
||||
typedef void (* nrfx_i2s_data_handler_t)(nrfx_i2s_buffers_t const * p_released,
|
||||
uint32_t status);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the I2S driver.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] handler Data handler provided by the user. Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The requested combination of configuration
|
||||
* options is not allowed by the I2S peripheral.
|
||||
*/
|
||||
nrfx_err_t nrfx_i2s_init(nrfx_i2s_config_t const * p_config,
|
||||
nrfx_i2s_data_handler_t handler);
|
||||
|
||||
/** @brief Function for uninitializing the I2S driver. */
|
||||
void nrfx_i2s_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the continuous I2S transfer.
|
||||
*
|
||||
* The I2S data transfer can be performed in one of three modes: RX (reception)
|
||||
* only, TX (transmission) only, or in both directions simultaneously.
|
||||
* The mode is selected by specifying a proper buffer for a given direction
|
||||
* in the call to this function or by passing NULL instead if this direction
|
||||
* is to be disabled.
|
||||
*
|
||||
* The length of the buffer (which is a common value for RX and TX if both
|
||||
* directions are enabled) is specified in 32-bit words. One 32-bit memory
|
||||
* word can either contain four 8-bit samples, two 16-bit samples, or one
|
||||
* right-aligned 24-bit sample sign-extended to a 32-bit value.
|
||||
* For a detailed memory mapping for different supported configurations,
|
||||
* see the @linkProductSpecification52.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including I2S) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param[in] p_initial_buffers Pointer to a structure specifying the buffers
|
||||
* to be used in the initial part of the transfer
|
||||
* (buffers for all consecutive parts are provided
|
||||
* through the data handler).
|
||||
* @param[in] buffer_size Size of the buffers (in 32-bit words).
|
||||
* Must not be 0.
|
||||
* @param[in] flags Transfer options (0 for default settings).
|
||||
* Currently, no additional flags are available.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Transfer was already started or
|
||||
* the driver has not been initialized.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed
|
||||
* in the Data RAM region.
|
||||
*/
|
||||
nrfx_err_t nrfx_i2s_start(nrfx_i2s_buffers_t const * p_initial_buffers,
|
||||
uint16_t buffer_size,
|
||||
uint8_t flags);
|
||||
|
||||
/**
|
||||
* @brief Function for supplying the buffers to be used in the next part of
|
||||
* the transfer.
|
||||
*
|
||||
* The application must call this function when the data handler receives
|
||||
* @ref NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED in the @c status parameter.
|
||||
* The call can be done immediately from the data handler function or later,
|
||||
* but it has to be done before the I2S peripheral finishes processing the
|
||||
* buffers supplied previously. Otherwise, data corruption will occur.
|
||||
*
|
||||
* @sa nrfx_i2s_data_handler_t
|
||||
*
|
||||
* @retval NRFX_SUCCESS If the operation was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE If the buffers were already supplied or
|
||||
* the peripheral is currently being stopped.
|
||||
*/
|
||||
nrfx_err_t nrfx_i2s_next_buffers_set(nrfx_i2s_buffers_t const * p_buffers);
|
||||
|
||||
/** @brief Function for stopping the I2S transfer. */
|
||||
void nrfx_i2s_stop(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_i2s_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_I2S_H__
|
||||
|
||||
153
modules/nrfx/drivers/include/nrfx_lpcomp.h
Normal file
153
modules/nrfx/drivers/include/nrfx_lpcomp.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 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 NRFX_LPCOMP_H__
|
||||
#define NRFX_LPCOMP_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_lpcomp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_lpcomp LPCOMP driver
|
||||
* @{
|
||||
* @ingroup nrf_lpcomp
|
||||
* @brief Low Power Comparator (LPCOMP) peripheral driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief LPCOMP event handler function type.
|
||||
* @param[in] event LPCOMP event.
|
||||
*/
|
||||
typedef void (* nrfx_lpcomp_event_handler_t)(nrf_lpcomp_event_t event);
|
||||
|
||||
/** @brief LPCOMP configuration. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_lpcomp_config_t hal; /**< LPCOMP HAL configuration. */
|
||||
nrf_lpcomp_input_t input; /**< Input to be monitored. */
|
||||
uint8_t interrupt_priority; /**< LPCOMP interrupt priority. */
|
||||
} nrfx_lpcomp_config_t;
|
||||
|
||||
/** @brief LPCOMP driver default configuration, including the LPCOMP HAL configuration. */
|
||||
#ifdef NRF52_SERIES
|
||||
#define NRFX_LPCOMP_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.hal = { (nrf_lpcomp_ref_t)NRFX_LPCOMP_CONFIG_REFERENCE , \
|
||||
(nrf_lpcomp_detect_t)NRFX_LPCOMP_CONFIG_DETECTION, \
|
||||
(nrf_lpcomp_hysteresis_t)NRFX_LPCOMP_CONFIG_HYST }, \
|
||||
.input = (nrf_lpcomp_input_t)NRFX_LPCOMP_CONFIG_INPUT, \
|
||||
.interrupt_priority = NRFX_LPCOMP_CONFIG_IRQ_PRIORITY \
|
||||
}
|
||||
#else
|
||||
#define NRFX_LPCOMP_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.hal = { (nrf_lpcomp_ref_t)NRFX_LPCOMP_CONFIG_REFERENCE , \
|
||||
(nrf_lpcomp_detect_t)NRFX_LPCOMP_CONFIG_DETECTION }, \
|
||||
.input = (nrf_lpcomp_input_t)NRFX_LPCOMP_CONFIG_INPUT, \
|
||||
.interrupt_priority = NRFX_LPCOMP_CONFIG_IRQ_PRIORITY \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the LPCOMP driver.
|
||||
*
|
||||
* This function initializes the LPCOMP driver, but does not enable the peripheral or any interrupts.
|
||||
* To start the driver, call the function nrfx_lpcomp_enable() after initialization.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver has already been initialized.
|
||||
* @retval NRFX_ERROR_BUSY The COMP peripheral is already in use.
|
||||
* This is possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_lpcomp_init(nrfx_lpcomp_config_t const * p_config,
|
||||
nrfx_lpcomp_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the LCOMP driver.
|
||||
*
|
||||
* This function uninitializes the LPCOMP driver. The LPCOMP peripheral and
|
||||
* its interrupts are disabled, and local variables are cleaned. After this call, you must
|
||||
* initialize the driver again by calling nrfx_lpcomp_init() if you want to use it.
|
||||
*
|
||||
* @sa nrfx_lpcomp_disable
|
||||
* @sa nrfx_lpcomp_init
|
||||
*/
|
||||
void nrfx_lpcomp_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the LPCOMP peripheral and interrupts.
|
||||
*
|
||||
* Before calling this function, the driver must be initialized. This function
|
||||
* enables the LPCOMP peripheral and its interrupts.
|
||||
*
|
||||
* @sa nrfx_lpcomp_disable
|
||||
*/
|
||||
void nrfx_lpcomp_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the LPCOMP peripheral.
|
||||
*
|
||||
* Before calling this function, the driver must be initialized. This function disables the LPCOMP
|
||||
* peripheral and its interrupts.
|
||||
*
|
||||
* @sa nrfx_lpcomp_enable
|
||||
*/
|
||||
void nrfx_lpcomp_disable(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_lpcomp_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_LPCOMP_H__
|
||||
356
modules/nrfx/drivers/include/nrfx_nfct.h
Normal file
356
modules/nrfx/drivers/include/nrfx_nfct.h
Normal file
@@ -0,0 +1,356 @@
|
||||
/**
|
||||
* Copyright (c) 2018 - 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 NRFX_NFCT_H__
|
||||
#define NRFX_NFCT_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_nfct.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_nfct NFCT driver
|
||||
* @{
|
||||
* @ingroup nrf_nfct
|
||||
* @brief Near Field Communication Tag (NFCT) peripheral driver.
|
||||
*/
|
||||
|
||||
#define NRFX_NFCT_NFCID1_SINGLE_SIZE 4u ///< Length of single-size NFCID1.
|
||||
#define NRFX_NFCT_NFCID1_DOUBLE_SIZE 7u ///< Length of double-size NFCID1.
|
||||
#define NRFX_NFCT_NFCID1_TRIPLE_SIZE 10u ///< Length of triple-size NFCID1.
|
||||
|
||||
#define NRFX_NFCT_NFCID1_DEFAULT_LEN NRFX_NFCT_NFCID1_DOUBLE_SIZE ///< Default length of NFC ID. */
|
||||
|
||||
/** @brief NFCT hardware states. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_NFCT_STATE_DISABLED = NRF_NFCT_TASK_DISABLE, ///< NFC Tag is disabled (no sensing of an external NFC field).
|
||||
NRFX_NFCT_STATE_SENSING = NRF_NFCT_TASK_SENSE, ///< NFC Tag is sensing whether there is an external NFC field.
|
||||
NRFX_NFCT_STATE_ACTIVATED = NRF_NFCT_TASK_ACTIVATE, ///< NFC Tag is powered-up (see @ref nrfx_nfct_active_state_t for possible substates).
|
||||
} nrfx_nfct_state_t;
|
||||
|
||||
/**
|
||||
* @brief NFC tag states, when NFCT hardware is activated.
|
||||
*
|
||||
* @details These states are substates of the @ref NRFX_NFCT_STATE_ACTIVATED state.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_NFCT_ACTIVE_STATE_IDLE = NRF_NFCT_TASK_GOIDLE, ///< NFC Tag is activated and idle (not selected by a reader).
|
||||
NRFX_NFCT_ACTIVE_STATE_SLEEP = NRF_NFCT_TASK_GOSLEEP, ///< NFC Tag is sleeping.
|
||||
NRFX_NFCT_ACTIVE_STATE_DEFAULT, ///< NFC Tag is either sleeping or idle, depending on the previous state before being selected by a poller.
|
||||
} nrfx_nfct_active_state_t;
|
||||
|
||||
/**
|
||||
* @brief NFCT driver event types, passed to the upper-layer callback function
|
||||
* provided during the initialization.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_NFCT_EVT_FIELD_DETECTED = NRF_NFCT_INT_FIELDDETECTED_MASK, ///< External NFC field is detected.
|
||||
NRFX_NFCT_EVT_FIELD_LOST = NRF_NFCT_INT_FIELDLOST_MASK, ///< External NFC Field is lost.
|
||||
NRFX_NFCT_EVT_SELECTED = NRF_NFCT_INT_SELECTED_MASK, ///< Tag was selected by the poller.
|
||||
NRFX_NFCT_EVT_RX_FRAMESTART = NRF_NFCT_INT_RXFRAMESTART_MASK, ///< Data frame reception started.
|
||||
NRFX_NFCT_EVT_RX_FRAMEEND = NRF_NFCT_INT_RXFRAMEEND_MASK, ///< Data frame is received.
|
||||
NRFX_NFCT_EVT_TX_FRAMESTART = NRF_NFCT_INT_TXFRAMESTART_MASK, ///< Data frame transmission started.
|
||||
NRFX_NFCT_EVT_TX_FRAMEEND = NRF_NFCT_INT_TXFRAMEEND_MASK, ///< Data frame is transmitted.
|
||||
NRFX_NFCT_EVT_ERROR = NRF_NFCT_INT_ERROR_MASK, ///< Error occurred in an NFC communication.
|
||||
} nrfx_nfct_evt_id_t;
|
||||
|
||||
/** @brief NFCT timing-related error types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_NFCT_ERROR_FRAMEDELAYTIMEOUT, ///< No response frame was transmitted to the poller in the transmit window.
|
||||
NRFX_NFCT_ERROR_NUM, ///< Total number of possible errors.
|
||||
} nrfx_nfct_error_t;
|
||||
|
||||
/** @brief NFCT driver parameter types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_NFCT_PARAM_ID_FDT, ///< NFC-A Frame Delay Time parameter.
|
||||
NRFX_NFCT_PARAM_ID_SEL_RES, ///< Value of the 'Protocol' field in the NFC-A SEL_RES frame.
|
||||
NRFX_NFCT_PARAM_ID_NFCID1, ///< NFC-A NFCID1 setting (NFC tag identifier).
|
||||
} nrfx_nfct_param_id_t;
|
||||
|
||||
/** @brief NFCID1 descriptor. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t const * p_id; ///< NFCID1 data.
|
||||
uint8_t id_size; ///< NFCID1 size.
|
||||
} nrfx_nfct_nfcid1_t;
|
||||
|
||||
/** @brief NFCT driver parameter descriptor. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_nfct_param_id_t id; ///< Type of parameter.
|
||||
union
|
||||
{
|
||||
uint32_t fdt; ///< NFC-A Frame Delay Time. Filled when nrfx_nfct_param_t::id is @ref NRFX_NFCT_PARAM_ID_FDT.
|
||||
uint8_t sel_res_protocol; ///< NFC-A value of the 'Protocol' field in the SEL_RES frame. Filled when nrfx_nfct_param_t::id is @ref NRFX_NFCT_PARAM_ID_SEL_RES.
|
||||
nrfx_nfct_nfcid1_t nfcid1; ///< NFC-A NFCID1 value (tag identifier). Filled when nrfx_nfct_param_t::id is @ref NRFX_NFCT_PARAM_ID_NFCID1.
|
||||
} data; ///< Union to store parameter data.
|
||||
} nrfx_nfct_param_t;
|
||||
|
||||
/** @brief NFCT driver RX/TX buffer descriptor. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t data_size; ///< RX/TX buffer size.
|
||||
uint8_t const * p_data; ///< RX/TX buffer.
|
||||
} nrfx_nfct_data_desc_t;
|
||||
|
||||
/** @brief Structure used to describe the @ref NRFX_NFCT_EVT_RX_FRAMEEND event type. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rx_status; ///< RX error status.
|
||||
nrfx_nfct_data_desc_t rx_data; ///< RX buffer.
|
||||
} nrfx_nfct_evt_rx_frameend_t;
|
||||
|
||||
/** @brief Structure used to describe the @ref NRFX_NFCT_EVT_TX_FRAMESTART event type. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_nfct_data_desc_t tx_data; ///< TX buffer.
|
||||
} nrfx_nfct_evt_tx_framestart_t;
|
||||
|
||||
/** @brief Structure used to describe the @ref NRFX_NFCT_EVT_ERROR event type. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_nfct_error_t reason; ///< Reason for error.
|
||||
} nrfx_nfct_evt_error_t;
|
||||
|
||||
/** @brief NFCT driver event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_nfct_evt_id_t evt_id; ///< Type of event.
|
||||
union
|
||||
{
|
||||
nrfx_nfct_evt_rx_frameend_t rx_frameend; ///< End of the RX frame data. Filled when nrfx_nfct_evt_t::evt_id is @ref NRFX_NFCT_EVT_RX_FRAMEEND.
|
||||
nrfx_nfct_evt_tx_framestart_t tx_framestart; ///< Start of the TX frame data. Filled when nrfx_nfct_evt_t::evt_id is @ref NRFX_NFCT_EVT_TX_FRAMESTART.
|
||||
nrfx_nfct_evt_error_t error; ///< Error data. Filled when nrfx_nfct_evt_t::evt_id is @ref NRFX_NFCT_EVT_ERROR.
|
||||
} params; ///< Union to store event data.
|
||||
} nrfx_nfct_evt_t;
|
||||
|
||||
/**
|
||||
* @brief Callback descriptor to pass events from the NFCT driver to the upper layer.
|
||||
*
|
||||
* @param[in] p_event Pointer to the event descriptor.
|
||||
*
|
||||
* @note @ref NRFX_NFCT_EVT_FIELD_DETECTED and @ref NRFX_NFCT_EVT_FIELD_LOST are generated only on field state transitions,
|
||||
* i.e. there will be no multiple events of the same type (out of the 2 mentioned) coming in a row.
|
||||
*/
|
||||
typedef void (*nrfx_nfct_handler_t)(nrfx_nfct_evt_t const * p_event);
|
||||
|
||||
/** @brief NFCT driver configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rxtx_int_mask; ///< Mask for enabling RX/TX events. Indicate which events must be forwarded to the upper layer by using @ref nrfx_nfct_evt_id_t. By default, no events are enabled. */
|
||||
nrfx_nfct_handler_t cb; ///< Callback.
|
||||
} nrfx_nfct_config_t;
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the NFCT driver.
|
||||
*
|
||||
* @param[in] p_config Pointer to the NFCT driver configuration structure.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The NFCT driver was initialized successfully.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The NFCT driver is already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_nfct_init(nrfx_nfct_config_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the NFCT driver.
|
||||
*
|
||||
* After uninitialization, the instance is in disabled state.
|
||||
*/
|
||||
void nrfx_nfct_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the NFC subsystem.
|
||||
*
|
||||
* After this function completes, NFC readers are able to detect the tag.
|
||||
*/
|
||||
void nrfx_nfct_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the NFCT driver.
|
||||
*
|
||||
* After this function returns, NFC readers are no longer able to connect
|
||||
* to the tag.
|
||||
*/
|
||||
void nrfx_nfct_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for checking whether the external NFC field is present in the range of the tag.
|
||||
*
|
||||
* @retval true The NFC field is present.
|
||||
* @retval false No NFC field is present.
|
||||
*/
|
||||
bool nrfx_nfct_field_check(void);
|
||||
|
||||
/**
|
||||
* @brief Function for preparing the NFCT driver for receiving an NFC frame.
|
||||
*
|
||||
* @param[in] p_rx_data Pointer to the RX buffer.
|
||||
*/
|
||||
void nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_rx_data);
|
||||
|
||||
/**
|
||||
* @brief Function for transmitting an NFC frame.
|
||||
*
|
||||
* @param[in] p_tx_data Pointer to the TX buffer.
|
||||
* @param[in] delay_mode Delay mode of the NFCT frame timer.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful.
|
||||
* @retval NRFX_ERROR_INVALID_LENGTH The TX buffer size is invalid.
|
||||
*/
|
||||
nrfx_err_t nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,
|
||||
nrf_nfct_frame_delay_mode_t delay_mode);
|
||||
|
||||
/**
|
||||
* @brief Function for moving the NFCT to a new state.
|
||||
*
|
||||
* @note The HFCLK must be running before activating the NFCT with
|
||||
* @ref NRFX_NFCT_STATE_ACTIVATED.
|
||||
*
|
||||
* @param[in] state The required state.
|
||||
*/
|
||||
void nrfx_nfct_state_force(nrfx_nfct_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Function for moving the NFCT to a new initial substate within @ref NRFX_NFCT_STATE_ACTIVATED.
|
||||
*
|
||||
* @param[in] sub_state The required substate.
|
||||
*/
|
||||
void nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the NFC communication parameter.
|
||||
*
|
||||
* @note Parameter validation for length and acceptable values.
|
||||
*
|
||||
* @param[in] p_param Pointer to parameter descriptor.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The parameter data is invalid.
|
||||
*/
|
||||
nrfx_err_t nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param);
|
||||
|
||||
/**
|
||||
* @brief Function for getting default bytes for NFCID1.
|
||||
*
|
||||
* @param[in,out] p_nfcid1_buff In: empty buffer for data;
|
||||
* Out: buffer with the NFCID1 default data. These values
|
||||
* can be used to fill the Type 2 Tag Internal Bytes.
|
||||
* @param[in] nfcid1_buff_len Length of the NFCID1 buffer.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful.
|
||||
* @retval NRFX_ERROR_INVALID_LENGTH Length of the NFCID buffer is different than
|
||||
* @ref NRFX_NFCT_NFCID1_SINGLE_SIZE,
|
||||
* @ref NRFX_NFCT_NFCID1_DOUBLE_SIZE, or
|
||||
* @ref NRFX_NFCT_NFCID1_TRIPLE_SIZE.
|
||||
*/
|
||||
nrfx_err_t nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,
|
||||
uint32_t nfcid1_buff_len);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the automatic collision resolution.
|
||||
*
|
||||
* @details As defined by the NFC Forum Digital Protocol Technical Specification (and ISO 14443-3),
|
||||
* the automatic collision resolution is implemented in the NFCT hardware.
|
||||
* This function allows enabling and disabling this feature.
|
||||
*/
|
||||
void nrfx_nfct_autocolres_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the automatic collision resolution.
|
||||
*
|
||||
* @details See also details in @ref nrfx_nfct_autocolres_enable.
|
||||
*/
|
||||
void nrfx_nfct_autocolres_disable(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_nfct_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_nfct_fixes NFCT driver fixes and workarounds
|
||||
* @{
|
||||
* @ingroup nrf_nfct
|
||||
* @brief Fixes for hardware-related anomalies.
|
||||
*
|
||||
* If you are using the nRF52832 chip, the workarounds for the following anomalies are applied:
|
||||
* - 79. NFCT: A false EVENTS_FIELDDETECTED event occurs after the field is lost.
|
||||
* - 116. NFCT does not release HFCLK when switching from ACTIVATED to SENSE mode.
|
||||
* To implement the first workaround, an instance of NRF_TIMER is used. After the NFC field is detected,
|
||||
* the timing module periodically polls its state to determine when the field is turned off.
|
||||
* To implement the second workaround, power reset is used to release the clock acquired by NFCT
|
||||
* after the field is turned off. Note that the NFCT register configuration is restored to defaults.
|
||||
*
|
||||
* If you are using the nRF52840 chip, rev. Engineering A, the workarounds for the following anomalies
|
||||
* are applied:
|
||||
* - 98. NFCT: The NFCT is not able to communicate with the peer.
|
||||
* - 116. NFCT does not release HFCLK when switching from ACTIVATED to SENSE mode.
|
||||
* - 144. NFCT: Not optimal NFC performance
|
||||
*
|
||||
* If you are using the nRF52840 chip, rev. 1, or rev. Engineering B or C, the workarounds for the following
|
||||
* anomalies are applied:
|
||||
* - 190. NFCT: Event FIELDDETECTED can be generated too early.
|
||||
* To implement this workaround, an instance of NRF_TIMER is used. After the NFC field is detected,
|
||||
* the timing module measures the necessary waiting period after which NFCT can be activated.
|
||||
* This debouncing technique is used to filter possible field instabilities.
|
||||
*
|
||||
* The application of the implemented workarounds for the nRF52840 chip is determined at runtime and depends
|
||||
* on the chip variant.
|
||||
*
|
||||
* The current code contains a patch for the anomaly 25 (NFCT: Reset value of
|
||||
* SENSRES register is incorrect), so that the module now works on Windows Phone.
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // NRFX_NFCT_H__
|
||||
295
modules/nrfx/drivers/include/nrfx_nvmc.h
Normal file
295
modules/nrfx/drivers/include/nrfx_nvmc.h
Normal file
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 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 NRFX_NVMC_H__
|
||||
#define NRFX_NVMC_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_nvmc.h>
|
||||
#include <hal/nrf_ficr.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_nvmc NVMC driver
|
||||
* @{
|
||||
* @ingroup nrf_nvmc
|
||||
* @brief Non-Volatile Memory Controller (NVMC) peripheral driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Function for erasing a page in flash.
|
||||
*
|
||||
* This function blocks until the erase operation finishes.
|
||||
*
|
||||
* @note Depending on the source of the code being executed,
|
||||
* the CPU may be halted during the operation.
|
||||
* Refer to the Product Specification for more information.
|
||||
*
|
||||
* @param address Address of the first word in the page to erase.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Page erase complete.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR Address is not aligned to the size of the page.
|
||||
*/
|
||||
nrfx_err_t nrfx_nvmc_page_erase(uint32_t address);
|
||||
|
||||
/**
|
||||
* @brief Function for erasing the user information configuration register (UICR).
|
||||
*
|
||||
* @note Depending on the source of the code being executed,
|
||||
* the CPU may be halted during the operation.
|
||||
* Refer to the Product Specification for more information.
|
||||
*
|
||||
* @retval NRFX_SUCCESS UICR has been successfully erased.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED UICR erase is not supported.
|
||||
*/
|
||||
nrfx_err_t nrfx_nvmc_uicr_erase(void);
|
||||
|
||||
/**
|
||||
* @brief Function for erasing the whole flash memory.
|
||||
*
|
||||
* @note All user code and UICR will be erased.
|
||||
*/
|
||||
void nrfx_nvmc_all_erase(void);
|
||||
|
||||
#if defined(NRF_NVMC_PARTIAL_ERASE_PRESENT)
|
||||
/**
|
||||
* @brief Function for initiating a complete page erase split into parts (also known as partial erase).
|
||||
*
|
||||
* This function initiates a partial erase with the specified duration.
|
||||
* To execute each part of the partial erase, use @ref nrfx_nvmc_page_partial_erase_continue.
|
||||
*
|
||||
* @param address Address of the first word in the page to erase.
|
||||
* @param duration_ms Time in milliseconds that each partial erase will take.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Partial erase started.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR Address is not aligned to the size of the page.
|
||||
*
|
||||
* @sa nrfx_nvmc_page_partial_erase_continue()
|
||||
*/
|
||||
nrfx_err_t nrfx_nvmc_page_partial_erase_init(uint32_t address, uint32_t duration_ms);
|
||||
|
||||
/**
|
||||
* @brief Function for performing a part of the complete page erase (also known as partial erase).
|
||||
*
|
||||
* This function must be called several times to erase the whole page, once for each erase part.
|
||||
*
|
||||
* @note The actual time needed to perform each part of the page erase is longer than the partial
|
||||
* erase duration specified in the call to @ref nrfx_nvmc_page_partial_erase_init,
|
||||
* since the NVMC peripheral needs certain additional amount of time to handle the process.
|
||||
* For details regarding this additional time, see the "Electrical specification" section
|
||||
* for the NVMC peripheral in the Product Specification.
|
||||
*
|
||||
* @note Using a page that was not completely erased leads to undefined behavior.
|
||||
* Depending on the source of the code being executed,
|
||||
* the CPU may be halted during the operation.
|
||||
* Refer to the Product Specification for more information.
|
||||
*
|
||||
* @retval true Partial erase finished.
|
||||
* @retval false Partial erase not finished.
|
||||
* Call the function again to process the next part.
|
||||
*/
|
||||
bool nrfx_nvmc_page_partial_erase_continue(void);
|
||||
|
||||
#endif // defined(NRF_NVMC_PARTIAL_ERASE_PRESENT)
|
||||
|
||||
/**
|
||||
* @brief Function for checking whether a byte is writable at the specified address.
|
||||
*
|
||||
* The NVMC is only able to write '0' to bits in the flash that are erased (set to '1').
|
||||
* It cannot rewrite a bit back to '1'. This function checks if the value currently
|
||||
* residing at the specified address can be transformed to the desired value
|
||||
* without any '0' to '1' transitions.
|
||||
*
|
||||
* @param address Address to be checked.
|
||||
* @param value Value to be checked.
|
||||
*
|
||||
* @retval true Byte can be written at the specified address.
|
||||
* @retval false Byte cannot be written at the specified address.
|
||||
* Erase the page or change the address.
|
||||
*/
|
||||
bool nrfx_nvmc_byte_writable_check(uint32_t address, uint8_t value);
|
||||
|
||||
/**
|
||||
* @brief Function for writing a single byte to flash.
|
||||
*
|
||||
* To determine if the flash write has been completed, use @ref nrfx_nvmc_write_done_check().
|
||||
*
|
||||
* @note Depending on the source of the code being executed,
|
||||
* the CPU may be halted during the operation.
|
||||
* Refer to the Product Specification for more information.
|
||||
*
|
||||
* @param address Address to write to.
|
||||
* @param value Value to write.
|
||||
*/
|
||||
void nrfx_nvmc_byte_write(uint32_t address, uint8_t value);
|
||||
|
||||
/**
|
||||
* @brief Function for checking whether a word is writable at the specified address.
|
||||
*
|
||||
* The NVMC is only able to write '0' to bits in the Flash that are erased (set to '1').
|
||||
* It cannot rewrite a bit back to '1'. This function checks if the value currently
|
||||
* residing at the specified address can be transformed to the desired value
|
||||
* without any '0' to '1' transitions.
|
||||
*
|
||||
* @param address Address to be checked. Must be word-aligned.
|
||||
* @param value Value to be checked.
|
||||
*
|
||||
* @retval true Word can be written at the specified address.
|
||||
* @retval false Word cannot be written at the specified address.
|
||||
* Erase page or change address.
|
||||
*/
|
||||
bool nrfx_nvmc_word_writable_check(uint32_t address, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Function for writing a 32-bit word to flash.
|
||||
*
|
||||
* To determine if the flash write has been completed, use @ref nrfx_nvmc_write_done_check().
|
||||
*
|
||||
* @note Depending on the source of the code being executed,
|
||||
* the CPU may be halted during the operation.
|
||||
* Refer to the Product Specification for more information.
|
||||
*
|
||||
* @param address Address to write to. Must be word-aligned.
|
||||
* @param value Value to write.
|
||||
*/
|
||||
void nrfx_nvmc_word_write(uint32_t address, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Function for writing consecutive bytes to flash.
|
||||
*
|
||||
* To determine if the last flash write has been completed, use @ref nrfx_nvmc_write_done_check().
|
||||
*
|
||||
* @note Depending on the source of the code being executed,
|
||||
* the CPU may be halted during the operation.
|
||||
* Refer to the Product Specification for more information.
|
||||
*
|
||||
* @param address Address to write to.
|
||||
* @param src Pointer to the data to copy from.
|
||||
* @param num_bytes Number of bytes to write.
|
||||
*/
|
||||
void nrfx_nvmc_bytes_write(uint32_t address, void const * src, uint32_t num_bytes);
|
||||
|
||||
/**
|
||||
* @brief Function for writing consecutive words to flash.
|
||||
*
|
||||
* To determine if the last flash write has been completed, use @ref nrfx_nvmc_write_done_check().
|
||||
*
|
||||
* @note Depending on the source of the code being executed,
|
||||
* the CPU may be halted during the operation.
|
||||
* Refer to the Product Specification for more information.
|
||||
*
|
||||
* @param address Address to write to. Must be word-aligned.
|
||||
* @param src Pointer to data to copy from. Must be word-aligned.
|
||||
* @param num_words Number of words to write.
|
||||
*/
|
||||
void nrfx_nvmc_words_write(uint32_t address, void const * src, uint32_t num_words);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the total flash size in bytes.
|
||||
*
|
||||
* @return Flash total size in bytes.
|
||||
*/
|
||||
uint32_t nrfx_nvmc_flash_size_get(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the flash page size in bytes.
|
||||
*
|
||||
* @return Flash page size in bytes.
|
||||
*/
|
||||
uint32_t nrfx_nvmc_flash_page_size_get(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the flash page count.
|
||||
*
|
||||
* @return Flash page count.
|
||||
*/
|
||||
uint32_t nrfx_nvmc_flash_page_count_get(void);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the last flash write has been completed.
|
||||
*
|
||||
* @retval true Last write completed successfully.
|
||||
* @retval false Last write is still in progress.
|
||||
*/
|
||||
__STATIC_INLINE bool nrfx_nvmc_write_done_check(void);
|
||||
|
||||
#if defined(NRF_NVMC_ICACHE_PRESENT)
|
||||
/**
|
||||
* @brief Function for enabling the Instruction Cache (ICache).
|
||||
*
|
||||
* Enabling ICache reduces the amount of accesses to flash memory,
|
||||
* which can boost performance and lower power consumption.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_nvmc_icache_enable(void);
|
||||
|
||||
/** @brief Function for disabling ICache. */
|
||||
__STATIC_INLINE void nrfx_nvmc_icache_disable(void);
|
||||
|
||||
#endif // defined(NRF_NVMC_ICACHE_PRESENT)
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE bool nrfx_nvmc_write_done_check(void)
|
||||
{
|
||||
return nrf_nvmc_ready_check(NRF_NVMC);
|
||||
}
|
||||
|
||||
#if defined(NRF_NVMC_ICACHE_PRESENT)
|
||||
__STATIC_INLINE void nrfx_nvmc_icache_enable(void)
|
||||
{
|
||||
nrf_nvmc_icache_config_set(NRF_NVMC, NRF_NVMC_ICACHE_ENABLE_WITH_PROFILING);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_nvmc_icache_disable(void)
|
||||
{
|
||||
nrf_nvmc_icache_config_set(NRF_NVMC, NRF_NVMC_ICACHE_DISABLE);
|
||||
}
|
||||
#endif // defined(NRF_NVMC_ICACHE_PRESENT)
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_NVMC_H__
|
||||
207
modules/nrfx/drivers/include/nrfx_pdm.h
Normal file
207
modules/nrfx/drivers/include/nrfx_pdm.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_PDM_H__
|
||||
#define NRFX_PDM_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_pdm.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_pdm PDM driver
|
||||
* @{
|
||||
* @ingroup nrf_pdm
|
||||
* @brief Pulse Density Modulation (PDM) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Maximum supported PDM buffer size. */
|
||||
#define NRFX_PDM_MAX_BUFFER_SIZE 32767
|
||||
|
||||
/** @brief PDM error type. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_PDM_NO_ERROR = 0, ///< No error.
|
||||
NRFX_PDM_ERROR_OVERFLOW = 1 ///< Overflow error.
|
||||
} nrfx_pdm_error_t;
|
||||
|
||||
/** @brief PDM event structure. */
|
||||
typedef struct
|
||||
{
|
||||
bool buffer_requested; ///< Buffer request flag.
|
||||
int16_t * buffer_released; ///< Pointer to the released buffer. Can be NULL.
|
||||
nrfx_pdm_error_t error; ///< Error type.
|
||||
} nrfx_pdm_evt_t;
|
||||
|
||||
/** @brief PDM interface driver configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_pdm_mode_t mode; ///< Interface operation mode.
|
||||
nrf_pdm_edge_t edge; ///< Sampling mode.
|
||||
uint8_t pin_clk; ///< CLK pin.
|
||||
uint8_t pin_din; ///< DIN pin.
|
||||
nrf_pdm_freq_t clock_freq; ///< Clock frequency.
|
||||
nrf_pdm_gain_t gain_l; ///< Left channel gain.
|
||||
nrf_pdm_gain_t gain_r; ///< Right channel gain.
|
||||
uint8_t interrupt_priority; ///< Interrupt priority.
|
||||
} nrfx_pdm_config_t;
|
||||
|
||||
/**
|
||||
* @brief Macro for setting @ref nrfx_pdm_config_t to default settings
|
||||
* in the single-ended mode.
|
||||
*
|
||||
* @param _pin_clk CLK output pin.
|
||||
* @param _pin_din DIN input pin.
|
||||
*/
|
||||
#define NRFX_PDM_DEFAULT_CONFIG(_pin_clk, _pin_din) \
|
||||
{ \
|
||||
.mode = (nrf_pdm_mode_t)NRFX_PDM_CONFIG_MODE, \
|
||||
.edge = (nrf_pdm_edge_t)NRFX_PDM_CONFIG_EDGE, \
|
||||
.pin_clk = _pin_clk, \
|
||||
.pin_din = _pin_din, \
|
||||
.clock_freq = (nrf_pdm_freq_t)NRFX_PDM_CONFIG_CLOCK_FREQ, \
|
||||
.gain_l = NRF_PDM_GAIN_DEFAULT, \
|
||||
.gain_r = NRF_PDM_GAIN_DEFAULT, \
|
||||
.interrupt_priority = NRFX_PDM_CONFIG_IRQ_PRIORITY \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handler for the PDM interface ready events.
|
||||
*
|
||||
* This event handler is called on a buffer request, an error or when a buffer
|
||||
* is full and ready to be processed.
|
||||
*
|
||||
* @param[in] p_evt Pointer to the PDM event structure.
|
||||
*/
|
||||
typedef void (*nrfx_pdm_event_handler_t)(nrfx_pdm_evt_t const * const p_evt);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the PDM interface.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user. Cannot be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Invalid configuration was specified.
|
||||
*/
|
||||
nrfx_err_t nrfx_pdm_init(nrfx_pdm_config_t const * p_config,
|
||||
nrfx_pdm_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the PDM interface.
|
||||
*
|
||||
* This function stops PDM sampling, if it is in progress.
|
||||
*/
|
||||
void nrfx_pdm_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of a PDM interface task.
|
||||
*
|
||||
* @param[in] task Task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_pdm_task_address_get(nrf_pdm_task_t task)
|
||||
{
|
||||
return nrf_pdm_task_address_get(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for getting the state of the PDM interface.
|
||||
*
|
||||
* @retval true The PDM interface is enabled.
|
||||
* @retval false The PDM interface is disabled.
|
||||
*/
|
||||
__STATIC_INLINE bool nrfx_pdm_enable_check(void)
|
||||
{
|
||||
return nrf_pdm_enable_check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for starting the PDM sampling.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Sampling was started successfully or was already in progress.
|
||||
* @retval NRFX_ERROR_BUSY Previous start/stop operation is in progress.
|
||||
*/
|
||||
nrfx_err_t nrfx_pdm_start(void);
|
||||
|
||||
/**
|
||||
* @brief Function for stopping the PDM sampling.
|
||||
*
|
||||
* When this function is called, the PDM interface is stopped after finishing
|
||||
* the current frame.
|
||||
* The event handler function might be called once more after calling this function.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Sampling was stopped successfully or was already stopped before.
|
||||
* @retval NRFX_ERROR_BUSY Previous start/stop operation is in progress.
|
||||
*/
|
||||
nrfx_err_t nrfx_pdm_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Function for supplying the sample buffer.
|
||||
*
|
||||
* Call this function after every buffer request event.
|
||||
*
|
||||
* @param[in] buffer Pointer to the receive buffer. Cannot be NULL.
|
||||
* @param[in] buffer_length Length of the receive buffer in 16-bit words.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The buffer was applied successfully.
|
||||
* @retval NRFX_ERROR_BUSY The buffer was already supplied or the peripheral is currently being stopped.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver was not initialized.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Invalid parameters were provided.
|
||||
*/
|
||||
nrfx_err_t nrfx_pdm_buffer_set(int16_t * buffer, uint16_t buffer_length);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_pdm_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_PDM_H__
|
||||
380
modules/nrfx/drivers/include/nrfx_power.h
Normal file
380
modules/nrfx/drivers/include/nrfx_power.h
Normal file
@@ -0,0 +1,380 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 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 NRFX_POWER_H__
|
||||
#define NRFX_POWER_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_power.h>
|
||||
#include <nrfx_power_clock.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_power POWER driver
|
||||
* @{
|
||||
* @ingroup nrf_power
|
||||
* @brief POWER peripheral driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Power mode possible configurations
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_POWER_MODE_CONSTLAT, /**< Constant latency mode */
|
||||
NRFX_POWER_MODE_LOWPWR /**< Low power mode */
|
||||
}nrfx_power_mode_t;
|
||||
|
||||
#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Events from power system
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_POWER_SLEEP_EVT_ENTER, /**< CPU entered WFI/WFE sleep
|
||||
*
|
||||
* Keep in mind that if this interrupt is enabled,
|
||||
* it means that CPU was waken up just after WFI by this interrupt.
|
||||
*/
|
||||
NRFX_POWER_SLEEP_EVT_EXIT /**< CPU exited WFI/WFE sleep */
|
||||
}nrfx_power_sleep_evt_t;
|
||||
#endif /* NRF_POWER_HAS_SLEEPEVT */
|
||||
|
||||
#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Events from USB power system
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_POWER_USB_EVT_DETECTED, /**< USB power detected on the connector (plugged in). */
|
||||
NRFX_POWER_USB_EVT_REMOVED, /**< USB power removed from the connector. */
|
||||
NRFX_POWER_USB_EVT_READY /**< USB power regulator ready. */
|
||||
}nrfx_power_usb_evt_t;
|
||||
|
||||
/**
|
||||
* @brief USB power state
|
||||
*
|
||||
* The single enumerator that holds all data about current state of USB
|
||||
* related POWER.
|
||||
*
|
||||
* Organized this way that higher power state has higher numeric value
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_POWER_USB_STATE_DISCONNECTED, /**< No power on USB lines detected. */
|
||||
NRFX_POWER_USB_STATE_CONNECTED, /**< The USB power is detected, but USB power regulator is not ready. */
|
||||
NRFX_POWER_USB_STATE_READY /**< From the power viewpoint, USB is ready for working. */
|
||||
}nrfx_power_usb_state_t;
|
||||
#endif /* NRF_POWER_HAS_USBREG */
|
||||
|
||||
/**
|
||||
* @name Callback types
|
||||
*
|
||||
* Defined types of callback functions.
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Event handler for power failure warning.
|
||||
*/
|
||||
typedef void (*nrfx_power_pofwarn_event_handler_t)(void);
|
||||
|
||||
#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Event handler for the sleep events.
|
||||
*
|
||||
* @param event Event type
|
||||
*/
|
||||
typedef void (*nrfx_power_sleep_event_handler_t)(nrfx_power_sleep_evt_t event);
|
||||
#endif
|
||||
|
||||
#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Event handler for the USB-related power events.
|
||||
*
|
||||
* @param event Event type
|
||||
*/
|
||||
typedef void (*nrfx_power_usb_event_handler_t)(nrfx_power_usb_evt_t event);
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief General power configuration
|
||||
*
|
||||
* Parameters required to initialize power driver.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
* @brief Enable main DCDC regulator.
|
||||
*
|
||||
* This bit only informs the driver that elements for DCDC regulator
|
||||
* are installed and the regulator can be used.
|
||||
* The regulator will be enabled or disabled automatically
|
||||
* by the hardware, basing on current power requirement.
|
||||
*/
|
||||
bool dcdcen:1;
|
||||
|
||||
#if NRF_POWER_HAS_VDDH || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Enable HV DCDC regulator.
|
||||
*
|
||||
* This bit only informs the driver that elements for DCDC regulator
|
||||
* are installed and the regulator can be used.
|
||||
* The regulator will be enabled or disabled automatically
|
||||
* by the hardware, basing on current power requirement.
|
||||
*/
|
||||
bool dcdcenhv: 1;
|
||||
#endif
|
||||
}nrfx_power_config_t;
|
||||
|
||||
/**
|
||||
* @brief The configuration for power failure comparator.
|
||||
*
|
||||
* Configuration used to enable and configure the power failure comparator.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_power_pofwarn_event_handler_t handler; //!< Event handler.
|
||||
#if NRF_POWER_HAS_POFCON || defined(__NRFX_DOXYGEN__)
|
||||
nrf_power_pof_thr_t thr; //!< Threshold for power failure detection
|
||||
#endif
|
||||
#if NRF_POWER_HAS_VDDH || defined(__NRFX_DOXYGEN__)
|
||||
nrf_power_pof_thrvddh_t thrvddh; //!< Threshold for power failure detection on the VDDH pin.
|
||||
#endif
|
||||
}nrfx_power_pofwarn_config_t;
|
||||
|
||||
#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief The configuration of sleep event processing.
|
||||
*
|
||||
* Configuration used to enable and configure sleep event handling.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_power_sleep_event_handler_t handler; //!< Event handler.
|
||||
bool en_enter:1; //!< Enable event on sleep entering.
|
||||
bool en_exit :1; //!< Enable event on sleep exiting.
|
||||
}nrfx_power_sleepevt_config_t;
|
||||
#endif
|
||||
|
||||
#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief The configuration of the USB-related power events.
|
||||
*
|
||||
* Configuration used to enable and configure USB power event handling.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_power_usb_event_handler_t handler; //!< Event processing.
|
||||
}nrfx_power_usbevt_config_t;
|
||||
#endif /* NRF_POWER_HAS_USBREG */
|
||||
|
||||
/**
|
||||
* @brief Function for getting the handler of the power failure comparator.
|
||||
* @return Handler of the power failure comparator.
|
||||
*/
|
||||
nrfx_power_pofwarn_event_handler_t nrfx_power_pof_handler_get(void);
|
||||
|
||||
#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for getting the handler of the USB power.
|
||||
* @return Handler of the USB power.
|
||||
*/
|
||||
nrfx_power_usb_event_handler_t nrfx_power_usb_handler_get(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the power module driver.
|
||||
*
|
||||
* Enabled power module driver processes all the interrupts from the power system.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Successfully initialized.
|
||||
* @retval NRFX_ERROR_ALREADY_INITIALIZED Module was already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_power_init(nrfx_power_config_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for unintializing the power module driver.
|
||||
*
|
||||
* Disables all the interrupt handling in the module.
|
||||
*
|
||||
* @sa nrfx_power_init
|
||||
*/
|
||||
void nrfx_power_uninit(void);
|
||||
|
||||
#if NRF_POWER_HAS_POFCON || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for initializing the power failure comparator.
|
||||
*
|
||||
* Configures the power failure comparator. This function does not set it up and enable it.
|
||||
* These steps can be done with functions @ref nrfx_power_pof_enable and @ref nrfx_power_pof_disable
|
||||
* or with the SoftDevice API (when in use).
|
||||
*
|
||||
* @param[in] p_config Configuration with values and event handler.
|
||||
* If event handler is set to NULL, the interrupt will be disabled.
|
||||
*/
|
||||
void nrfx_power_pof_init(nrfx_power_pofwarn_config_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the power failure comparator.
|
||||
* Sets and enables the interrupt of the power failure comparator. This function cannot be in use
|
||||
* when SoftDevice is enabled. If the event handler set in the init function is set to NULL, the interrupt
|
||||
* will be disabled.
|
||||
*
|
||||
* @param[in] p_config Configuration with values and event handler.
|
||||
*/
|
||||
void nrfx_power_pof_enable(nrfx_power_pofwarn_config_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the power failure comparator.
|
||||
*
|
||||
* Disables the power failure comparator interrupt.
|
||||
*/
|
||||
void nrfx_power_pof_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for clearing the power failure comparator settings.
|
||||
*
|
||||
* Clears the settings of the power failure comparator.
|
||||
*/
|
||||
void nrfx_power_pof_uninit(void);
|
||||
#endif // NRF_POWER_HAS_POFCON || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for initializing the processing of the sleep events.
|
||||
*
|
||||
* Configures and sets up the sleep event processing.
|
||||
*
|
||||
* @param[in] p_config Configuration with values and event handler.
|
||||
*
|
||||
* @sa nrfx_power_sleepevt_uninit
|
||||
*
|
||||
*/
|
||||
void nrfx_power_sleepevt_init(nrfx_power_sleepevt_config_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the processing of the sleep events.
|
||||
*
|
||||
* @param[in] p_config Configuration with values and event handler.
|
||||
*/
|
||||
void nrfx_power_sleepevt_enable(nrfx_power_sleepevt_config_t const * p_config);
|
||||
|
||||
/** @brief Function for disabling the processing of the sleep events. */
|
||||
void nrfx_power_sleepevt_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the processing of the sleep events.
|
||||
*
|
||||
* @sa nrfx_power_sleepevt_init
|
||||
*/
|
||||
void nrfx_power_sleepevt_uninit(void);
|
||||
#endif /* NRF_POWER_HAS_SLEEPEVT */
|
||||
|
||||
#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for initializing the processing of USB power event.
|
||||
*
|
||||
* Configures and sets up the USB power event processing.
|
||||
*
|
||||
* @param[in] p_config Configuration with values and event handler.
|
||||
*
|
||||
* @sa nrfx_power_usbevt_uninit
|
||||
*/
|
||||
void nrfx_power_usbevt_init(nrfx_power_usbevt_config_t const * p_config);
|
||||
|
||||
/** @brief Function for enabling the processing of USB power event. */
|
||||
void nrfx_power_usbevt_enable(void);
|
||||
|
||||
/** @brief Function for disabling the processing of USB power event. */
|
||||
void nrfx_power_usbevt_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitalizing the processing of USB power event.
|
||||
*
|
||||
* @sa nrfx_power_usbevt_init
|
||||
*/
|
||||
void nrfx_power_usbevt_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the status of USB power.
|
||||
*
|
||||
* @return Current USB power status.
|
||||
*/
|
||||
__STATIC_INLINE nrfx_power_usb_state_t nrfx_power_usbstatus_get(void);
|
||||
|
||||
#endif /* NRF_POWER_HAS_USBREG */
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
#if NRF_POWER_HAS_USBREG
|
||||
__STATIC_INLINE nrfx_power_usb_state_t nrfx_power_usbstatus_get(void)
|
||||
{
|
||||
uint32_t status = nrf_power_usbregstatus_get();
|
||||
if(0 == (status & NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK))
|
||||
{
|
||||
return NRFX_POWER_USB_STATE_DISCONNECTED;
|
||||
}
|
||||
if(0 == (status & NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK))
|
||||
{
|
||||
return NRFX_POWER_USB_STATE_CONNECTED;
|
||||
}
|
||||
return NRFX_POWER_USB_STATE_READY;
|
||||
}
|
||||
#endif /* NRF_POWER_HAS_USBREG */
|
||||
|
||||
#endif /* SUPPRESS_INLINE_IMPLEMENTATION */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_power_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRFX_POWER_H__ */
|
||||
92
modules/nrfx/drivers/include/nrfx_power_clock.h
Normal file
92
modules/nrfx/drivers/include/nrfx_power_clock.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_POWER_CLOCK_H__
|
||||
#define NRFX_POWER_CLOCK_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
__STATIC_INLINE void nrfx_power_clock_irq_init(void);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE void nrfx_power_clock_irq_init(void)
|
||||
{
|
||||
uint8_t priority;
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED) && NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
#if NRFX_POWER_CONFIG_IRQ_PRIORITY != NRFX_CLOCK_CONFIG_IRQ_PRIORITY
|
||||
#error "IRQ priorities for POWER and CLOCK must be the same. Check <nrfx_config.h>."
|
||||
#endif
|
||||
priority = NRFX_POWER_CONFIG_IRQ_PRIORITY;
|
||||
#elif NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
priority = NRFX_POWER_CONFIG_IRQ_PRIORITY;
|
||||
#elif NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
priority = NRFX_CLOCK_CONFIG_IRQ_PRIORITY;
|
||||
#else
|
||||
#error "This code is not supposed to be compiled when neither POWER nor CLOCK is enabled."
|
||||
#endif
|
||||
|
||||
if (!NRFX_IRQ_IS_ENABLED(nrfx_get_irq_number(NRF_CLOCK)))
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(NRF_CLOCK), priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(NRF_CLOCK));
|
||||
}
|
||||
}
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED) && NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
void nrfx_power_clock_irq_handler(void);
|
||||
#elif NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
#define nrfx_power_irq_handler nrfx_power_clock_irq_handler
|
||||
#elif NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
#define nrfx_clock_irq_handler nrfx_power_clock_irq_handler
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_POWER_CLOCK_H__
|
||||
331
modules/nrfx/drivers/include/nrfx_ppi.h
Normal file
331
modules/nrfx/drivers/include/nrfx_ppi.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_PPI_H__
|
||||
#define NRFX_PPI_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_ppi.h>
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_ppi PPI allocator
|
||||
* @{
|
||||
* @ingroup nrf_ppi
|
||||
* @brief Programmable Peripheral Interconnect (PPI) allocator.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined (NRFX_PPI_CHANNELS_USED) || defined(__NRFX_DOXYGEN__)
|
||||
/** @brief Bitfield representing PPI channels used by external modules. */
|
||||
#define NRFX_PPI_CHANNELS_USED 0
|
||||
#endif
|
||||
|
||||
#if !defined(NRFX_PPI_GROUPS_USED) || defined(__NRFX_DOXYGEN__)
|
||||
/** @brief Bitfield representing PPI groups used by external modules. */
|
||||
#define NRFX_PPI_GROUPS_USED 0
|
||||
#endif
|
||||
|
||||
#if (PPI_CH_NUM > 16) || defined(__NRFX_DOXYGEN__)
|
||||
/** @brief Bitfield representing all PPI channels available to the application. */
|
||||
#define NRFX_PPI_ALL_APP_CHANNELS_MASK ((uint32_t)0xFFFFFFFFuL & ~(NRFX_PPI_CHANNELS_USED))
|
||||
/** @brief Bitfield representing programmable PPI channels available to the application. */
|
||||
#define NRFX_PPI_PROG_APP_CHANNELS_MASK ((uint32_t)0x000FFFFFuL & ~(NRFX_PPI_CHANNELS_USED))
|
||||
#else
|
||||
#define NRFX_PPI_ALL_APP_CHANNELS_MASK ((uint32_t)0xFFF0FFFFuL & ~(NRFX_PPI_CHANNELS_USED))
|
||||
#define NRFX_PPI_PROG_APP_CHANNELS_MASK ((uint32_t)0x0000FFFFuL & ~(NRFX_PPI_CHANNELS_USED))
|
||||
#endif
|
||||
|
||||
/** @brief Bitfield representing all PPI groups available to the application. */
|
||||
#define NRFX_PPI_ALL_APP_GROUPS_MASK (((1uL << PPI_GROUP_NUM) - 1) & ~(NRFX_PPI_GROUPS_USED))
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the PPI module.
|
||||
*
|
||||
* This function disables all channels and clears the channel groups.
|
||||
*/
|
||||
void nrfx_ppi_free_all(void);
|
||||
|
||||
/**
|
||||
* @brief Function for allocating a PPI channel.
|
||||
* @details This function allocates the first unused PPI channel.
|
||||
*
|
||||
* @param[out] p_channel Pointer to the PPI channel that has been allocated.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully allocated.
|
||||
* @retval NRFX_ERROR_NO_MEM There is no available channel to be used.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channel_alloc(nrf_ppi_channel_t * p_channel);
|
||||
|
||||
/**
|
||||
* @brief Function for freeing a PPI channel.
|
||||
* @details This function also disables the chosen channel.
|
||||
*
|
||||
* @param[in] channel PPI channel to be freed.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully freed.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The channel is not user-configurable.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channel_free(nrf_ppi_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for assigning task and event endpoints to the PPI channel.
|
||||
*
|
||||
* @param[in] channel PPI channel to be assigned endpoints.
|
||||
* @param[in] eep Event endpoint address.
|
||||
* @param[in] tep Task endpoint address.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully assigned.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The channel is not allocated for the user.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The channel is not user-configurable.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep);
|
||||
|
||||
/**
|
||||
* @brief Function for assigning fork endpoint to the PPI channel or clearing it.
|
||||
*
|
||||
* @param[in] channel PPI channel to be assigned endpoints.
|
||||
* @param[in] fork_tep Fork task endpoint address or 0 to clear.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully assigned.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The channel is not allocated for the user.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED Function is not supported.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channel_fork_assign(nrf_ppi_channel_t channel, uint32_t fork_tep);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling a PPI channel.
|
||||
*
|
||||
* @param[in] channel PPI channel to be enabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully enabled.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The user-configurable channel is not allocated.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The channel cannot be enabled by the user.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channel_enable(nrf_ppi_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling a PPI channel.
|
||||
*
|
||||
* @param[in] channel PPI channel to be disabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully disabled.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The user-configurable channel is not allocated.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The channel cannot be disabled by the user.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channel_disable(nrf_ppi_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for allocating a PPI channel group.
|
||||
* @details This function allocates the first unused PPI group.
|
||||
*
|
||||
* @param[out] p_group Pointer to the PPI channel group that has been allocated.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel group was successfully allocated.
|
||||
* @retval NRFX_ERROR_NO_MEM There is no available channel group to be used.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_group_alloc(nrf_ppi_channel_group_t * p_group);
|
||||
|
||||
/**
|
||||
* @brief Function for freeing a PPI channel group.
|
||||
* @details This function also disables the chosen group.
|
||||
*
|
||||
* @param[in] group PPI channel group to be freed.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel group was successfully freed.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The channel group is not user-configurable.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_group_free(nrf_ppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Compute a channel mask for NRF_PPI registers.
|
||||
*
|
||||
* @param[in] channel Channel number to transform to a mask.
|
||||
*
|
||||
* @return Channel mask.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_ppi_channel_to_mask(nrf_ppi_channel_t channel)
|
||||
{
|
||||
return (1uL << (uint32_t) channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for including multiple PPI channels in a channel group.
|
||||
*
|
||||
* @param[in] channel_mask PPI channels to be added.
|
||||
* @param[in] group Channel group in which to include the channels.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channels was successfully included.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Group is not an application group or channels are not an
|
||||
* application channels.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Group is not an allocated group.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channels_include_in_group(uint32_t channel_mask,
|
||||
nrf_ppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for including a PPI channel in a channel group.
|
||||
*
|
||||
* @param[in] channel PPI channel to be added.
|
||||
* @param[in] group Channel group in which to include the channel.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully included.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Group is not an application group or channel is not an
|
||||
* application channel.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Group is not an allocated group.
|
||||
*/
|
||||
__STATIC_INLINE nrfx_err_t nrfx_ppi_channel_include_in_group(nrf_ppi_channel_t channel,
|
||||
nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return nrfx_ppi_channels_include_in_group(nrfx_ppi_channel_to_mask(channel), group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for removing multiple PPI channels from a channel group.
|
||||
*
|
||||
* @param[in] channel_mask PPI channels to be removed.
|
||||
* @param[in] group Channel group from which to remove the channels.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully removed.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Group is not an application group or channels are not an
|
||||
* application channels.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Group is not an allocated group.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_channels_remove_from_group(uint32_t channel_mask,
|
||||
nrf_ppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for removing a single PPI channel from a channel group.
|
||||
*
|
||||
* @param[in] channel PPI channel to be removed.
|
||||
* @param[in] group Channel group from which to remove the channel.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The channel was successfully removed.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Group is not an application group or channel is not an
|
||||
* application channel.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Group is not an allocated group.
|
||||
*/
|
||||
__STATIC_INLINE nrfx_err_t nrfx_ppi_channel_remove_from_group(nrf_ppi_channel_t channel,
|
||||
nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return nrfx_ppi_channels_remove_from_group(nrfx_ppi_channel_to_mask(channel), group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for clearing a PPI channel group.
|
||||
*
|
||||
* @param[in] group Channel group to be cleared.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The group was successfully cleared.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Group is not an application group.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Group is not an allocated group.
|
||||
*/
|
||||
__STATIC_INLINE nrfx_err_t nrfx_ppi_group_clear(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return nrfx_ppi_channels_remove_from_group(NRFX_PPI_ALL_APP_CHANNELS_MASK, group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for enabling a PPI channel group.
|
||||
*
|
||||
* @param[in] group Channel group to be enabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The group was successfully enabled.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Group is not an application group.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Group is not an allocated group.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_group_enable(nrf_ppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling a PPI channel group.
|
||||
*
|
||||
* @param[in] group Channel group to be disabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The group was successfully disabled.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Group is not an application group.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Group is not an allocated group.
|
||||
*/
|
||||
nrfx_err_t nrfx_ppi_group_disable(nrf_ppi_channel_group_t group);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of a PPI task.
|
||||
*
|
||||
* @param[in] task Task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_ppi_task_addr_get(nrf_ppi_task_t task)
|
||||
{
|
||||
return (uint32_t) nrf_ppi_task_address_get(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the enable task of a PPI group.
|
||||
*
|
||||
* @param[in] group PPI channel group
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_ppi_task_addr_group_enable_get(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return (uint32_t) nrf_ppi_task_group_enable_address_get(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the enable task of a PPI group.
|
||||
*
|
||||
* @param[in] group PPI channel group
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_ppi_task_addr_group_disable_get(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return (uint32_t) nrf_ppi_task_group_disable_address_get(group);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_PPI_H__
|
||||
476
modules/nrfx/drivers/include/nrfx_pwm.h
Normal file
476
modules/nrfx/drivers/include/nrfx_pwm.h
Normal file
@@ -0,0 +1,476 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_PWM_H__
|
||||
#define NRFX_PWM_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_pwm.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_pwm PWM driver
|
||||
* @{
|
||||
* @ingroup nrf_pwm
|
||||
* @brief Pulse Width Modulation (PWM) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief PWM driver instance data structure. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_PWM_Type * p_registers; ///< Pointer to the structure with PWM peripheral instance registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_pwm_t;
|
||||
|
||||
/** @brief Macro for creating a PWM driver instance. */
|
||||
#define NRFX_PWM_INSTANCE(id) \
|
||||
{ \
|
||||
.p_registers = NRFX_CONCAT_2(NRF_PWM, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_PWM, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_PWM0_ENABLED)
|
||||
NRFX_PWM0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_PWM1_ENABLED)
|
||||
NRFX_PWM1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_PWM2_ENABLED)
|
||||
NRFX_PWM2_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_PWM3_ENABLED)
|
||||
NRFX_PWM3_INST_IDX,
|
||||
#endif
|
||||
NRFX_PWM_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief This value can be provided instead of a pin number for any channel
|
||||
* to specify that its output is not used and therefore does not need
|
||||
* to be connected to a pin.
|
||||
*/
|
||||
#define NRFX_PWM_PIN_NOT_USED 0xFF
|
||||
|
||||
/** @brief This value can be added to a pin number to invert its polarity (set idle state = 1). */
|
||||
#define NRFX_PWM_PIN_INVERTED 0x80
|
||||
|
||||
/** @brief PWM driver configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t output_pins[NRF_PWM_CHANNEL_COUNT]; ///< Pin numbers for individual output channels (optional).
|
||||
/**< Use @ref NRFX_PWM_PIN_NOT_USED
|
||||
* if a given output channel is not needed. */
|
||||
uint8_t irq_priority; ///< Interrupt priority.
|
||||
nrf_pwm_clk_t base_clock; ///< Base clock frequency.
|
||||
nrf_pwm_mode_t count_mode; ///< Operating mode of the pulse generator counter.
|
||||
uint16_t top_value; ///< Value up to which the pulse generator counter counts.
|
||||
nrf_pwm_dec_load_t load_mode; ///< Mode of loading sequence data from RAM.
|
||||
nrf_pwm_dec_step_t step_mode; ///< Mode of advancing the active sequence.
|
||||
} nrfx_pwm_config_t;
|
||||
|
||||
/** @brief PWM driver default configuration. */
|
||||
#define NRFX_PWM_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.output_pins = { NRFX_PWM_DEFAULT_CONFIG_OUT0_PIN, \
|
||||
NRFX_PWM_DEFAULT_CONFIG_OUT1_PIN, \
|
||||
NRFX_PWM_DEFAULT_CONFIG_OUT2_PIN, \
|
||||
NRFX_PWM_DEFAULT_CONFIG_OUT3_PIN }, \
|
||||
.irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
.base_clock = (nrf_pwm_clk_t)NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK, \
|
||||
.count_mode = (nrf_pwm_mode_t)NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE, \
|
||||
.top_value = NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE, \
|
||||
.load_mode = (nrf_pwm_dec_load_t)NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE, \
|
||||
.step_mode = (nrf_pwm_dec_step_t)NRFX_PWM_DEFAULT_CONFIG_STEP_MODE, \
|
||||
}
|
||||
|
||||
/** @brief PWM flags that provide additional playback options. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_PWM_FLAG_STOP = 0x01, /**< When the requested playback is finished,
|
||||
the peripheral will be stopped.
|
||||
@note The STOP task is triggered when
|
||||
the last value of the final sequence is
|
||||
loaded from RAM, and the peripheral stops
|
||||
at the end of the current PWM period.
|
||||
For sequences with configured repeating
|
||||
of duty cycle values, this might result in
|
||||
less than the requested number of repeats
|
||||
of the last value. */
|
||||
NRFX_PWM_FLAG_LOOP = 0x02, /**< When the requested playback is finished,
|
||||
it will be started from the beginning.
|
||||
This flag is ignored if used together
|
||||
with @ref NRFX_PWM_FLAG_STOP.
|
||||
@note The playback restart is done via a
|
||||
shortcut configured in the PWM peripheral.
|
||||
This shortcut triggers the proper starting
|
||||
task when the final value of previous
|
||||
playback is read from RAM and applied to
|
||||
the pulse generator counter.
|
||||
When this mechanism is used together with
|
||||
the @ref NRF_PWM_STEP_TRIGGERED mode,
|
||||
the playback restart will occur right
|
||||
after switching to the final value (this
|
||||
final value will be played only once). */
|
||||
NRFX_PWM_FLAG_SIGNAL_END_SEQ0 = 0x04, /**< The event handler is to be
|
||||
called when the last value
|
||||
from sequence 0 is loaded. */
|
||||
NRFX_PWM_FLAG_SIGNAL_END_SEQ1 = 0x08, /**< The event handler is to be
|
||||
called when the last value
|
||||
from sequence 1 is loaded. */
|
||||
NRFX_PWM_FLAG_NO_EVT_FINISHED = 0x10, /**< The playback finished event
|
||||
(enabled by default) is to be
|
||||
suppressed. */
|
||||
NRFX_PWM_FLAG_START_VIA_TASK = 0x80, /**< The playback must not be
|
||||
started directly by the called
|
||||
function. Instead, the function
|
||||
must only prepare it and
|
||||
return the address of the task
|
||||
to be triggered to start the
|
||||
playback. */
|
||||
} nrfx_pwm_flag_t;
|
||||
|
||||
/** @brief PWM driver event type. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_PWM_EVT_FINISHED, ///< Sequence playback finished.
|
||||
NRFX_PWM_EVT_END_SEQ0, /**< End of sequence 0 reached. Its data can be
|
||||
safely modified now. */
|
||||
NRFX_PWM_EVT_END_SEQ1, /**< End of sequence 1 reached. Its data can be
|
||||
safely modified now. */
|
||||
NRFX_PWM_EVT_STOPPED, ///< The PWM peripheral has been stopped.
|
||||
} nrfx_pwm_evt_type_t;
|
||||
|
||||
/** @brief PWM driver event handler type. */
|
||||
typedef void (* nrfx_pwm_handler_t)(nrfx_pwm_evt_type_t event_type);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the PWM driver.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] handler Event handler provided by the user. If NULL is passed
|
||||
* instead, event notifications are not done and PWM
|
||||
* interrupts are disabled.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_pwm_init(nrfx_pwm_t const * const p_instance,
|
||||
nrfx_pwm_config_t const * p_config,
|
||||
nrfx_pwm_handler_t handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the PWM driver.
|
||||
*
|
||||
* If any sequence playback is in progress, it is stopped immediately.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_pwm_uninit(nrfx_pwm_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for starting a single sequence playback.
|
||||
*
|
||||
* To take advantage of the looping mechanism in the PWM peripheral, both
|
||||
* sequences must be used (single sequence can be played back only once by
|
||||
* the peripheral). Therefore, the provided sequence is internally set and
|
||||
* played back as both sequence 0 and sequence 1. Consequently, if the end of
|
||||
* sequence notifications are required, events for both sequences must be
|
||||
* used (that is, both the @ref NRFX_PWM_FLAG_SIGNAL_END_SEQ0 flag
|
||||
* and the @ref NRFX_PWM_FLAG_SIGNAL_END_SEQ1 flag must be specified, and
|
||||
* the @ref NRFX_PWM_EVT_END_SEQ0 event and the @ref NRFX_PWM_EVT_END_SEQ1
|
||||
* event must be handled in the same way).
|
||||
*
|
||||
* Use the @ref NRFX_PWM_FLAG_START_VIA_TASK flag if you want the playback
|
||||
* to be only prepared by this function, and you want to start it later by
|
||||
* triggering a task (for example, by using PPI). The function will then return
|
||||
* the address of the task to be triggered.
|
||||
*
|
||||
* @note The array containing the duty cycle values for the specified sequence
|
||||
* must be in RAM and cannot be allocated on the stack.
|
||||
* For detailed information, see @ref nrf_pwm_sequence_t.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_sequence Sequence to be played back.
|
||||
* @param[in] playback_count Number of playbacks to be performed (must not be 0).
|
||||
* @param[in] flags Additional options. Pass any combination of
|
||||
* @ref nrfx_pwm_flag_t "playback flags", or 0
|
||||
* for default settings.
|
||||
*
|
||||
* @return Address of the task to be triggered to start the playback if the @ref
|
||||
* NRFX_PWM_FLAG_START_VIA_TASK flag was used, 0 otherwise.
|
||||
*/
|
||||
uint32_t nrfx_pwm_simple_playback(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_sequence_t const * p_sequence,
|
||||
uint16_t playback_count,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief Function for starting a two-sequence playback.
|
||||
*
|
||||
* Use the @ref NRFX_PWM_FLAG_START_VIA_TASK flag if you want the playback
|
||||
* to be only prepared by this function, and you want to start it later by
|
||||
* triggering a task (using PPI for instance). The function will then return
|
||||
* the address of the task to be triggered.
|
||||
*
|
||||
* @note The array containing the duty cycle values for the specified sequence
|
||||
* must be in RAM and cannot be allocated on the stack.
|
||||
* For detailed information, see @ref nrf_pwm_sequence_t.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_sequence_0 First sequence to be played back.
|
||||
* @param[in] p_sequence_1 Second sequence to be played back.
|
||||
* @param[in] playback_count Number of playbacks to be performed (must not be 0).
|
||||
* @param[in] flags Additional options. Pass any combination of
|
||||
* @ref nrfx_pwm_flag_t "playback flags", or 0
|
||||
* for default settings.
|
||||
*
|
||||
* @return Address of the task to be triggered to start the playback if the @ref
|
||||
* NRFX_PWM_FLAG_START_VIA_TASK flag was used, 0 otherwise.
|
||||
*/
|
||||
uint32_t nrfx_pwm_complex_playback(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_sequence_t const * p_sequence_0,
|
||||
nrf_pwm_sequence_t const * p_sequence_1,
|
||||
uint16_t playback_count,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief Function for advancing the active sequence.
|
||||
*
|
||||
* This function only applies to @ref NRF_PWM_STEP_TRIGGERED mode.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_pwm_step(nrfx_pwm_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for stopping the sequence playback.
|
||||
*
|
||||
* The playback is stopped at the end of the current PWM period.
|
||||
* This means that if the active sequence is configured to repeat each duty
|
||||
* cycle value for a certain number of PWM periods, the last played value
|
||||
* might appear on the output less times than requested.
|
||||
*
|
||||
* @note This function can be instructed to wait until the playback is stopped
|
||||
* (by setting @p wait_until_stopped to true). Depending on
|
||||
* the length of the PMW period, this might take a significant amount of
|
||||
* time. Alternatively, the @ref nrfx_pwm_is_stopped function can be
|
||||
* used to poll the status, or the @ref NRFX_PWM_EVT_STOPPED event can
|
||||
* be used to get the notification when the playback is stopped, provided
|
||||
* the event handler is defined.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] wait_until_stopped If true, the function will not return until
|
||||
* the playback is stopped.
|
||||
*
|
||||
* @retval true The PWM peripheral is stopped.
|
||||
* @retval false The PWM peripheral is not stopped.
|
||||
*/
|
||||
bool nrfx_pwm_stop(nrfx_pwm_t const * const p_instance, bool wait_until_stopped);
|
||||
|
||||
/**
|
||||
* @brief Function for checking the status of the PWM peripheral.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The PWM peripheral is stopped.
|
||||
* @retval false The PWM peripheral is not stopped.
|
||||
*/
|
||||
bool nrfx_pwm_is_stopped(nrfx_pwm_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for updating the sequence data during playback.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] seq_id Identifier of the sequence (0 or 1).
|
||||
* @param[in] p_sequence Pointer to the new sequence definition.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
nrf_pwm_sequence_t const * p_sequence);
|
||||
|
||||
/**
|
||||
* @brief Function for updating the pointer to the duty cycle values
|
||||
* in the specified sequence during playback.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] seq_id Identifier of the sequence (0 or 1).
|
||||
* @param[in] values New pointer to the duty cycle values.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_values_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
nrf_pwm_values_t values);
|
||||
|
||||
/**
|
||||
* @brief Function for updating the number of duty cycle values
|
||||
* in the specified sequence during playback.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] seq_id Identifier of the sequence (0 or 1).
|
||||
* @param[in] length New number of the duty cycle values.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_length_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief Function for updating the number of repeats for duty cycle values
|
||||
* in the specified sequence during playback.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] seq_id Identifier of the sequence (0 or 1).
|
||||
* @param[in] repeats New number of repeats.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_repeats_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
uint32_t repeats);
|
||||
|
||||
/**
|
||||
* @brief Function for updating the additional delay after the specified
|
||||
* sequence during playback.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] seq_id Identifier of the sequence (0 or 1).
|
||||
* @param[in] end_delay New end delay value (in PWM periods).
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_end_delay_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
uint32_t end_delay);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of a specified PWM task that can
|
||||
* be used in PPI module.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] task Requested task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_pwm_task_address_get(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_task_t task);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of a specified PWM event that can
|
||||
* be used in PPI module.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] event Requested event.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_pwm_event_address_get(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_event_t event);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE void nrfx_pwm_step(nrfx_pwm_t const * const p_instance)
|
||||
{
|
||||
nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_NEXTSTEP);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
nrf_pwm_sequence_t const * p_sequence)
|
||||
{
|
||||
nrf_pwm_sequence_set(p_instance->p_registers, seq_id, p_sequence);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_values_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
nrf_pwm_values_t values)
|
||||
{
|
||||
nrf_pwm_seq_ptr_set(p_instance->p_registers, seq_id, values.p_raw);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_length_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
uint16_t length)
|
||||
{
|
||||
nrf_pwm_seq_cnt_set(p_instance->p_registers, seq_id, length);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_repeats_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
uint32_t repeats)
|
||||
{
|
||||
nrf_pwm_seq_refresh_set(p_instance->p_registers, seq_id, repeats);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_pwm_sequence_end_delay_update(nrfx_pwm_t const * const p_instance,
|
||||
uint8_t seq_id,
|
||||
uint32_t end_delay)
|
||||
{
|
||||
nrf_pwm_seq_end_delay_set(p_instance->p_registers, seq_id, end_delay);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_pwm_task_address_get(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_task_t task)
|
||||
{
|
||||
return nrf_pwm_task_address_get(p_instance->p_registers, task);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_pwm_event_address_get(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_event_t event)
|
||||
{
|
||||
return nrf_pwm_event_address_get(p_instance->p_registers, event);
|
||||
}
|
||||
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_pwm_0_irq_handler(void);
|
||||
void nrfx_pwm_1_irq_handler(void);
|
||||
void nrfx_pwm_2_irq_handler(void);
|
||||
void nrfx_pwm_3_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_PWM_H__
|
||||
198
modules/nrfx/drivers/include/nrfx_qdec.h
Normal file
198
modules/nrfx/drivers/include/nrfx_qdec.h
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_QDEC_H__
|
||||
#define NRFX_QDEC_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_qdec.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_qdec QDEC driver
|
||||
* @{
|
||||
* @ingroup nrf_qdec
|
||||
* @brief Quadrature Decoder (QDEC) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief QDEC configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_qdec_reportper_t reportper; /**< Report period in samples. */
|
||||
nrf_qdec_sampleper_t sampleper; /**< Sampling period in microseconds. */
|
||||
uint32_t psela; /**< Pin number for A input. */
|
||||
uint32_t pselb; /**< Pin number for B input. */
|
||||
uint32_t pselled; /**< Pin number for LED output. */
|
||||
uint32_t ledpre; /**< Time (in microseconds) how long LED is switched on before sampling. */
|
||||
nrf_qdec_ledpol_t ledpol; /**< Active LED polarity. */
|
||||
bool dbfen; /**< State of debouncing filter. */
|
||||
bool sample_inten; /**< Enabling sample ready interrupt. */
|
||||
uint8_t interrupt_priority; /**< QDEC interrupt priority. */
|
||||
} nrfx_qdec_config_t;
|
||||
|
||||
/**@brief QDEC default configuration. */
|
||||
#define NRFX_QDEC_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.reportper = (nrf_qdec_reportper_t)NRFX_QDEC_CONFIG_REPORTPER, \
|
||||
.sampleper = (nrf_qdec_sampleper_t)NRFX_QDEC_CONFIG_SAMPLEPER, \
|
||||
.psela = NRFX_QDEC_CONFIG_PIO_A, \
|
||||
.pselb = NRFX_QDEC_CONFIG_PIO_B, \
|
||||
.pselled = NRFX_QDEC_CONFIG_PIO_LED, \
|
||||
.ledpre = NRFX_QDEC_CONFIG_LEDPRE, \
|
||||
.ledpol = (nrf_qdec_ledpol_t)NRFX_QDEC_CONFIG_LEDPOL, \
|
||||
.dbfen = NRFX_QDEC_CONFIG_DBFEN, \
|
||||
.sample_inten = NRFX_QDEC_CONFIG_SAMPLE_INTEN, \
|
||||
.interrupt_priority = NRFX_QDEC_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/** @brief QDEC sample event data. */
|
||||
typedef struct
|
||||
{
|
||||
int8_t value; /**< Sample value. */
|
||||
} nrfx_qdec_sample_data_evt_t;
|
||||
|
||||
/** @brief QDEC report event data. */
|
||||
typedef struct
|
||||
{
|
||||
int16_t acc; /**< Accumulated transitions. */
|
||||
uint16_t accdbl; /**< Accumulated double transitions. */
|
||||
} nrfx_qdec_report_data_evt_t;
|
||||
|
||||
/** @brief QDEC event handler structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_qdec_event_t type; /**< Event type. */
|
||||
union
|
||||
{
|
||||
nrfx_qdec_sample_data_evt_t sample; /**< Sample event data. */
|
||||
nrfx_qdec_report_data_evt_t report; /**< Report event data. */
|
||||
} data; /**< Union to store event data. */
|
||||
} nrfx_qdec_event_t;
|
||||
|
||||
/**
|
||||
* @brief QDEC event handler.
|
||||
*
|
||||
* @param[in] event QDEC event structure.
|
||||
*/
|
||||
typedef void (*nrfx_qdec_event_handler_t)(nrfx_qdec_event_t event);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing QDEC.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The QDEC was already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_qdec_init(nrfx_qdec_config_t const * p_config,
|
||||
nrfx_qdec_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing QDEC.
|
||||
*
|
||||
* @note Function asserts if module is uninitialized.
|
||||
*/
|
||||
void nrfx_qdec_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling QDEC.
|
||||
*
|
||||
* @note Function asserts if module is uninitialized or enabled.
|
||||
*/
|
||||
void nrfx_qdec_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling QDEC.
|
||||
*
|
||||
* @note Function asserts if module is uninitialized or disabled.
|
||||
*/
|
||||
void nrfx_qdec_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for reading accumulated transitions from the QDEC peripheral.
|
||||
*
|
||||
* @note Function asserts if module is not enabled.
|
||||
* @note Accumulators are cleared after reading.
|
||||
*
|
||||
* @param[out] p_acc Pointer to store the accumulated transitions.
|
||||
* @param[out] p_accdbl Pointer to store the accumulated double transitions.
|
||||
*/
|
||||
void nrfx_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of the specified QDEC task.
|
||||
*
|
||||
* @param task QDEC task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_qdec_task_address_get(nrf_qdec_task_t task)
|
||||
{
|
||||
return (uint32_t)nrf_qdec_task_address_get(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of the specified QDEC event.
|
||||
*
|
||||
* @param event QDEC event.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_qdec_event_address_get(nrf_qdec_event_t event)
|
||||
{
|
||||
return (uint32_t)nrf_qdec_event_address_get(event);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_qdec_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_QDEC_H__
|
||||
330
modules/nrfx/drivers/include/nrfx_qspi.h
Normal file
330
modules/nrfx/drivers/include/nrfx_qspi.h
Normal file
@@ -0,0 +1,330 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 NRFX_QSPI_H__
|
||||
#define NRFX_QSPI_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_qspi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_qspi QSPI driver
|
||||
* @{
|
||||
* @ingroup nrf_qspi
|
||||
* @brief Quad Serial Peripheral Interface (QSPI) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief QSPI driver instance configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t xip_offset; /**< Address offset into the external memory for Execute in Place operation. */
|
||||
nrf_qspi_pins_t pins; /**< Pin configuration structure. */
|
||||
nrf_qspi_prot_conf_t prot_if; /**< Protocol layer interface configuration structure. */
|
||||
nrf_qspi_phy_conf_t phy_if; /**< Physical layer interface configuration structure. */
|
||||
uint8_t irq_priority; /**< Interrupt priority. */
|
||||
} nrfx_qspi_config_t;
|
||||
|
||||
/** @brief QSPI instance default configuration. */
|
||||
#define NRFX_QSPI_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.xip_offset = NRFX_QSPI_CONFIG_XIP_OFFSET, \
|
||||
.pins = { \
|
||||
.sck_pin = NRFX_QSPI_PIN_SCK, \
|
||||
.csn_pin = NRFX_QSPI_PIN_CSN, \
|
||||
.io0_pin = NRFX_QSPI_PIN_IO0, \
|
||||
.io1_pin = NRFX_QSPI_PIN_IO1, \
|
||||
.io2_pin = NRFX_QSPI_PIN_IO2, \
|
||||
.io3_pin = NRFX_QSPI_PIN_IO3, \
|
||||
}, \
|
||||
.prot_if = { \
|
||||
.readoc = (nrf_qspi_readoc_t)NRFX_QSPI_CONFIG_READOC, \
|
||||
.writeoc = (nrf_qspi_writeoc_t)NRFX_QSPI_CONFIG_WRITEOC, \
|
||||
.addrmode = (nrf_qspi_addrmode_t)NRFX_QSPI_CONFIG_ADDRMODE, \
|
||||
.dpmconfig = false, \
|
||||
}, \
|
||||
.phy_if = { \
|
||||
.sck_delay = (uint8_t)NRFX_QSPI_CONFIG_SCK_DELAY, \
|
||||
.dpmen = false, \
|
||||
.spi_mode = (nrf_qspi_spi_mode_t)NRFX_QSPI_CONFIG_MODE, \
|
||||
.sck_freq = (nrf_qspi_frequency_t)NRFX_QSPI_CONFIG_FREQUENCY, \
|
||||
}, \
|
||||
.irq_priority = (uint8_t)NRFX_QSPI_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/** @brief QSPI custom instruction helper with the default configuration. */
|
||||
#define NRFX_QSPI_DEFAULT_CINSTR(opc, len) \
|
||||
{ \
|
||||
.opcode = (opc), \
|
||||
.length = (len), \
|
||||
.io2_level = false, \
|
||||
.io3_level = false, \
|
||||
.wipwait = false, \
|
||||
.wren = false \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QSPI master driver event types, passed to the handler routine provided
|
||||
* during initialization.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_QSPI_EVENT_DONE, /**< Transfer done. */
|
||||
} nrfx_qspi_evt_t;
|
||||
|
||||
/** @brief QSPI driver event handler type. */
|
||||
typedef void (*nrfx_qspi_handler_t)(nrfx_qspi_evt_t event, void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the QSPI driver instance.
|
||||
*
|
||||
* This function configures the peripheral and its interrupts, and activates it. During the
|
||||
* activation process, the internal clocks are started and the QSPI peripheral tries to read
|
||||
* the status byte to read the busy bit. Reading the status byte is done in a simple poll and wait
|
||||
* mechanism.
|
||||
* If the busy bit is 1, this indicates issues with the external memory device. As a result,
|
||||
* @ref nrfx_qspi_init returns NRFX_ERROR_TIMEOUT.
|
||||
*
|
||||
* In case of issues:
|
||||
* - Check the connection.
|
||||
* - Make sure that the memory device does not perform other operations like erasing or writing.
|
||||
* - Check if there is a short circuit.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] handler Event handler provided by the user. If NULL, transfers
|
||||
* will be performed in blocking mode.
|
||||
* @param[in] p_context Pointer to context. Use in the interrupt handler.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_TIMEOUT The peripheral cannot connect with external memory.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM The pin configuration was incorrect.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_init(nrfx_qspi_config_t const * p_config,
|
||||
nrfx_qspi_handler_t handler,
|
||||
void * p_context);
|
||||
|
||||
/** @brief Function for uninitializing the QSPI driver instance. */
|
||||
void nrfx_qspi_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for reading data from the QSPI memory.
|
||||
*
|
||||
* Write, read, and erase operations check memory device busy state before starting the operation.
|
||||
* If the memory is busy, the resulting action depends on the mode in which the read operation is used:
|
||||
* - blocking mode (without handler) - a delay occurs until the last operation runs and
|
||||
* until the operation data is being read.
|
||||
* - interrupt mode (with handler) - event emission occurs after the last operation
|
||||
* and reading of data are finished.
|
||||
*
|
||||
* @param[out] p_rx_buffer Pointer to the receive buffer.
|
||||
* @param[in] rx_buffer_length Size of the data to read.
|
||||
* @param[in] src_address Address in memory to read from.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful (blocking mode) or operation
|
||||
* was commissioned (handler mode).
|
||||
* @retval NRFX_ERROR_BUSY The driver currently handles another operation.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffer is not placed in the Data RAM region
|
||||
* or its address is not aligned to a 32-bit word.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_read(void * p_rx_buffer,
|
||||
size_t rx_buffer_length,
|
||||
uint32_t src_address);
|
||||
|
||||
/**
|
||||
* @brief Function for writing data to QSPI memory.
|
||||
*
|
||||
* Write, read, and erase operations check memory device busy state before starting the operation.
|
||||
* If the memory is busy, the resulting action depends on the mode in which the write operation is used:
|
||||
* - blocking mode (without handler) - a delay occurs until the last operation runs or
|
||||
* until the operation data is being sent.
|
||||
* - interrupt mode (with handler) - event emission occurs after the last operation
|
||||
* and sending of operation data are finished.
|
||||
* To manually control operation execution in the memory device, use @ref nrfx_qspi_mem_busy_check
|
||||
* after executing the write function.
|
||||
* Remember that an incoming event signalizes only that data was sent to the memory device and the periheral
|
||||
* before the write operation checked if memory was busy.
|
||||
*
|
||||
* @param[in] p_tx_buffer Pointer to the writing buffer.
|
||||
* @param[in] tx_buffer_length Size of the data to write.
|
||||
* @param[in] dst_address Address in memory to write to.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful (blocking mode) or operation
|
||||
* was commissioned (handler mode).
|
||||
* @retval NRFX_ERROR_BUSY The driver currently handles other operation.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffer is not placed in the Data RAM region
|
||||
* or its address is not aligned to a 32-bit word.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_write(void const * p_tx_buffer,
|
||||
size_t tx_buffer_length,
|
||||
uint32_t dst_address);
|
||||
|
||||
/**
|
||||
* @brief Function for starting erasing of one memory block - 4KB, 64KB, or the whole chip.
|
||||
*
|
||||
* Write, read, and erase operations check memory device busy state before starting the operation.
|
||||
* If the memory is busy, the resulting action depends on the mode in which the erase operation is used:
|
||||
* - blocking mode (without handler) - a delay occurs until the last operation runs or
|
||||
* until the operation data is being sent.
|
||||
* - interrupt mode (with handler) - event emission occurs after the last operation
|
||||
* and sending of operation data are finished.
|
||||
* To manually control operation execution in the memory device, use @ref nrfx_qspi_mem_busy_check
|
||||
* after executing the erase function.
|
||||
* Remember that an incoming event signalizes only that data was sent to the memory device and the periheral
|
||||
* before the erase operation checked if memory was busy.
|
||||
*
|
||||
* @param[in] length Size of data to erase. See @ref nrf_qspi_erase_len_t.
|
||||
* @param[in] start_address Memory address to start erasing. If chip erase is performed, address
|
||||
* field is ommited.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful (blocking mode) or operation
|
||||
* was commissioned (handler mode).
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided start address is not aligned to a 32-bit word.
|
||||
* @retval NRFX_ERROR_BUSY The driver currently handles another operation.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_erase(nrf_qspi_erase_len_t length,
|
||||
uint32_t start_address);
|
||||
|
||||
/**
|
||||
* @brief Function for starting an erase operation of the whole chip.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful (blocking mode) or operation
|
||||
* was commissioned (handler mode).
|
||||
* @retval NRFX_ERROR_BUSY The driver currently handles another operation.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_chip_erase(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the current driver status and status byte of memory device with
|
||||
* testing WIP (write in progress) bit.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The driver and memory are ready to handle a new operation.
|
||||
* @retval NRFX_ERROR_BUSY The driver or memory currently handle another operation.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_mem_busy_check(void);
|
||||
|
||||
/**
|
||||
* @brief Function for sending operation code, sending data, and receiving data from the memory device.
|
||||
*
|
||||
* Use this function to transfer configuration data to memory and to receive data from memory.
|
||||
* Pointers can be addresses from flash memory.
|
||||
* This function is a synchronous function and should be used only if necessary.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with opcode and transfer configuration.
|
||||
* @param[in] p_tx_buffer Pointer to the array with data to send. Can be NULL if only opcode is transmitted.
|
||||
* @param[out] p_rx_buffer Pointer to the array for data to receive. Can be NULL if there is nothing to receive.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful.
|
||||
* @retval NRFX_ERROR_TIMEOUT The external memory is busy or there are connection issues.
|
||||
* @retval NRFX_ERROR_BUSY The driver currently handles other operation.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_cinstr_xfer(nrf_qspi_cinstr_conf_t const * p_config,
|
||||
void const * p_tx_buffer,
|
||||
void * p_rx_buffer);
|
||||
|
||||
/**
|
||||
* @brief Function for sending operation code and data to the memory device with simpler configuration.
|
||||
*
|
||||
* Use this function to transfer configuration data to memory and to receive data from memory.
|
||||
* This function is a synchronous function and should be used only if necessary.
|
||||
*
|
||||
* @param[in] opcode Operation code. Sending first.
|
||||
* @param[in] length Length of the data to send and opcode. See @ref nrf_qspi_cinstr_len_t.
|
||||
* @param[in] p_tx_buffer Pointer to input data array.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver currently handles another operation.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_cinstr_quick_send(uint8_t opcode,
|
||||
nrf_qspi_cinstr_len_t length,
|
||||
void const * p_tx_buffer);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the custom instruction long frame mode.
|
||||
*
|
||||
* The long frame mode is a mechanism that allows for arbitrary byte length custom instructions.
|
||||
* Use this function to initiate a custom transaction by sending custom instruction opcode.
|
||||
* To send and receive data, use @ref nrfx_qspi_lfm_xfer.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with custom instruction opcode and transfer
|
||||
* configuration. Transfer length must be set to @ref NRF_QSPI_CINSTR_LEN_1B.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Operation was successful.
|
||||
* @retval NRFX_ERROR_BUSY Driver currently handles other operation.
|
||||
* @retval NRFX_ERROR_TIMEOUT External memory is busy or there are connection issues.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_lfm_start(nrf_qspi_cinstr_conf_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for sending and receiving data in the custom instruction long frame mode.
|
||||
*
|
||||
* Both specified buffers must be at least @p transfer_length bytes in size.
|
||||
*
|
||||
* @param[in] p_tx_buffer Pointer to the array with data to send.
|
||||
* Can be NULL if there is nothing to send.
|
||||
* @param[out] p_rx_buffer Pointer to the array for receiving data.
|
||||
* Can be NULL if there is nothing to receive.
|
||||
* @param[in] transfer_length Number of bytes to send and receive.
|
||||
* @param[in] finalize True if custom instruction long frame mode is to be finalized
|
||||
* after this transfer.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Operation was successful.
|
||||
* @retval NRFX_ERROR_TIMEOUT External memory is busy or there are connection issues.
|
||||
* Long frame mode becomes deactivated.
|
||||
*/
|
||||
nrfx_err_t nrfx_qspi_lfm_xfer(void const * p_tx_buffer,
|
||||
void * p_rx_buffer,
|
||||
size_t transfer_length,
|
||||
bool finalize);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_qspi_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_QSPI_H__
|
||||
120
modules/nrfx/drivers/include/nrfx_rng.h
Normal file
120
modules/nrfx/drivers/include/nrfx_rng.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 NRFX_RNG_H__
|
||||
#define NRFX_RNG_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_rng.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_rng RNG driver
|
||||
* @{
|
||||
* @ingroup nrf_rng
|
||||
* @brief Random Number Generator (RNG) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Struct for RNG configuration. */
|
||||
typedef struct
|
||||
{
|
||||
bool error_correction : 1; /**< Error correction flag. */
|
||||
uint8_t interrupt_priority; /**< Interrupt priority. */
|
||||
} nrfx_rng_config_t;
|
||||
|
||||
/**
|
||||
* @brief RNG default configuration.
|
||||
* Basic usage:
|
||||
* @code
|
||||
* nrfx_rng_config_t config = NRFX_RNG_DEFAULT_CONFIG;
|
||||
* if (nrfx_rng_init(&config, handler)
|
||||
* { ...
|
||||
* @endcode
|
||||
*/
|
||||
#define NRFX_RNG_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.error_correction = NRFX_RNG_CONFIG_ERROR_CORRECTION, \
|
||||
.interrupt_priority = NRFX_RNG_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/** @brief RNG driver event handler type. */
|
||||
typedef void (* nrfx_rng_evt_handler_t)(uint8_t rng_data);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the nrfx_rng module.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] handler Event handler provided by the user. Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Driver was successfully initialized.
|
||||
* @retval NRFX_ERROR_ALREADY_INITIALIZED Driver was already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_rng_init(nrfx_rng_config_t const * p_config, nrfx_rng_evt_handler_t handler);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the generation of random values.
|
||||
*
|
||||
* New data should be handled by handler passed to the @ref nrfx_rng_init() function.
|
||||
*/
|
||||
void nrfx_rng_start(void);
|
||||
|
||||
/**
|
||||
* @brief Function for stopping the generation of random values.
|
||||
*
|
||||
* Function disables interrupts in peripheral and stops the generation of new random values.
|
||||
*/
|
||||
void nrfx_rng_stop(void);
|
||||
|
||||
/** @brief Function for uninitializing the nrfx_rng module. */
|
||||
void nrfx_rng_uninit(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_rng_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_RNG_H__
|
||||
378
modules/nrfx/drivers/include/nrfx_rtc.h
Normal file
378
modules/nrfx/drivers/include/nrfx_rtc.h
Normal file
@@ -0,0 +1,378 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 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 NRFX_RTC_H__
|
||||
#define NRFX_RTC_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_rtc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_rtc RTC driver
|
||||
* @{
|
||||
* @ingroup nrf_rtc
|
||||
* @brief Real Timer Counter (RTC) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Macro for converting microseconds into ticks. */
|
||||
#define NRFX_RTC_US_TO_TICKS(us,freq) (((us) * (freq)) / 1000000U)
|
||||
|
||||
/** @brief RTC driver interrupt types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_RTC_INT_COMPARE0 = 0, /**< Interrupt from COMPARE0 event. */
|
||||
NRFX_RTC_INT_COMPARE1 = 1, /**< Interrupt from COMPARE1 event. */
|
||||
NRFX_RTC_INT_COMPARE2 = 2, /**< Interrupt from COMPARE2 event. */
|
||||
NRFX_RTC_INT_COMPARE3 = 3, /**< Interrupt from COMPARE3 event. */
|
||||
NRFX_RTC_INT_TICK = 4, /**< Interrupt from TICK event. */
|
||||
NRFX_RTC_INT_OVERFLOW = 5 /**< Interrupt from OVERFLOW event. */
|
||||
} nrfx_rtc_int_type_t;
|
||||
|
||||
/** @brief RTC driver instance structure. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_RTC_Type * p_reg; /**< Pointer to instance register set. */
|
||||
IRQn_Type irq; /**< Instance IRQ ID. */
|
||||
uint8_t instance_id; /**< Index of the driver instance. For internal use only. */
|
||||
uint8_t cc_channel_count; /**< Number of capture/compare channels. */
|
||||
} nrfx_rtc_t;
|
||||
|
||||
/** @brief Macro for creating an RTC driver instance. */
|
||||
#define NRFX_RTC_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_RTC, id), \
|
||||
.irq = NRFX_CONCAT_3(RTC, id, _IRQn), \
|
||||
.instance_id = NRFX_CONCAT_3(NRFX_RTC, id, _INST_IDX), \
|
||||
.cc_channel_count = NRF_RTC_CC_CHANNEL_COUNT(id), \
|
||||
}
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_RTC0_ENABLED)
|
||||
NRFX_RTC0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_RTC1_ENABLED)
|
||||
NRFX_RTC1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_RTC2_ENABLED)
|
||||
NRFX_RTC2_INST_IDX,
|
||||
#endif
|
||||
NRFX_RTC_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief RTC driver instance configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t prescaler; /**< Prescaler. */
|
||||
uint8_t interrupt_priority; /**< Interrupt priority. */
|
||||
uint8_t tick_latency; /**< Maximum length of the interrupt handler in ticks (maximum 7.7 ms). */
|
||||
bool reliable; /**< Reliable mode flag. */
|
||||
} nrfx_rtc_config_t;
|
||||
|
||||
/** @brief RTC instance default configuration. */
|
||||
#define NRFX_RTC_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.prescaler = RTC_FREQ_TO_PRESCALER(NRFX_RTC_DEFAULT_CONFIG_FREQUENCY), \
|
||||
.interrupt_priority = NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
.tick_latency = NRFX_RTC_US_TO_TICKS(NRFX_RTC_MAXIMUM_LATENCY_US, \
|
||||
NRFX_RTC_DEFAULT_CONFIG_FREQUENCY), \
|
||||
.reliable = NRFX_RTC_DEFAULT_CONFIG_RELIABLE, \
|
||||
}
|
||||
|
||||
/** @brief RTC driver instance handler type. */
|
||||
typedef void (*nrfx_rtc_handler_t)(nrfx_rtc_int_type_t int_type);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the RTC driver instance.
|
||||
*
|
||||
* After initialization, the instance is in power off state.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] handler Event handler provided by the user.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Successfully initialized.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The instance is already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const * const p_instance,
|
||||
nrfx_rtc_config_t const * p_config,
|
||||
nrfx_rtc_handler_t handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the RTC driver instance.
|
||||
*
|
||||
* After uninitialization, the instance is in idle state. The hardware should return to the state
|
||||
* before initialization.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_rtc_uninit(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the RTC driver instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_rtc_enable(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the RTC driver instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_rtc_disable(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for setting a compare channel.
|
||||
*
|
||||
* The function powers on the instance if the instance was in power off state.
|
||||
*
|
||||
* The driver is not entering a critical section when configuring RTC, which means that it can be
|
||||
* preempted for a certain amount of time. When the driver was preempted and the value to be set
|
||||
* is short in time, there is a risk that the driver sets a compare value that is
|
||||
* behind. In this case, if the reliable mode is enabled for the specified instance,
|
||||
* the risk is handled.
|
||||
* However, to detect if the requested value is behind, this mode makes the following assumptions:
|
||||
* - The maximum preemption time in ticks (8-bit value) is known and is less than 7.7 ms
|
||||
* (for prescaler = 0, RTC frequency 32 kHz).
|
||||
* - The requested absolute compare value is not bigger than (0x00FFFFFF)-tick_latency. It is
|
||||
* the user's responsibility to ensure this.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] channel One of the channels of the instance.
|
||||
* @param[in] val Absolute value to be set in the compare register.
|
||||
* @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_TIMEOUT The compare is not set because the request value is behind the
|
||||
* current counter value. This error can only be reported
|
||||
* if the reliable mode is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance,
|
||||
uint32_t channel,
|
||||
uint32_t val,
|
||||
bool enable_irq);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling a channel.
|
||||
*
|
||||
* This function disables channel events and channel interrupts.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] channel One of the channels of the instance.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_TIMEOUT Interrupt is pending on the requested channel.
|
||||
*/
|
||||
nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * const p_instance, uint32_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the TICK event.
|
||||
*
|
||||
* This function enables the tick event and optionally the interrupt.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
|
||||
*/
|
||||
void nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance, bool enable_irq);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the TICK event.
|
||||
*
|
||||
* This function disables the TICK event and interrupt.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_rtc_tick_disable(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling overflow.
|
||||
*
|
||||
* This function enables the overflow event and optionally the interrupt.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
|
||||
*/
|
||||
void nrfx_rtc_overflow_enable(nrfx_rtc_t const * const p_instance, bool enable_irq);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling overflow.
|
||||
*
|
||||
* This function disables the overflow event and interrupt.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_rtc_overflow_disable(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the maximum relative tick value that can be set in the compare channel.
|
||||
*
|
||||
* When a stack (for example SoftDevice) is used and it occupies high priority interrupts,
|
||||
* the application code can be interrupted at any moment for a certain period of time.
|
||||
* If the reliable mode is enabled, the provided maximum latency is taken into account
|
||||
* and the return value is smaller than the RTC counter resolution.
|
||||
* If the reliable mode is disabled, the return value equals the counter resolution.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Maximum ticks value.
|
||||
*/
|
||||
uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling all instance interrupts.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_mask Pointer to the location where the mask is filled.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * const p_instance,
|
||||
uint32_t * p_mask);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling instance interrupts.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] mask Mask of interrupts to enable.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * const p_instance, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Function for retrieving the current counter value.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Counter value.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for clearing the counter value.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
__STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for returning a requested task address for the RTC driver instance.
|
||||
*
|
||||
* The task address can be used by the PPI module.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the instance.
|
||||
* @param[in] task One of the peripheral tasks.
|
||||
*
|
||||
* @return Address of task register.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * const p_instance,
|
||||
nrf_rtc_task_t task);
|
||||
|
||||
/**
|
||||
* @brief Function for returning a requested event address for the RTC driver instance.
|
||||
*
|
||||
* The event address can be used by the PPI module.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] event One of the peripheral events.
|
||||
*
|
||||
* @return Address of event register.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * const p_instance,
|
||||
nrf_rtc_event_t event);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * const p_instance,
|
||||
uint32_t * p_mask)
|
||||
{
|
||||
*p_mask = nrf_rtc_int_get(p_instance->p_reg);
|
||||
nrf_rtc_int_disable(p_instance->p_reg, NRF_RTC_INT_TICK_MASK |
|
||||
NRF_RTC_INT_OVERFLOW_MASK |
|
||||
NRF_RTC_INT_COMPARE0_MASK |
|
||||
NRF_RTC_INT_COMPARE1_MASK |
|
||||
NRF_RTC_INT_COMPARE2_MASK |
|
||||
NRF_RTC_INT_COMPARE3_MASK);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * const p_instance, uint32_t mask)
|
||||
{
|
||||
nrf_rtc_int_enable(p_instance->p_reg, mask);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
return nrf_rtc_counter_get(p_instance->p_reg);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_CLEAR);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * const p_instance,
|
||||
nrf_rtc_task_t task)
|
||||
{
|
||||
return nrf_rtc_task_address_get(p_instance->p_reg, task);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * const p_instance,
|
||||
nrf_rtc_event_t event)
|
||||
{
|
||||
return nrf_rtc_event_address_get(p_instance->p_reg, event);
|
||||
}
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_rtc_0_irq_handler(void);
|
||||
void nrfx_rtc_1_irq_handler(void);
|
||||
void nrfx_rtc_2_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_RTC_H__
|
||||
322
modules/nrfx/drivers/include/nrfx_saadc.h
Normal file
322
modules/nrfx/drivers/include/nrfx_saadc.h
Normal file
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_SAADC_H__
|
||||
#define NRFX_SAADC_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_saadc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(NRFX_SAADC_API_V2)
|
||||
#include "nrfx_saadc_v2.h"
|
||||
#else
|
||||
/**
|
||||
* @defgroup nrfx_saadc SAADC legacy driver
|
||||
* @{
|
||||
* @ingroup nrf_saadc
|
||||
* @brief Successive Approximation Analog-to-Digital Converter (SAADC) peripheral legacy driver.
|
||||
*/
|
||||
|
||||
/** @brief Value to be set as high limit to disable limit detection. */
|
||||
#define NRFX_SAADC_LIMITH_DISABLED (2047)
|
||||
/** @brief Value to be set as low limit to disable limit detection. */
|
||||
#define NRFX_SAADC_LIMITL_DISABLED (-2048)
|
||||
|
||||
/** @brief Macro for setting @ref nrfx_saadc_config_t to default settings. */
|
||||
#define NRFX_SAADC_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.resolution = (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION, \
|
||||
.oversample = (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE, \
|
||||
.interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY, \
|
||||
.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for setting @ref nrf_saadc_channel_config_t to default settings
|
||||
* in single-ended mode.
|
||||
*
|
||||
* @param PIN_P Analog input.
|
||||
*/
|
||||
#define NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
|
||||
{ \
|
||||
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.gain = NRF_SAADC_GAIN1_6, \
|
||||
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
|
||||
.acq_time = NRF_SAADC_ACQTIME_10US, \
|
||||
.mode = NRF_SAADC_MODE_SINGLE_ENDED, \
|
||||
.burst = NRF_SAADC_BURST_DISABLED, \
|
||||
.pin_p = (nrf_saadc_input_t)(PIN_P), \
|
||||
.pin_n = NRF_SAADC_INPUT_DISABLED \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for setting @ref nrf_saadc_channel_config_t to default settings
|
||||
* in differential mode.
|
||||
*
|
||||
* @param PIN_P Positive analog input.
|
||||
* @param PIN_N Negative analog input.
|
||||
*/
|
||||
#define NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(PIN_P, PIN_N) \
|
||||
{ \
|
||||
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.gain = NRF_SAADC_GAIN1_6, \
|
||||
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
|
||||
.acq_time = NRF_SAADC_ACQTIME_10US, \
|
||||
.mode = NRF_SAADC_MODE_DIFFERENTIAL, \
|
||||
.burst = NRF_SAADC_BURST_DISABLED, \
|
||||
.pin_p = (nrf_saadc_input_t)(PIN_P), \
|
||||
.pin_n = (nrf_saadc_input_t)(PIN_N) \
|
||||
}
|
||||
|
||||
/** @brief SAADC driver configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_saadc_resolution_t resolution; ///< Resolution configuration.
|
||||
nrf_saadc_oversample_t oversample; ///< Oversampling configuration.
|
||||
uint8_t interrupt_priority; ///< Interrupt priority.
|
||||
bool low_power_mode; ///< Indicates if low power mode is active.
|
||||
} nrfx_saadc_config_t;
|
||||
|
||||
/** @brief SAADC driver event types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_SAADC_EVT_DONE, ///< Event generated when the buffer is filled with samples.
|
||||
NRFX_SAADC_EVT_LIMIT, ///< Event generated after one of the limits is reached.
|
||||
NRFX_SAADC_EVT_CALIBRATEDONE ///< Event generated when the calibration is complete.
|
||||
} nrfx_saadc_evt_type_t;
|
||||
|
||||
/** @brief SAADC driver done event data. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_saadc_value_t * p_buffer; ///< Pointer to buffer with converted samples.
|
||||
uint16_t size; ///< Number of samples in the buffer.
|
||||
} nrfx_saadc_done_evt_t;
|
||||
|
||||
/** @brief SAADC driver limit event data. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t channel; ///< Channel on which the limit was detected.
|
||||
nrf_saadc_limit_t limit_type; ///< Type of limit detected.
|
||||
} nrfx_saadc_limit_evt_t;
|
||||
|
||||
/** @brief SAADC driver event structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_saadc_evt_type_t type; ///< Event type.
|
||||
union
|
||||
{
|
||||
nrfx_saadc_done_evt_t done; ///< Data for @ref NRFX_SAADC_EVT_DONE event.
|
||||
nrfx_saadc_limit_evt_t limit; ///< Data for @ref NRFX_SAADC_EVT_LIMIT event.
|
||||
} data; ///< Union to store event data.
|
||||
} nrfx_saadc_evt_t;
|
||||
|
||||
/**
|
||||
* @brief SAADC driver event handler.
|
||||
*
|
||||
* @param[in] p_event Pointer to an SAADC driver event. The event structure is allocated on
|
||||
* the stack, so it is valid only within the context of the event handler.
|
||||
*/
|
||||
typedef void (* nrfx_saadc_event_handler_t)(nrfx_saadc_evt_t const * p_event);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the SAADC.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config,
|
||||
nrfx_saadc_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the SAADC.
|
||||
*
|
||||
* This function stops all ongoing conversions and disables all channels.
|
||||
*/
|
||||
void nrfx_saadc_uninit(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of a SAMPLE SAADC task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
uint32_t nrfx_saadc_sample_task_get(void);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing an SAADC channel.
|
||||
*
|
||||
* This function configures and enables the channel.
|
||||
*
|
||||
* @param[in] channel Channel index.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The SAADC was not initialized.
|
||||
* @retval NRFX_ERROR_NO_MEM The specified channel was already allocated.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_channel_init(uint8_t channel,
|
||||
nrf_saadc_channel_config_t const * const p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing an SAADC channel.
|
||||
*
|
||||
* @param[in] channel Channel index.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Uninitialization was successful.
|
||||
* @retval NRFX_ERROR_BUSY The SAADC is busy.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_channel_uninit(uint8_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the SAADC sampling.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The SAADC sampling was triggered.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The SAADC is in idle state.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_sample(void);
|
||||
|
||||
/**
|
||||
* @brief Blocking function for executing a single SAADC conversion.
|
||||
*
|
||||
* This function selects the desired input, starts a single conversion,
|
||||
* waits for it to finish, and returns the result.
|
||||
*
|
||||
* The function fails if the SAADC is busy.
|
||||
*
|
||||
* @param[in] channel Channel.
|
||||
* @param[out] p_value Pointer to the location where the result is to be placed.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The conversion was successful.
|
||||
* @retval NRFX_ERROR_BUSY The SAADC driver is busy.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value);
|
||||
|
||||
/**
|
||||
* @brief Function for issuing conversion of data to the buffer.
|
||||
*
|
||||
* This function is non-blocking. The application is notified about filling the buffer by the event
|
||||
* handler. Conversion will be done on all enabled channels. If the SAADC is in idle state, the
|
||||
* function will set up EasyDMA for the conversion. The SAADC will be ready for sampling and wait
|
||||
* for the SAMPLE task. It can be triggered manually by the @ref nrfx_saadc_sample function
|
||||
* or by PPI using the @ref NRF_SAADC_TASK_SAMPLE task. If one buffer is already set and the
|
||||
* conversion is ongoing, calling this function will result in queuing the given buffer.
|
||||
* The driver will start filling the issued buffer when the first one is completed.
|
||||
* If the function is called again before the first buffer is filled or calibration
|
||||
* is in progress, it will return with error.
|
||||
*
|
||||
* @param[in] buffer Result buffer.
|
||||
* @param[in] size Buffer size in words.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The conversion was successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver already has two buffers set or the calibration is in progress.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * buffer, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief Function for triggering the SAADC offset calibration.
|
||||
*
|
||||
* This function is non-blocking. The application is notified about completion by the event handler.
|
||||
* Calibration will also trigger DONE and RESULTDONE events.
|
||||
*
|
||||
* The function will fail if the SAADC is busy or calibration is already in progress.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The calibration was started successfully.
|
||||
* @retval NRFX_ERROR_BUSY The SAADC driver is busy.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_calibrate_offset(void);
|
||||
|
||||
/**
|
||||
* @brief Function for retrieving the SAADC state.
|
||||
*
|
||||
* @retval true The SAADC is busy.
|
||||
* @retval false The SAADC is ready.
|
||||
*/
|
||||
bool nrfx_saadc_is_busy(void);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting the ongoing and buffered conversions.
|
||||
*
|
||||
* @note @ref NRFX_SAADC_EVT_DONE event will be generated if there is a conversion in progress.
|
||||
* Event will contain number of words in the sample buffer.
|
||||
*
|
||||
* @warning This function must not be called from the context of event handler of the SAADC driver
|
||||
* or from the context of interrupt with priority equal to or higher than priority
|
||||
* of the SAADC interrupt.
|
||||
*/
|
||||
void nrfx_saadc_abort(void);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the SAADC channel limits.
|
||||
* When limits are enabled and the result exceeds the defined bounds, the limit handler
|
||||
* function is called.
|
||||
*
|
||||
* @param[in] channel SAADC channel number.
|
||||
* @param[in] limit_low Lower limit (valid values from @ref NRFX_SAADC_LIMITL_DISABLED to
|
||||
* @ref NRFX_SAADC_LIMITH_DISABLED). Conversion results below this value will
|
||||
* trigger the handler function. Set to @ref NRFX_SAADC_LIMITL_DISABLED
|
||||
* to disable this limit.
|
||||
* @param[in] limit_high Upper limit (valid values from @ref NRFX_SAADC_LIMITL_DISABLED to
|
||||
* @ref NRFX_SAADC_LIMITH_DISABLED). Conversion results above this value will
|
||||
* trigger the handler function. Set to @ref NRFX_SAADC_LIMITH_DISABLED
|
||||
* to disable this limit.
|
||||
*/
|
||||
void nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high);
|
||||
|
||||
/** @} */
|
||||
#endif // defined(NRFX_SAADC_API_V2)
|
||||
|
||||
void nrfx_saadc_irq_handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_SAADC_H__
|
||||
|
||||
382
modules/nrfx/drivers/include/nrfx_saadc_v2.h
Normal file
382
modules/nrfx/drivers/include/nrfx_saadc_v2.h
Normal file
@@ -0,0 +1,382 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 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 NRFX_SAADC_V2_H__
|
||||
#define NRFX_SAADC_V2_H__
|
||||
|
||||
#ifndef NRFX_SAADC_H__
|
||||
#error "This file should not be included directly. Include nrfx_saadc.h instead."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_saadc_v2 SAADC v2 driver
|
||||
* @{
|
||||
* @ingroup nrf_saadc
|
||||
* @brief Successive Approximation Analog-to-Digital Converter (SAADC) peripheral v2 driver.
|
||||
* @details API description can be found <a href="../../drivers/include/nrfx_saadc_v2.h">here</a>.
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief SAADC channel default configuration for the single-ended mode.
|
||||
*
|
||||
* This configuration sets up single-ended SAADC channel with the following options:
|
||||
* - resistor ladder disabled
|
||||
* - gain: 1/6
|
||||
* - reference voltage: internal 0.6 V
|
||||
* - sample acquisition time: 10 us
|
||||
* - burst disabled
|
||||
*
|
||||
* @param[in] _pin_p Positive input analog pin.
|
||||
* @param[in] _index Channel index.
|
||||
*
|
||||
* @sa nrfx_saadc_channel_t
|
||||
*/
|
||||
#define NRFX_SAADC_DEFAULT_CHANNEL_SE(_pin_p, _index) \
|
||||
{ \
|
||||
.channel_config = \
|
||||
{ \
|
||||
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.gain = NRF_SAADC_GAIN1_6, \
|
||||
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
|
||||
.acq_time = NRF_SAADC_ACQTIME_10US, \
|
||||
.mode = NRF_SAADC_MODE_SINGLE_ENDED, \
|
||||
.burst = NRF_SAADC_BURST_DISABLED, \
|
||||
}, \
|
||||
.pin_p = (nrf_saadc_input_t)_pin_p, \
|
||||
.pin_n = NRF_SAADC_INPUT_DISABLED, \
|
||||
.channel_index = _index, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SAADC channel default configuration for the differential mode.
|
||||
*
|
||||
* This configuration sets up differential SAADC channel with the following options:
|
||||
* - resistor ladder disabled
|
||||
* - gain: 1/6
|
||||
* - reference voltage: internal 0.6 V
|
||||
* - sample acquisition time: 10 us
|
||||
* - burst disabled
|
||||
*
|
||||
* @param[in] _pin_p Positive input analog pin.
|
||||
* @param[in] _pin_n Negative input analog pin.
|
||||
* @param[in] _index Channel index.
|
||||
*
|
||||
* @sa nrfx_saadc_channel_t
|
||||
*/
|
||||
#define NRFX_SAADC_DEFAULT_CHANNEL_DIFFERENTIAL(_pin_p, _pin_n, _index) \
|
||||
{ \
|
||||
.channel_config = \
|
||||
{ \
|
||||
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
|
||||
.gain = NRF_SAADC_GAIN1_6, \
|
||||
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
|
||||
.acq_time = NRF_SAADC_ACQTIME_10US, \
|
||||
.mode = NRF_SAADC_MODE_DIFFERENTIAL, \
|
||||
.burst = NRF_SAADC_BURST_DISABLED, \
|
||||
}, \
|
||||
.pin_p = (nrf_saadc_input_t)_pin_p, \
|
||||
.pin_n = (nrf_saadc_input_t)_pin_n, \
|
||||
.channel_index = _index, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SAADC driver advanced mode default configuration.
|
||||
*
|
||||
* This configuration sets up advanced mode of the SAADC driver with the following options:
|
||||
* - oversampling disabled
|
||||
* - burst disabled
|
||||
* - internal sampling timer disabled
|
||||
* - triggering of the START task on the END event disabled
|
||||
*
|
||||
* @param[in] _pin_p Positive input analog pin.
|
||||
* @param[in] _pin_n Negative input analog pin.
|
||||
* @param[in] _index Channel index.
|
||||
*
|
||||
* @sa nrfx_saadc_adv_config_t
|
||||
*/
|
||||
#define NRFX_SAADC_DEFAULT_ADV_CONFIG \
|
||||
{ \
|
||||
.oversampling = NRF_SAADC_OVERSAMPLE_DISABLED, \
|
||||
.burst = NRF_SAADC_BURST_DISABLED, \
|
||||
.internal_timer_cc = 0, \
|
||||
.start_on_end = false, \
|
||||
}
|
||||
|
||||
/** @brief SAADC channel configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_saadc_channel_config_t channel_config; ///< Channel hardware configuration.
|
||||
nrf_saadc_input_t pin_p; ///< Input positive pin selection.
|
||||
nrf_saadc_input_t pin_n; ///< Input negative pin selection.
|
||||
uint8_t channel_index; ///< Channel index.
|
||||
} nrfx_saadc_channel_t;
|
||||
|
||||
/** @brief SAADC driver advanced mode configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_saadc_oversample_t oversampling; ///< Oversampling configuration.
|
||||
nrf_saadc_burst_t burst; ///< Burst configuration.
|
||||
uint16_t internal_timer_cc; ///< Internal timer capture and compare value.
|
||||
bool start_on_end; ///< Flag indicating if the START task is to be triggered on the END event.
|
||||
} nrfx_saadc_adv_config_t;
|
||||
|
||||
/** @brief SAADC driver event types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_SAADC_EVT_DONE, ///< Event generated when the buffer is filled with samples.
|
||||
NRFX_SAADC_EVT_LIMIT, ///< Event generated when one of the limits is reached.
|
||||
NRFX_SAADC_EVT_CALIBRATEDONE, ///< Event generated when the calibration is complete.
|
||||
NRFX_SAADC_EVT_BUF_REQ, ///< Event generated when the next buffer for continuous conversion is requested.
|
||||
NRFX_SAADC_EVT_READY, ///< Event generated when the first buffer is acquired by the peripheral and sampling can be started.
|
||||
NRFX_SAADC_EVT_FINISHED, ///< Event generated when all supplied buffers are filled with results.
|
||||
} nrfx_saadc_evt_type_t;
|
||||
|
||||
/** @brief SAADC driver done event data. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_saadc_value_t * p_buffer; ///< Pointer to the buffer with converted samples.
|
||||
uint16_t size; ///< Number of samples in the buffer.
|
||||
} nrfx_saadc_done_evt_t;
|
||||
|
||||
/** @brief SAADC driver limit event data. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t channel; ///< Channel on which the limit was detected.
|
||||
nrf_saadc_limit_t limit_type; ///< Type of limit detected.
|
||||
} nrfx_saadc_limit_evt_t;
|
||||
|
||||
/** @brief SAADC driver event structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_saadc_evt_type_t type; ///< Event type.
|
||||
union
|
||||
{
|
||||
nrfx_saadc_done_evt_t done; ///< Data for @ref NRFX_SAADC_EVT_DONE event.
|
||||
nrfx_saadc_limit_evt_t limit; ///< Data for @ref NRFX_SAADC_EVT_LIMIT event.
|
||||
} data; ///< Union to store event data.
|
||||
} nrfx_saadc_evt_t;
|
||||
|
||||
/**
|
||||
* @brief SAADC driver event handler.
|
||||
*
|
||||
* When operating in the advanced mode:
|
||||
* - when the sampling is performed by the external timer, the external timer can be safely started
|
||||
* on @ref NRFX_SAADC_EVT_READY and stopped on @ref NRFX_SAADC_EVT_FINISHED.
|
||||
* - call the @ref nrfx_saadc_buffer_set() on @ref NRFX_SAADC_EVT_BUF_REQ to achieve the continuous conversion.
|
||||
*
|
||||
* @param[in] p_event Pointer to an SAADC driver event. The event structure is allocated on
|
||||
* the stack, so it is valid only within the context of the event handler.
|
||||
*/
|
||||
typedef void (* nrfx_saadc_event_handler_t)(nrfx_saadc_evt_t const * p_event);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the SAADC driver.
|
||||
*
|
||||
* @param[in] interrupt_priority Interrupt priority.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_init(uint8_t interrupt_priority);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the SAADC driver.
|
||||
*
|
||||
* This function stops all ongoing conversions and disables all channels.
|
||||
*/
|
||||
void nrfx_saadc_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for configuring the SAADC channels.
|
||||
*
|
||||
* @note The values of the @ref nrf_saadc_channel_config_t.burst fields in channel configurations
|
||||
* are ignored. They will be overridden with the value suitable for the selected driver
|
||||
* operation mode.
|
||||
* @note The desired mode (simple or advanced) must be set after the channels are configured.
|
||||
*
|
||||
* @param[in] p_channels Pointer to the array of channel configuration structures.
|
||||
* @param[in] channel_count Number of channels to be configured.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Configuration was successful.
|
||||
* @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Attempt to configure the same channel more than once.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,
|
||||
uint32_t channel_count);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the SAADC driver in the simple mode.
|
||||
*
|
||||
* The simple mode allows obtaining a single sample from each requested channel.
|
||||
* The conversion can be done in a blocking or non-blocking manner.
|
||||
* Sampling is initiated by calling @ref nrfx_saadc_mode_trigger() once.
|
||||
*
|
||||
* @param[in] channel_mask Bitmask of channels to be used in the simple mode.
|
||||
* @param[in] resolution Resolution configuration.
|
||||
* @param[in] oversampling Oversampling configuration.
|
||||
* @param[in] event_handler Event handler provided by the user. In case of providing NULL,
|
||||
* the conversion will be performed in the blocking manner.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Attempt to activate channel that is not configured.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_simple_mode_set(uint32_t channel_mask,
|
||||
nrf_saadc_resolution_t resolution,
|
||||
nrf_saadc_oversample_t oversampling,
|
||||
nrfx_saadc_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the SAADC driver in the advanced mode.
|
||||
*
|
||||
* The advanced mode allows performing double-buffered conversions of arbitrary length.
|
||||
* The conversions can be done in a blocking or non-blocking manner. When performing conversions
|
||||
* in the non-blocking manner and @ref nrfx_saadc_adv_config_t.internal_timer_cc is set to 0,
|
||||
* sampling needs to be done by triggering @ref NRF_SAADC_TASK_SAMPLE externally
|
||||
* (for example by using the TIMER and/or the PPI/DPPI).
|
||||
* When performing conversions in the non-blocking manner and @ref nrfx_saadc_adv_config_t.start_on_end
|
||||
* is false, the @ref NRF_SAADC_TASK_START needs to be triggered on @ref NRF_SAADC_EVENT_END
|
||||
* externally (for example by using the PPI/DPPI).
|
||||
* Sampling is initiated by calling @ref nrfx_saadc_mode_trigger(). In case of performing
|
||||
* conversions in the blocking manner, @ref nrfx_saadc_mode_trigger() may need to be called several
|
||||
* times as each call sample each requested channel once.
|
||||
*
|
||||
* @note The internal timer can only be used when a single input channel is enabled.
|
||||
* @note The internal timer can only be used in the non-blocking mode.
|
||||
*
|
||||
* @param[in] channel_mask Bitmask of channels to be used in the advanced mode.
|
||||
* @param[in] resolution Resolution configuration.
|
||||
* @param[in] p_config Pointer to the structure with the advanced mode configuration.
|
||||
* @param[in] event_handler Event handler provided by the user. In case of providing NULL,
|
||||
* the conversion will be performed in the blocking manner.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Attempt to activate channel that is not configured.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED Attempt to activate internal timer or oversampling without burst
|
||||
* with multiple channels enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_advanced_mode_set(uint32_t channel_mask,
|
||||
nrf_saadc_resolution_t resolution,
|
||||
nrfx_saadc_adv_config_t const * p_config,
|
||||
nrfx_saadc_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for supplying the buffer to be used in the next part of
|
||||
* the conversion.
|
||||
*
|
||||
* @param[in] p_buffer Pointer to the buffer to be filled with conversion results.
|
||||
* @param[in] size Number of @ref nrf_saadc_value_t samples in buffer.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Buffer was supplied successfully.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffer is not in the Data RAM region.
|
||||
* @retval NRFX_ERROR_INVALID_LENGTH The provided buffer is not aligned to the number of activated channels
|
||||
* or is too long for the EasyDMA to handle.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is in the idle mode.
|
||||
* @retval NRFX_ERROR_ALREADY_INITIALIZED Both buffers for double-buffered conversions are already set.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief Function for triggering the conversion in the configured mode.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Operation finished successfully in the blocking manner or started
|
||||
* successfully in the non-blocking manner.
|
||||
* @retval NRFX_ERROR_BUSY The driver is performing the conversion in the advanced blocking mode.
|
||||
* Call the function again to continue the conversion.
|
||||
* @retval NRFX_ERROR_NO_MEM There is no buffer provided.
|
||||
* Supply the buffer using @ref nrfx_saadc_buffer_set() and try again.
|
||||
* @retval NRFX_ERROR_INVALID_STATE There is an ongoing conversion being performed in the non-blocking manner
|
||||
* or the driver is in the idle mode.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_mode_trigger(void);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting the ongoing and buffered conversions.
|
||||
*
|
||||
* @note @ref NRFX_SAADC_EVT_DONE event will be generated if there is a conversion in progress.
|
||||
* Event will contain number of words in the sample buffer.
|
||||
*/
|
||||
void nrfx_saadc_abort(void);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the SAADC channel limits.
|
||||
*
|
||||
* When limits are enabled and the conversion result exceeds the defined bounds,
|
||||
* the handler function is called with the corresponding event as parameter.
|
||||
*
|
||||
* @note Before the limits are set, the driver operation mode (simple or advanced) has
|
||||
* to be configured. Only non-blocking conversions can be monitored.
|
||||
*
|
||||
* @note Changing of the driver operation mode disables all configured limits.
|
||||
*
|
||||
* @param[in] channel Channel index.
|
||||
* @param[in] limit_low Limit low value to generate interrupt. Use @c INT16_MIN
|
||||
* to disable interrupt generation.
|
||||
* @param[in] limit_high Limit high value to generate interrupt. Use @c INT16_MAX
|
||||
* to disable interrupt generation.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Requested channel limits were set.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Attempt to activate the limits on disabled channel.
|
||||
* @retval NRFX_ERROR_FORBIDDEN Attempt to activate the limits for blocking conversions.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Attempt to activate the limits without configured mode.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the SAADC offset calibration.
|
||||
*
|
||||
* @note This function cancels the currently selected driver operation mode, if any.
|
||||
* The desired mode (simple or advanced) must be set after the calibration process completes.
|
||||
*
|
||||
* @param[in] event_handler Event handler provided by the user. In case of providing NULL,
|
||||
* the calibration will be performed in the blocking manner.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Calibration finished successfully in the blocking manner
|
||||
* or started successfully in the non-blocking manner.
|
||||
* @retval NRFX_ERROR_BUSY There is a conversion or calibration ongoing.
|
||||
*/
|
||||
nrfx_err_t nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t event_handler);
|
||||
|
||||
#endif // NRFX_SAADC_V2_H__
|
||||
|
||||
255
modules/nrfx/drivers/include/nrfx_spi.h
Normal file
255
modules/nrfx/drivers/include/nrfx_spi.h
Normal file
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_SPI_H__
|
||||
#define NRFX_SPI_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_spi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_spi SPI driver
|
||||
* @{
|
||||
* @ingroup nrf_spi
|
||||
* @brief Serial Peripheral Interface master (SPI) driver.
|
||||
*/
|
||||
|
||||
/** @brief Data structure of the Serial Peripheral Interface master (SPI) driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_SPI_Type * p_reg; ///< Pointer to a structure with SPI registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_spi_t;
|
||||
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_SPI0_ENABLED)
|
||||
NRFX_SPI0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPI1_ENABLED)
|
||||
NRFX_SPI1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPI2_ENABLED)
|
||||
NRFX_SPI2_INST_IDX,
|
||||
#endif
|
||||
NRFX_SPI_ENABLED_COUNT
|
||||
};
|
||||
|
||||
/** @brief Macro for creating an instance of the SPI master driver. */
|
||||
#define NRFX_SPI_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_SPI, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_SPI, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This value can be provided instead of a pin number for signals MOSI,
|
||||
* MISO, and Slave Select to specify that the given signal is not used and
|
||||
* therefore does not need to be connected to a pin.
|
||||
*/
|
||||
#define NRFX_SPI_PIN_NOT_USED 0xFF
|
||||
|
||||
/** @brief Configuration structure of the SPI master driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t sck_pin; ///< SCK pin number.
|
||||
uint8_t mosi_pin; ///< MOSI pin number (optional).
|
||||
/**< Set to @ref NRFX_SPI_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint8_t miso_pin; ///< MISO pin number (optional).
|
||||
/**< Set to @ref NRFX_SPI_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint8_t ss_pin; ///< Slave Select pin number (optional).
|
||||
/**< Set to @ref NRFX_SPI_PIN_NOT_USED
|
||||
* if this signal is not needed. The driver
|
||||
* supports only active low for this signal.
|
||||
* If the signal must be active high,
|
||||
* it must be controlled externally. */
|
||||
uint8_t irq_priority; ///< Interrupt priority.
|
||||
uint8_t orc; ///< Overrun character.
|
||||
/**< This character is used when all bytes from the TX buffer are sent,
|
||||
but the transfer continues due to RX. */
|
||||
nrf_spi_frequency_t frequency; ///< SPI frequency.
|
||||
nrf_spi_mode_t mode; ///< SPI mode.
|
||||
nrf_spi_bit_order_t bit_order; ///< SPI bit order.
|
||||
} nrfx_spi_config_t;
|
||||
|
||||
/** @brief SPI master instance default configuration. */
|
||||
#define NRFX_SPI_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.sck_pin = NRFX_SPI_PIN_NOT_USED, \
|
||||
.mosi_pin = NRFX_SPI_PIN_NOT_USED, \
|
||||
.miso_pin = NRFX_SPI_PIN_NOT_USED, \
|
||||
.ss_pin = NRFX_SPI_PIN_NOT_USED, \
|
||||
.irq_priority = NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
.orc = 0xFF, \
|
||||
.frequency = NRF_SPI_FREQ_4M, \
|
||||
.mode = NRF_SPI_MODE_0, \
|
||||
.bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST, \
|
||||
}
|
||||
|
||||
/** @brief Single transfer descriptor structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t const * p_tx_buffer; ///< Pointer to TX buffer.
|
||||
size_t tx_length; ///< TX buffer length.
|
||||
uint8_t * p_rx_buffer; ///< Pointer to RX buffer.
|
||||
size_t rx_length; ///< RX buffer length.
|
||||
}nrfx_spi_xfer_desc_t;
|
||||
|
||||
/**
|
||||
* @brief Macro for setting up single transfer descriptor.
|
||||
*
|
||||
* This macro is for internal use only.
|
||||
*/
|
||||
#define NRFX_SPI_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \
|
||||
{ \
|
||||
.p_tx_buffer = (uint8_t const *)(p_tx), \
|
||||
.tx_length = (tx_len), \
|
||||
.p_rx_buffer = (p_rx), \
|
||||
.rx_length = (rx_len), \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the duplex TX RX transfer. */
|
||||
#define NRFX_SPI_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \
|
||||
NRFX_SPI_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length)
|
||||
|
||||
/** @brief Macro for setting the TX transfer. */
|
||||
#define NRFX_SPI_XFER_TX(p_buf, length) \
|
||||
NRFX_SPI_SINGLE_XFER(p_buf, length, NULL, 0)
|
||||
|
||||
/** @brief Macro for setting the RX transfer. */
|
||||
#define NRFX_SPI_XFER_RX(p_buf, length) \
|
||||
NRFX_SPI_SINGLE_XFER(NULL, 0, p_buf, length)
|
||||
|
||||
/**
|
||||
* @brief SPI master driver event types, passed to the handler routine provided
|
||||
* during initialization.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_SPI_EVENT_DONE, ///< Transfer done.
|
||||
} nrfx_spi_evt_type_t;
|
||||
|
||||
/** @brief SPI master event description with transmission details. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_spi_evt_type_t type; ///< Event type.
|
||||
nrfx_spi_xfer_desc_t xfer_desc; ///< Transfer details.
|
||||
} nrfx_spi_evt_t;
|
||||
|
||||
/** @brief SPI master driver event handler type. */
|
||||
typedef void (* nrfx_spi_evt_handler_t)(nrfx_spi_evt_t const * p_event,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the SPI master driver instance.
|
||||
*
|
||||
* This function configures and enables the specified peripheral.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] handler Event handler provided by the user. If NULL, transfers
|
||||
* will be performed in blocking mode.
|
||||
* @param[in] p_context Context passed to the event handler.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_spi_init(nrfx_spi_t const * const p_instance,
|
||||
nrfx_spi_config_t const * p_config,
|
||||
nrfx_spi_evt_handler_t handler,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the SPI master driver instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_spi_uninit(nrfx_spi_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the SPI data transfer.
|
||||
*
|
||||
* If an event handler was provided in the @ref nrfx_spi_init call, this function
|
||||
* returns immediately and the handler is called when the transfer is done.
|
||||
* Otherwise, the transfer is performed in blocking mode, which means that this function
|
||||
* returns when the transfer is finished.
|
||||
*
|
||||
* @param p_instance Pointer to the driver instance structure.
|
||||
* @param p_xfer_desc Pointer to the transfer descriptor.
|
||||
* @param flags Transfer options (0 for default settings).
|
||||
* Currently, no additional flags are available.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
|
||||
*/
|
||||
nrfx_err_t nrfx_spi_xfer(nrfx_spi_t const * const p_instance,
|
||||
nrfx_spi_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting the ongoing transfer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_spi_abort(nrfx_spi_t const * p_instance);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_spi_0_irq_handler(void);
|
||||
void nrfx_spi_1_irq_handler(void);
|
||||
void nrfx_spi_2_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_SPI_H__
|
||||
385
modules/nrfx/drivers/include/nrfx_spim.h
Normal file
385
modules/nrfx/drivers/include/nrfx_spim.h
Normal file
@@ -0,0 +1,385 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_SPIM_H__
|
||||
#define NRFX_SPIM_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_spim.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_spim SPIM driver
|
||||
* @{
|
||||
* @ingroup nrf_spim
|
||||
* @brief Serial Peripheral Interface Master with EasyDMA (SPIM) driver.
|
||||
*/
|
||||
|
||||
/** @brief Data structure of the Serial Peripheral Interface Master with EasyDMA (SPIM) driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_SPIM_Type * p_reg; ///< Pointer to a structure with SPIM registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_spim_t;
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
|
||||
NRFX_SPIM0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
|
||||
NRFX_SPIM1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
|
||||
NRFX_SPIM2_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
|
||||
NRFX_SPIM3_INST_IDX,
|
||||
#endif
|
||||
NRFX_SPIM_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Macro for creating an instance of the SPIM driver. */
|
||||
#define NRFX_SPIM_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_SPIM, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIM, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This value can be provided instead of a pin number for signals MOSI,
|
||||
* MISO, and Slave Select to specify that the given signal is not used and
|
||||
* therefore does not need to be connected to a pin.
|
||||
*/
|
||||
#define NRFX_SPIM_PIN_NOT_USED 0xFF
|
||||
|
||||
/** @brief Configuration structure of the SPIM driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t sck_pin; ///< SCK pin number.
|
||||
uint8_t mosi_pin; ///< MOSI pin number (optional).
|
||||
/**< Set to @ref NRFX_SPIM_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint8_t miso_pin; ///< MISO pin number (optional).
|
||||
/**< Set to @ref NRFX_SPIM_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint8_t ss_pin; ///< Slave Select pin number (optional).
|
||||
/**< Set to @ref NRFX_SPIM_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
bool ss_active_high; ///< Polarity of the Slave Select pin during transmission.
|
||||
uint8_t irq_priority; ///< Interrupt priority.
|
||||
uint8_t orc; ///< Overrun character.
|
||||
/**< This character is used when all bytes from the TX buffer are sent,
|
||||
but the transfer continues due to RX. */
|
||||
nrf_spim_frequency_t frequency; ///< SPIM frequency.
|
||||
nrf_spim_mode_t mode; ///< SPIM mode.
|
||||
nrf_spim_bit_order_t bit_order; ///< SPIM bit order.
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
|
||||
uint8_t dcx_pin; ///< D/CX pin number (optional).
|
||||
uint8_t rx_delay; ///< Sample delay for input serial data on MISO.
|
||||
/**< The value specifies the delay, in number of 64 MHz clock cycles
|
||||
* (15.625 ns), from the the sampling edge of SCK (leading edge for
|
||||
* CONFIG.CPHA = 0, trailing edge for CONFIG.CPHA = 1) until
|
||||
* the input serial data is sampled. */
|
||||
bool use_hw_ss; ///< Indication to use software or hardware controlled Slave Select pin.
|
||||
uint8_t ss_duration; ///< Slave Select duration before and after transmission.
|
||||
/**< Minimum duration between the edge of CSN and the edge of SCK and minimum
|
||||
* duration of CSN must stay inactive between transactions.
|
||||
* The value is specified in number of 64 MHz clock cycles (15.625 ns).
|
||||
* Supported only for hardware-controlled Slave Select. */
|
||||
#endif
|
||||
} nrfx_spim_config_t;
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Extended default configuration of the SPIM instance.
|
||||
*/
|
||||
#define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \
|
||||
.dcx_pin = NRFX_SPIM_PIN_NOT_USED, \
|
||||
.rx_delay = 0x02, \
|
||||
.use_hw_ss = false, \
|
||||
.ss_duration = 0x02,
|
||||
#else
|
||||
#define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG
|
||||
#endif
|
||||
|
||||
/** @brief The default configuration of the SPIM master instance. */
|
||||
#define NRFX_SPIM_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.sck_pin = NRFX_SPIM_PIN_NOT_USED, \
|
||||
.mosi_pin = NRFX_SPIM_PIN_NOT_USED, \
|
||||
.miso_pin = NRFX_SPIM_PIN_NOT_USED, \
|
||||
.ss_pin = NRFX_SPIM_PIN_NOT_USED, \
|
||||
.ss_active_high = false, \
|
||||
.irq_priority = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
.orc = 0xFF, \
|
||||
.frequency = NRF_SPIM_FREQ_4M, \
|
||||
.mode = NRF_SPIM_MODE_0, \
|
||||
.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, \
|
||||
NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \
|
||||
}
|
||||
|
||||
/** @brief Flag indicating that TX buffer address will be incremented after transfer. */
|
||||
#define NRFX_SPIM_FLAG_TX_POSTINC (1UL << 0)
|
||||
/** @brief Flag indicating that RX buffer address will be incremented after transfer. */
|
||||
#define NRFX_SPIM_FLAG_RX_POSTINC (1UL << 1)
|
||||
/** @brief Flag indicating that the interrupt after each transfer will be suppressed, and the event handler will not be called. */
|
||||
#define NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER (1UL << 2)
|
||||
/** @brief Flag indicating that the transfer will be set up, but not started. */
|
||||
#define NRFX_SPIM_FLAG_HOLD_XFER (1UL << 3)
|
||||
/** @brief Flag indicating that the transfer will be executed multiple times. */
|
||||
#define NRFX_SPIM_FLAG_REPEATED_XFER (1UL << 4)
|
||||
|
||||
/** @brief Single transfer descriptor structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t const * p_tx_buffer; ///< Pointer to TX buffer.
|
||||
size_t tx_length; ///< TX buffer length.
|
||||
uint8_t * p_rx_buffer; ///< Pointer to RX buffer.
|
||||
size_t rx_length; ///< RX buffer length.
|
||||
} nrfx_spim_xfer_desc_t;
|
||||
|
||||
/**
|
||||
* @brief Macro for setting up single transfer descriptor.
|
||||
*
|
||||
* This macro is for internal use only.
|
||||
*/
|
||||
#define NRFX_SPIM_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \
|
||||
{ \
|
||||
.p_tx_buffer = (uint8_t const *)(p_tx), \
|
||||
.tx_length = (tx_len), \
|
||||
.p_rx_buffer = (p_rx), \
|
||||
.rx_length = (rx_len), \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the duplex TX RX transfer. */
|
||||
#define NRFX_SPIM_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \
|
||||
NRFX_SPIM_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length)
|
||||
|
||||
/** @brief Macro for setting the TX transfer. */
|
||||
#define NRFX_SPIM_XFER_TX(p_buf, length) \
|
||||
NRFX_SPIM_SINGLE_XFER(p_buf, length, NULL, 0)
|
||||
|
||||
/** @brief Macro for setting the RX transfer. */
|
||||
#define NRFX_SPIM_XFER_RX(p_buf, length) \
|
||||
NRFX_SPIM_SINGLE_XFER(NULL, 0, p_buf, length)
|
||||
|
||||
/**
|
||||
* @brief SPIM master driver event types, passed to the handler routine provided
|
||||
* during initialization.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_SPIM_EVENT_DONE, ///< Transfer done.
|
||||
} nrfx_spim_evt_type_t;
|
||||
|
||||
/** @brief SPIM event description with transmission details. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_spim_evt_type_t type; ///< Event type.
|
||||
nrfx_spim_xfer_desc_t xfer_desc; ///< Transfer details.
|
||||
} nrfx_spim_evt_t;
|
||||
|
||||
/** @brief SPIM driver event handler type. */
|
||||
typedef void (* nrfx_spim_evt_handler_t)(nrfx_spim_evt_t const * p_event,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the SPIM driver instance.
|
||||
*
|
||||
* This function configures and enables the specified peripheral.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] handler Event handler provided by the user. If NULL, transfers
|
||||
* will be performed in blocking mode.
|
||||
* @param[in] p_context Context passed to event handler.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED Requested configuration is not supported
|
||||
* by the SPIM instance.
|
||||
*/
|
||||
nrfx_err_t nrfx_spim_init(nrfx_spim_t const * const p_instance,
|
||||
nrfx_spim_config_t const * p_config,
|
||||
nrfx_spim_evt_handler_t handler,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the SPIM driver instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_spim_uninit(nrfx_spim_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the SPIM data transfer.
|
||||
*
|
||||
* Additional options are provided using the @c flags parameter:
|
||||
*
|
||||
* - @ref NRFX_SPIM_FLAG_TX_POSTINC and @ref NRFX_SPIM_FLAG_RX_POSTINC -
|
||||
* Post-incrementation of buffer addresses.
|
||||
* - @ref NRFX_SPIM_FLAG_HOLD_XFER - Driver is not starting the transfer. Use this
|
||||
* flag if the transfer is triggered externally by PPI. Use
|
||||
* @ref nrfx_spim_start_task_get to get the address of the start task.
|
||||
* - @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER - No user event handler after transfer
|
||||
* completion. This also means no interrupt at the end of the transfer.
|
||||
* If @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER is used, the driver does not set the instance into
|
||||
* busy state, so you must ensure that the next transfers are set up when SPIM is not active.
|
||||
* @ref nrfx_spim_end_event_get function can be used to detect end of transfer. Option can be used
|
||||
* together with @ref NRFX_SPIM_FLAG_REPEATED_XFER to prepare a sequence of SPI transfers
|
||||
* without interruptions.
|
||||
* - @ref NRFX_SPIM_FLAG_REPEATED_XFER - Prepare for repeated transfers. You can set
|
||||
* up a number of transfers that will be triggered externally (for example by PPI). An example is
|
||||
* a TXRX transfer with the options @ref NRFX_SPIM_FLAG_RX_POSTINC,
|
||||
* @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER, and @ref NRFX_SPIM_FLAG_REPEATED_XFER. After the
|
||||
* transfer is set up, a set of transfers can be triggered by PPI that will read, for example,
|
||||
* the same register of an external component and put it into a RAM buffer without any interrupts.
|
||||
* @ref nrfx_spim_end_event_get can be used to get the address of the END event, which can be
|
||||
* used to count the number of transfers. If @ref NRFX_SPIM_FLAG_REPEATED_XFER is used,
|
||||
* the driver does not set the instance into busy state, so you must ensure that the next
|
||||
* transfers are set up when SPIM is not active.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including SPIM) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param p_instance Pointer to the driver instance structure.
|
||||
* @param p_xfer_desc Pointer to the transfer descriptor.
|
||||
* @param flags Transfer options (0 for default settings).
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed in the Data
|
||||
* RAM region.
|
||||
*/
|
||||
nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * const p_instance,
|
||||
nrfx_spim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags);
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Function for starting the SPIM data transfer with DCX control.
|
||||
*
|
||||
* See @ref nrfx_spim_xfer for description of additional options of transfer
|
||||
* provided by the @c flags parameter.
|
||||
*
|
||||
* @note Peripherals that use EasyDMA (including SPIM) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param p_instance Pointer to the driver instance structure.
|
||||
* @param p_xfer_desc Pointer to the transfer descriptor.
|
||||
* @param flags Transfer options (0 for default settings).
|
||||
* @param cmd_length Length of the command bytes preceding the data
|
||||
* bytes. The DCX line will be low during transmission
|
||||
* of command bytes and high during transmission of data bytes.
|
||||
* Maximum value available for dividing the transmitted bytes
|
||||
* into command bytes and data bytes is @ref NRF_SPIM_DCX_CNT_ALL_CMD - 1.
|
||||
* The @ref NRF_SPIM_DCX_CNT_ALL_CMD value passed as the
|
||||
* @c cmd_length parameter causes all transmitted bytes
|
||||
* to be marked as command bytes.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed in the Data
|
||||
* RAM region.
|
||||
*/
|
||||
nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const * const p_instance,
|
||||
nrfx_spim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags,
|
||||
uint8_t cmd_length);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of a SPIM start task.
|
||||
*
|
||||
* This function is to be used if @ref nrfx_spim_xfer was called with the flag @ref NRFX_SPIM_FLAG_HOLD_XFER.
|
||||
* In that case, the transfer is not started by the driver, but it must be started externally by PPI.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Start task address.
|
||||
*/
|
||||
uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of a END SPIM event.
|
||||
*
|
||||
* The END event can be used to detect the end of a transfer
|
||||
* if the @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER option is used.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return END event address.
|
||||
*/
|
||||
uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting ongoing transfer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_spim_abort(nrfx_spim_t const * p_instance);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_spim_0_irq_handler(void);
|
||||
void nrfx_spim_1_irq_handler(void);
|
||||
void nrfx_spim_2_irq_handler(void);
|
||||
void nrfx_spim_3_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_SPIM_H__
|
||||
256
modules/nrfx/drivers/include/nrfx_spis.h
Normal file
256
modules/nrfx/drivers/include/nrfx_spis.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_SPIS_H__
|
||||
#define NRFX_SPIS_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_spis.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_spis SPIS driver
|
||||
* @{
|
||||
* @ingroup nrf_spis
|
||||
* @brief Serial Peripheral Interface Slave with EasyDMA (SPIS) driver.
|
||||
*/
|
||||
|
||||
/** @brief Data structure for the Serial Peripheral Interface Slave with EasyDMA (SPIS) driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_SPIS_Type * p_reg; //!< Pointer to a structure with SPIS registers.
|
||||
uint8_t drv_inst_idx; //!< Index of the driver instance. For internal use only.
|
||||
} nrfx_spis_t;
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_SPIS0_ENABLED)
|
||||
NRFX_SPIS0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIS1_ENABLED)
|
||||
NRFX_SPIS1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIS2_ENABLED)
|
||||
NRFX_SPIS2_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIS3_ENABLED)
|
||||
NRFX_SPIS3_INST_IDX,
|
||||
#endif
|
||||
NRFX_SPIS_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Macro for creating an instance of the SPI slave driver. */
|
||||
#define NRFX_SPIS_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_SPIS, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIS, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This value can be provided instead of a pin number for the signals MOSI
|
||||
* and MISO to specify that the given signal is not used and therefore
|
||||
* does not need to be connected to a pin.
|
||||
*/
|
||||
#define NRFX_SPIS_PIN_NOT_USED 0xFF
|
||||
|
||||
/** @brief Default pull-up configuration of the SPI CS. */
|
||||
#define NRFX_SPIS_DEFAULT_CSN_PULLUP NRF_GPIO_PIN_NOPULL
|
||||
/** @brief Default drive configuration of the SPI MISO. */
|
||||
#define NRFX_SPIS_DEFAULT_MISO_DRIVE NRF_GPIO_PIN_S0S1
|
||||
|
||||
/** @brief SPI slave driver event types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_SPIS_BUFFERS_SET_DONE, //!< Memory buffer set event. Memory buffers have been set successfully to the SPI slave device, and SPI transaction can be done.
|
||||
NRFX_SPIS_XFER_DONE, //!< SPI transaction event. SPI transaction has been completed.
|
||||
NRFX_SPIS_EVT_TYPE_MAX //!< Enumeration upper bound.
|
||||
} nrfx_spis_evt_type_t;
|
||||
|
||||
/** @brief SPI slave driver event structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_spis_evt_type_t evt_type; //!< Type of the event.
|
||||
size_t rx_amount; //!< Number of bytes received in the last transaction. This parameter is only valid for @ref NRFX_SPIS_XFER_DONE events.
|
||||
size_t tx_amount; //!< Number of bytes transmitted in the last transaction. This parameter is only valid for @ref NRFX_SPIS_XFER_DONE events.
|
||||
} nrfx_spis_evt_t;
|
||||
|
||||
/** @brief The default configuration of the SPI slave instance. */
|
||||
#define NRFX_SPIS_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.miso_pin = NRFX_SPIS_PIN_NOT_USED, \
|
||||
.mosi_pin = NRFX_SPIS_PIN_NOT_USED, \
|
||||
.sck_pin = NRFX_SPIS_PIN_NOT_USED, \
|
||||
.csn_pin = NRFX_SPIS_PIN_NOT_USED, \
|
||||
.mode = NRF_SPIS_MODE_0, \
|
||||
.bit_order = NRF_SPIS_BIT_ORDER_MSB_FIRST, \
|
||||
.csn_pullup = NRFX_SPIS_DEFAULT_CSN_PULLUP, \
|
||||
.miso_drive = NRFX_SPIS_DEFAULT_MISO_DRIVE, \
|
||||
.def = NRFX_SPIS_DEFAULT_DEF, \
|
||||
.orc = NRFX_SPIS_DEFAULT_ORC, \
|
||||
.irq_priority = NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/** @brief SPI peripheral device configuration data. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t miso_pin; //!< SPI MISO pin (optional).
|
||||
/**< Set @ref NRFX_SPIS_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint32_t mosi_pin; //!< SPI MOSI pin (optional).
|
||||
/**< Set @ref NRFX_SPIS_PIN_NOT_USED
|
||||
* if this signal is not needed. */
|
||||
uint32_t sck_pin; //!< SPI SCK pin.
|
||||
uint32_t csn_pin; //!< SPI CSN pin.
|
||||
nrf_spis_mode_t mode; //!< SPI mode.
|
||||
nrf_spis_bit_order_t bit_order; //!< SPI transaction bit order.
|
||||
nrf_gpio_pin_pull_t csn_pullup; //!< CSN pin pull-up configuration.
|
||||
nrf_gpio_pin_drive_t miso_drive; //!< MISO pin drive configuration.
|
||||
uint8_t def; //!< Character clocked out in case of an ignored transaction.
|
||||
uint8_t orc; //!< Character clocked out after an over-read of the transmit buffer.
|
||||
uint8_t irq_priority; //!< Interrupt priority.
|
||||
} nrfx_spis_config_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief SPI slave driver event handler type.
|
||||
*
|
||||
* @param[in] p_event Pointer to the event structure. The structure is
|
||||
* allocated on the stack so it is valid only until
|
||||
* the event handler returns.
|
||||
* @param[in] p_context Context set on initialization.
|
||||
*/
|
||||
typedef void (*nrfx_spis_event_handler_t)(nrfx_spis_evt_t const * p_event,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the SPI slave driver instance.
|
||||
*
|
||||
* @note When the nRF52 Anomaly 109 workaround for SPIS is enabled, this function
|
||||
* initializes the GPIOTE driver as well, and uses one of GPIOTE channels
|
||||
* to detect falling edges on CSN pin.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Function to be called by the SPI slave driver upon event.
|
||||
* Must not be NULL.
|
||||
* @param[in] p_context Context passed to the event handler.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The instance is already initialized.
|
||||
* @retval NRFX_ERROR_INVALID_PARAM Invalid parameter is supplied.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
* @retval NRFX_ERROR_INTERNAL GPIOTE channel for detecting falling edges
|
||||
* on CSN pin cannot be initialized. Possible
|
||||
* only when using nRF52 Anomaly 109 workaround.
|
||||
*/
|
||||
nrfx_err_t nrfx_spis_init(nrfx_spis_t const * const p_instance,
|
||||
nrfx_spis_config_t const * p_config,
|
||||
nrfx_spis_event_handler_t event_handler,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the SPI slave driver instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_spis_uninit(nrfx_spis_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for preparing the SPI slave instance for a single SPI transaction.
|
||||
*
|
||||
* This function prepares the SPI slave device to be ready for a single SPI transaction. It configures
|
||||
* the SPI slave device to use the memory supplied with the function call in SPI transactions.
|
||||
*
|
||||
* When either the memory buffer configuration or the SPI transaction has been
|
||||
* completed, the event callback function will be called with the appropriate event
|
||||
* @ref nrfx_spis_evt_type_t. The callback function can be called before returning from
|
||||
* this function, because it is called from the SPI slave interrupt context.
|
||||
*
|
||||
* @note This function can be called from the callback function context.
|
||||
*
|
||||
* @note Client applications must call this function after every @ref NRFX_SPIS_XFER_DONE event if
|
||||
* the SPI slave driver must be prepared for a possible new SPI transaction.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including SPIS) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_tx_buffer Pointer to the TX buffer. Can be NULL when the buffer length is zero.
|
||||
* @param[in] p_rx_buffer Pointer to the RX buffer. Can be NULL when the buffer length is zero.
|
||||
* @param[in] tx_buffer_length Length of the TX buffer in bytes.
|
||||
* @param[in] rx_buffer_length Length of the RX buffer in bytes.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The operation was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The operation failed because the SPI slave device is in an incorrect state.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed in the Data
|
||||
* RAM region.
|
||||
* @retval NRFX_ERROR_INVALID_LENGTH Provided lengths exceed the EasyDMA limits for the peripheral.
|
||||
* @retval NRFX_ERROR_INTERNAL The operation failed because of an internal error.
|
||||
*/
|
||||
nrfx_err_t nrfx_spis_buffers_set(nrfx_spis_t const * const p_instance,
|
||||
uint8_t const * p_tx_buffer,
|
||||
size_t tx_buffer_length,
|
||||
uint8_t * p_rx_buffer,
|
||||
size_t rx_buffer_length);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_spis_0_irq_handler(void);
|
||||
void nrfx_spis_1_irq_handler(void);
|
||||
void nrfx_spis_2_irq_handler(void);
|
||||
void nrfx_spis_3_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_SPIS_H__
|
||||
|
||||
245
modules/nrfx/drivers/include/nrfx_swi.h
Normal file
245
modules/nrfx/drivers/include/nrfx_swi.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_SWI_H__
|
||||
#define NRFX_SWI_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_EGU_ENABLED)
|
||||
#include <hal/nrf_egu.h>
|
||||
#endif
|
||||
|
||||
#ifndef SWI_COUNT
|
||||
#define SWI_COUNT EGU_COUNT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_swi SWI driver
|
||||
* @{
|
||||
* @ingroup nrf_swi_egu
|
||||
*
|
||||
* @brief Driver for managing software interrupts (SWI).
|
||||
*/
|
||||
|
||||
/** @brief SWI instance. */
|
||||
typedef uint8_t nrfx_swi_t;
|
||||
|
||||
/**
|
||||
* @brief SWI user flags.
|
||||
*
|
||||
* User flags are set during the SWI trigger and passed to the callback function as an argument.
|
||||
*/
|
||||
typedef uint16_t nrfx_swi_flags_t;
|
||||
|
||||
/** @brief Unallocated instance value. */
|
||||
#define NRFX_SWI_UNALLOCATED ((nrfx_swi_t)0xFFuL)
|
||||
|
||||
/** @brief Default SWI priority. */
|
||||
#define NRFX_SWI_DEFAULT_PRIORITY APP_IRQ_PRIORITY_LOWEST
|
||||
|
||||
/**
|
||||
* @brief SWI handler function.
|
||||
*
|
||||
* @param swi SWI instance.
|
||||
* @param flags User flags.
|
||||
*/
|
||||
typedef void (*nrfx_swi_handler_t)(nrfx_swi_t swi, nrfx_swi_flags_t flags);
|
||||
|
||||
/**
|
||||
* @brief Function for allocating the first unused SWI instance and setting a handler.
|
||||
*
|
||||
* If provided handler is not NULL, an allocated SWI has its interrupt enabled by default.
|
||||
* The interrupt can be disabled by @ref nrfx_swi_int_disable.
|
||||
*
|
||||
* @param[out] p_swi Points to a place where the allocated SWI instance
|
||||
* number is to be stored.
|
||||
* @param[in] event_handler Event handler function.
|
||||
* If NULL, no interrupt will be enabled.
|
||||
* It can be NULL only if the EGU driver is enabled.
|
||||
* For classic SWI, it must be a valid handler pointer.
|
||||
* @param[in] irq_priority Interrupt priority.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The SWI was successfully allocated.
|
||||
* @retval NRFX_ERROR_NO_MEM There is no available SWI to be used.
|
||||
*/
|
||||
nrfx_err_t nrfx_swi_alloc(nrfx_swi_t * p_swi,
|
||||
nrfx_swi_handler_t event_handler,
|
||||
uint32_t irq_priority);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling an allocated SWI interrupt.
|
||||
*
|
||||
* Use @ref nrfx_swi_int_enable to re-enable the interrupt.
|
||||
*
|
||||
* @param[in] swi SWI instance.
|
||||
*/
|
||||
void nrfx_swi_int_disable(nrfx_swi_t swi);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling an allocated SWI interrupt.
|
||||
*
|
||||
* @param[in] swi SWI instance.
|
||||
*/
|
||||
void nrfx_swi_int_enable(nrfx_swi_t swi);
|
||||
|
||||
/**
|
||||
* @brief Function for freeing a previously allocated SWI.
|
||||
*
|
||||
* @param[in,out] p_swi SWI instance to free. The value is changed to
|
||||
* @ref NRFX_SWI_UNALLOCATED on success.
|
||||
*/
|
||||
void nrfx_swi_free(nrfx_swi_t * p_swi);
|
||||
|
||||
/** @brief Function for freeing all allocated SWIs. */
|
||||
void nrfx_swi_all_free(void);
|
||||
|
||||
/**
|
||||
* @brief Function for triggering the SWI.
|
||||
*
|
||||
* @param[in] swi SWI to trigger.
|
||||
* @param[in] flag_number Number of user flag to trigger.
|
||||
*/
|
||||
void nrfx_swi_trigger(nrfx_swi_t swi,
|
||||
uint8_t flag_number);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the specified SWI is currently allocated.
|
||||
*
|
||||
* @param[in] swi SWI instance.
|
||||
*
|
||||
* @retval true The SWI instance is allocated.
|
||||
* @retval false The SWI instance is not allocated.
|
||||
*/
|
||||
bool nrfx_swi_is_allocated(nrfx_swi_t swi);
|
||||
|
||||
#if NRFX_CHECK(NRFX_EGU_ENABLED) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
/**
|
||||
* @brief Function for returning the base address of the EGU peripheral
|
||||
* associated with the specified SWI instance.
|
||||
*
|
||||
* @param[in] swi SWI instance.
|
||||
*
|
||||
* @return EGU base address or NULL if the specified SWI instance number
|
||||
* is too high.
|
||||
*/
|
||||
__STATIC_INLINE NRF_EGU_Type * nrfx_swi_egu_instance_get(nrfx_swi_t swi)
|
||||
{
|
||||
#if (EGU_COUNT < SWI_COUNT)
|
||||
if (swi >= EGU_COUNT)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
uint32_t offset = ((uint32_t)swi) * ((uint32_t)NRF_EGU1 - (uint32_t)NRF_EGU0);
|
||||
return (NRF_EGU_Type *)((uint32_t)NRF_EGU0 + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for returning the EGU trigger task address.
|
||||
*
|
||||
* @param[in] swi SWI instance.
|
||||
* @param[in] channel Number of the EGU channel.
|
||||
*
|
||||
* @return Address of the EGU trigger task.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_swi_task_trigger_address_get(nrfx_swi_t swi,
|
||||
uint8_t channel)
|
||||
{
|
||||
NRFX_ASSERT(nrfx_swi_is_allocated(swi));
|
||||
|
||||
NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
|
||||
#if (EGU_COUNT < SWI_COUNT)
|
||||
if (p_egu == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (uint32_t)nrf_egu_task_trigger_address_get(p_egu, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for returning the EGU-triggered event address.
|
||||
*
|
||||
* @param[in] swi SWI instance.
|
||||
* @param[in] channel Number of the EGU channel.
|
||||
*
|
||||
* @return Address of the EGU-triggered event.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_swi_event_triggered_address_get(nrfx_swi_t swi,
|
||||
uint8_t channel)
|
||||
{
|
||||
NRFX_ASSERT(nrfx_swi_is_allocated(swi));
|
||||
|
||||
NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
|
||||
#if (EGU_COUNT < SWI_COUNT)
|
||||
if (p_egu == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (uint32_t)nrf_egu_event_triggered_address_get(p_egu, channel);
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_EGU_ENABLED) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_swi_0_irq_handler(void);
|
||||
void nrfx_swi_1_irq_handler(void);
|
||||
void nrfx_swi_2_irq_handler(void);
|
||||
void nrfx_swi_3_irq_handler(void);
|
||||
void nrfx_swi_4_irq_handler(void);
|
||||
void nrfx_swi_5_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_SWI_H__
|
||||
135
modules/nrfx/drivers/include/nrfx_systick.h
Normal file
135
modules/nrfx/drivers/include/nrfx_systick.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 NRFX_SYSTICK_H__
|
||||
#define NRFX_SYSTICK_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_systick.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_systick ARM(R) SysTick driver
|
||||
* @{
|
||||
* @ingroup nrf_systick
|
||||
*
|
||||
* @brief ARM(R) SysTick driver.
|
||||
*
|
||||
* This driver configures ARM(R) SysTick as a free-running timer.
|
||||
* This timer is used to generate delays and pool for timeouts.
|
||||
* Only relatively short timeouts are supported.
|
||||
* The SysTick works on 64MHz and is 24-bit wide.
|
||||
* This means that it overflows around 4 times per second and
|
||||
* around 250 microseconds will be the highest supported time in the library.
|
||||
* As it is hard to detect if the overflow is generated without
|
||||
* using interrupts, the maximum delay range is halved for safety reasons.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The value type that holds the SysTick state.
|
||||
*
|
||||
* This variable is used to count the requested timeout.
|
||||
* @sa nrfx_systick_get
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t time; //!< Registered time value.
|
||||
} nrfx_systick_state_t;
|
||||
|
||||
/**
|
||||
* @brief Function for configuring and starting the timer.
|
||||
*
|
||||
* Function configures SysTick as a free-running timer without interrupt.
|
||||
*/
|
||||
void nrfx_systick_init(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the current SysTick state.
|
||||
*
|
||||
* Function gets the current state of the SysTick timer.
|
||||
* It can be used to check time-out by @ref nrfx_systick_test.
|
||||
*
|
||||
* @param[out] p_state The pointer to the state variable to be filled.
|
||||
*/
|
||||
void nrfx_systick_get(nrfx_systick_state_t * p_state);
|
||||
|
||||
/**
|
||||
* @brief Function for testing if the current time is higher in relation to the remembered state.
|
||||
*
|
||||
* @param[in] p_state Remembered state set by @ref nrfx_systick_get
|
||||
* @param[in] us Required time-out.
|
||||
*
|
||||
* @retval true The current time is higher than the specified state plus the given time-out.
|
||||
* @retval false The current time is lower than the specified state plus the given time-out.
|
||||
*/
|
||||
bool nrfx_systick_test(nrfx_systick_state_t const * p_state, uint32_t us);
|
||||
|
||||
/**
|
||||
* @brief Function for delaying the execution for the specified amount of CPU ticks.
|
||||
*
|
||||
* @param[in] ticks Number of CPU ticks when the execution is blocked.
|
||||
*/
|
||||
void nrfx_systick_delay_ticks(uint32_t ticks);
|
||||
|
||||
/**
|
||||
* @brief Function for delaying the execution for the specified amount of microseconds.
|
||||
*
|
||||
* @param[in] us Number of microseconds when the execution is blocked.
|
||||
*/
|
||||
void nrfx_systick_delay_us(uint32_t us);
|
||||
|
||||
/**
|
||||
* @brief Function for delaying the execution for the specified amount of milliseconds.
|
||||
*
|
||||
* This delay function removes the limits of the highest possible delay value.
|
||||
*
|
||||
* @param[in] ms Number of milliseconds when the execution is blocked.
|
||||
*/
|
||||
void nrfx_systick_delay_ms(uint32_t ms);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRFX_SYSTICK_H__ */
|
||||
162
modules/nrfx/drivers/include/nrfx_temp.h
Normal file
162
modules/nrfx/drivers/include/nrfx_temp.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 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 NRFX_TEMP_H__
|
||||
#define NRFX_TEMP_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_temp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_temp TEMP driver
|
||||
* @{
|
||||
* @ingroup nrf_temp
|
||||
* @brief Temperature sensor (TEMP) driver.
|
||||
*/
|
||||
|
||||
/** @brief Structure for TEMP configuration. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t interrupt_priority; /**< Interrupt priority. */
|
||||
} nrfx_temp_config_t;
|
||||
|
||||
/** @brief TEMP default configuration. */
|
||||
#define NRFX_TEMP_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.interrupt_priority = NRFX_TEMP_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TEMP driver data ready handler type.
|
||||
*
|
||||
* @param temperature Raw temperature in a 2's complement signed value
|
||||
* representation. This value can be converted to Celsius
|
||||
* scale using the @ref nrfx_temp_calculate() function.
|
||||
*/
|
||||
typedef void (* nrfx_temp_data_handler_t)(int32_t raw_temperature);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the TEMP driver.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with initial configuration.
|
||||
* @param[in] handler Data handler provided by the user. If not provided,
|
||||
* the driver is initialized in blocking mode.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Driver was successfully initialized.
|
||||
* @retval NRFX_ERROR_ALREADY_INITIALIZED Driver was already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_temp_init(nrfx_temp_config_t const * p_config, nrfx_temp_data_handler_t handler);
|
||||
|
||||
/** @brief Function for uninitializing the TEMP driver. */
|
||||
void nrfx_temp_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the temperature measurement in a 2's complement
|
||||
* signed value representation.
|
||||
*
|
||||
* This function returns the last value prepared by the TEMP peripheral.
|
||||
* In blocking mode, it should be used after calling the @ref nrfx_temp_measure()
|
||||
* function. In non-blocking mode, it is called internally by the driver,
|
||||
* and the value it returns is passed to the data handler.
|
||||
*
|
||||
* @return Temperature measurement result in a 2's complement signed value
|
||||
* representation.
|
||||
*/
|
||||
__STATIC_INLINE int32_t nrfx_temp_result_get(void);
|
||||
|
||||
/**
|
||||
* @brief Function for calculating the temperature value in Celsius scale from raw data.
|
||||
*
|
||||
* The returned temperature value is in Celsius scale, multiplied by 100
|
||||
* For example, the actual temperature of 25.75[C] will be returned as a 2575 signed integer.
|
||||
* Measurement accuracy is 0.25[C].
|
||||
*
|
||||
* @param[in] raw_measurement Temperature value in a 2's complement signed
|
||||
* value representation.
|
||||
*
|
||||
* @return Temperature measurement result.
|
||||
*/
|
||||
int32_t nrfx_temp_calculate(int32_t raw_measurement);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the temperature measurement.
|
||||
*
|
||||
* Non-blocking mode:
|
||||
* This function returns immediately. After a measurement, the handler specified
|
||||
* during initialization is called, with measurement result as the parameter.
|
||||
*
|
||||
* Blocking mode:
|
||||
* This function waits until the measurement is finished. The value should be read
|
||||
* using the @ref nrfx_temp_result_get() function.
|
||||
*
|
||||
* @retval NRFX_SUCCESS In non-blocking mode: Measurement was started.
|
||||
* An interrupt will be generated soon. <br>
|
||||
* In blocking mode:
|
||||
* Measurement was started and finished. Data can
|
||||
* be read using the @ref nrfx_temp_result_get() function.
|
||||
* @retval NRFX_ERROR_INTERNAL In non-blocking mode:
|
||||
* Not applicable. <br>
|
||||
* In blocking mode:
|
||||
* Measurement data ready event did not occur.
|
||||
*/
|
||||
nrfx_err_t nrfx_temp_measure(void);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE int32_t nrfx_temp_result_get(void)
|
||||
{
|
||||
return nrf_temp_result_get(NRF_TEMP);
|
||||
}
|
||||
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
void nrfx_temp_irq_handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_TEMP_H__
|
||||
409
modules/nrfx/drivers/include/nrfx_timer.h
Normal file
409
modules/nrfx/drivers/include/nrfx_timer.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_TIMER_H__
|
||||
#define NRFX_TIMER_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_timer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_timer Timer driver
|
||||
* @{
|
||||
* @ingroup nrf_timer
|
||||
* @brief TIMER peripheral driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Timer driver instance data structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NRF_TIMER_Type * p_reg; ///< Pointer to the structure with TIMER peripheral instance registers.
|
||||
uint8_t instance_id; ///< Index of the driver instance. For internal use only.
|
||||
uint8_t cc_channel_count; ///< Number of capture/compare channels.
|
||||
} nrfx_timer_t;
|
||||
|
||||
/** @brief Macro for creating a timer driver instance. */
|
||||
#define NRFX_TIMER_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_TIMER, id), \
|
||||
.instance_id = NRFX_CONCAT_3(NRFX_TIMER, id, _INST_IDX), \
|
||||
.cc_channel_count = NRF_TIMER_CC_CHANNEL_COUNT(id), \
|
||||
}
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_TIMER0_ENABLED)
|
||||
NRFX_TIMER0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER1_ENABLED)
|
||||
NRFX_TIMER1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER2_ENABLED)
|
||||
NRFX_TIMER2_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER3_ENABLED)
|
||||
NRFX_TIMER3_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER4_ENABLED)
|
||||
NRFX_TIMER4_INST_IDX,
|
||||
#endif
|
||||
NRFX_TIMER_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief The configuration structure of the timer driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_timer_frequency_t frequency; ///< Frequency.
|
||||
nrf_timer_mode_t mode; ///< Mode of operation.
|
||||
nrf_timer_bit_width_t bit_width; ///< Bit width.
|
||||
uint8_t interrupt_priority; ///< Interrupt priority.
|
||||
void * p_context; ///< Context passed to interrupt handler.
|
||||
} nrfx_timer_config_t;
|
||||
|
||||
/** @brief Timer driver instance default configuration. */
|
||||
#define NRFX_TIMER_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.frequency = (nrf_timer_frequency_t)NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY,\
|
||||
.mode = (nrf_timer_mode_t)NRFX_TIMER_DEFAULT_CONFIG_MODE, \
|
||||
.bit_width = (nrf_timer_bit_width_t)NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH,\
|
||||
.interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
.p_context = NULL \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Timer driver event handler type.
|
||||
*
|
||||
* @param[in] event_type Timer event.
|
||||
* @param[in] p_context General purpose parameter set during initialization of
|
||||
* the timer. This parameter can be used to pass
|
||||
* additional information to the handler function, for
|
||||
* example, the timer ID.
|
||||
*/
|
||||
typedef void (* nrfx_timer_event_handler_t)(nrf_timer_event_t event_type,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the timer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] timer_event_handler Event handler provided by the user.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The instance is already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_timer_init(nrfx_timer_t const * const p_instance,
|
||||
nrfx_timer_config_t const * p_config,
|
||||
nrfx_timer_event_handler_t timer_event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the timer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_timer_uninit(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for turning on the timer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_timer_enable(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for turning off the timer.
|
||||
*
|
||||
* The timer will allow to enter the lowest possible SYSTEM_ON state
|
||||
* only after this function is called.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_timer_disable(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for checking the timer state.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true Timer is enabled.
|
||||
* @retval false Timer is not enabled.
|
||||
*/
|
||||
bool nrfx_timer_is_enabled(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for pausing the timer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_timer_pause(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for resuming the timer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_timer_resume(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for clearing the timer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_timer_clear(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for incrementing the timer.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_timer_increment(nrfx_timer_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of the specified timer task.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] timer_task Timer task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_timer_task_address_get(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_task_t timer_task);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of the specified timer capture task.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] channel Capture channel number.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_timer_capture_task_address_get(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of the specified timer event.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] timer_event Timer event.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_timer_event_address_get(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_event_t timer_event);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of the specified timer compare event.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] channel Compare channel number.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_timer_compare_event_address_get(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for capturing the timer value.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] cc_channel Capture channel number.
|
||||
*
|
||||
* @return Captured value.
|
||||
*/
|
||||
uint32_t nrfx_timer_capture(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the capture value from the specified channel.
|
||||
*
|
||||
* Use this function to read channel values when PPI is used for capturing.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] cc_channel Capture channel number.
|
||||
*
|
||||
* @return Captured value.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_timer_capture_get(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the timer channel in compare mode.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] cc_channel Compare channel number.
|
||||
* @param[in] cc_value Compare value.
|
||||
* @param[in] enable_int Enable or disable the interrupt for the compare channel.
|
||||
*/
|
||||
void nrfx_timer_compare(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel,
|
||||
uint32_t cc_value,
|
||||
bool enable_int);
|
||||
|
||||
/**
|
||||
* @brief Function for setting the timer channel in the extended compare mode.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] cc_channel Compare channel number.
|
||||
* @param[in] cc_value Compare value.
|
||||
* @param[in] timer_short_mask Shortcut between the compare event on the channel
|
||||
* and the timer task (STOP or CLEAR).
|
||||
* @param[in] enable_int Enable or disable the interrupt for the compare channel.
|
||||
*/
|
||||
void nrfx_timer_extended_compare(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel,
|
||||
uint32_t cc_value,
|
||||
nrf_timer_short_mask_t timer_short_mask,
|
||||
bool enable_int);
|
||||
|
||||
/**
|
||||
* @brief Function for converting time in microseconds to timer ticks.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] time_us Time in microseconds.
|
||||
*
|
||||
* @return Number of ticks.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_timer_us_to_ticks(nrfx_timer_t const * const p_instance,
|
||||
uint32_t time_us);
|
||||
|
||||
/**
|
||||
* @brief Function for converting time in milliseconds to timer ticks.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] time_ms Time in milliseconds.
|
||||
*
|
||||
* @return Number of ticks.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_timer_ms_to_ticks(nrfx_timer_t const * const p_instance,
|
||||
uint32_t time_ms);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling timer compare interrupt.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] channel Compare channel.
|
||||
*/
|
||||
void nrfx_timer_compare_int_enable(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling timer compare interrupt.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] channel Compare channel.
|
||||
*/
|
||||
void nrfx_timer_compare_int_disable(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel);
|
||||
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_timer_task_address_get(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_task_t timer_task)
|
||||
{
|
||||
return (uint32_t)nrf_timer_task_address_get(p_instance->p_reg, timer_task);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_timer_capture_task_address_get(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel)
|
||||
{
|
||||
NRFX_ASSERT(channel < p_instance->cc_channel_count);
|
||||
return (uint32_t)nrf_timer_task_address_get(p_instance->p_reg,
|
||||
nrf_timer_capture_task_get(channel));
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_timer_event_address_get(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_event_t timer_event)
|
||||
{
|
||||
return (uint32_t)nrf_timer_event_address_get(p_instance->p_reg, timer_event);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_timer_compare_event_address_get(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel)
|
||||
{
|
||||
NRFX_ASSERT(channel < p_instance->cc_channel_count);
|
||||
return (uint32_t)nrf_timer_event_address_get(p_instance->p_reg,
|
||||
nrf_timer_compare_event_get(channel));
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_timer_capture_get(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel)
|
||||
{
|
||||
return nrf_timer_cc_read(p_instance->p_reg, cc_channel);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_timer_us_to_ticks(nrfx_timer_t const * const p_instance,
|
||||
uint32_t timer_us)
|
||||
{
|
||||
return nrf_timer_us_to_ticks(timer_us, nrf_timer_frequency_get(p_instance->p_reg));
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_timer_ms_to_ticks(nrfx_timer_t const * const p_instance,
|
||||
uint32_t timer_ms)
|
||||
{
|
||||
return nrf_timer_ms_to_ticks(timer_ms, nrf_timer_frequency_get(p_instance->p_reg));
|
||||
}
|
||||
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_timer_0_irq_handler(void);
|
||||
void nrfx_timer_1_irq_handler(void);
|
||||
void nrfx_timer_2_irq_handler(void);
|
||||
void nrfx_timer_3_irq_handler(void);
|
||||
void nrfx_timer_4_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_TIMER_H__
|
||||
|
||||
407
modules/nrfx/drivers/include/nrfx_twi.h
Normal file
407
modules/nrfx/drivers/include/nrfx_twi.h
Normal file
@@ -0,0 +1,407 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_TWI_H__
|
||||
#define NRFX_TWI_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <nrfx_twi_twim.h>
|
||||
#include <hal/nrf_twi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_twi TWI driver
|
||||
* @{
|
||||
* @ingroup nrf_twi
|
||||
* @brief Two Wire Interface master (TWI) peripheral driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Structure for the TWI master driver instance.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NRF_TWI_Type * p_twi; ///< Pointer to a structure with TWI registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_twi_t;
|
||||
|
||||
/** @brief Macro for creating a TWI master driver instance. */
|
||||
#define NRFX_TWI_INSTANCE(id) \
|
||||
{ \
|
||||
.p_twi = NRFX_CONCAT_2(NRF_TWI, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_TWI, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_TWI0_ENABLED)
|
||||
NRFX_TWI0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWI1_ENABLED)
|
||||
NRFX_TWI1_INST_IDX,
|
||||
#endif
|
||||
NRFX_TWI_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Structure for the configuration of the TWI master driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t scl; ///< SCL pin number.
|
||||
uint32_t sda; ///< SDA pin number.
|
||||
nrf_twi_frequency_t frequency; ///< TWI frequency.
|
||||
uint8_t interrupt_priority; ///< Interrupt priority.
|
||||
bool hold_bus_uninit; ///< Hold pull up state on GPIO pins after uninit.
|
||||
} nrfx_twi_config_t;
|
||||
|
||||
/** @brief The default configuration of the TWI master driver instance. */
|
||||
#define NRFX_TWI_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.frequency = (nrf_twi_frequency_t)NRFX_TWI_DEFAULT_CONFIG_FREQUENCY, \
|
||||
.scl = 31, \
|
||||
.sda = 31, \
|
||||
.interrupt_priority = NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
.hold_bus_uninit = NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT, \
|
||||
}
|
||||
|
||||
/** @brief Flag indicating that the interrupt after each transfer will be suppressed, and the event handler will not be called. */
|
||||
#define NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER (1UL << 2)
|
||||
/** @brief Flag indicating that the TX transfer will not end with a stop condition. */
|
||||
#define NRFX_TWI_FLAG_TX_NO_STOP (1UL << 5)
|
||||
/** @brief Flag indicating that the transfer will be suspended. */
|
||||
#define NRFX_TWI_FLAG_SUSPEND (1UL << 6)
|
||||
|
||||
/** @brief TWI master driver event types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_TWI_EVT_DONE, ///< Transfer completed event.
|
||||
NRFX_TWI_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address.
|
||||
NRFX_TWI_EVT_DATA_NACK, ///< Error event: NACK received after sending a data byte.
|
||||
NRFX_TWI_EVT_OVERRUN, ///< Error event: The unread data is replaced by new data.
|
||||
NRFX_TWI_EVT_BUS_ERROR ///< Error event: An unexpected transition occurred on the bus.
|
||||
} nrfx_twi_evt_type_t;
|
||||
|
||||
/** @brief TWI master driver transfer types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_TWI_XFER_TX, ///< TX transfer.
|
||||
NRFX_TWI_XFER_RX, ///< RX transfer.
|
||||
NRFX_TWI_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start.
|
||||
NRFX_TWI_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start.
|
||||
} nrfx_twi_xfer_type_t;
|
||||
|
||||
/** @brief Structure for a TWI transfer descriptor. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twi_xfer_type_t type; ///< Type of transfer.
|
||||
uint8_t address; ///< Slave address.
|
||||
size_t primary_length; ///< Number of bytes transferred.
|
||||
size_t secondary_length; ///< Number of bytes transferred.
|
||||
uint8_t * p_primary_buf; ///< Pointer to transferred data.
|
||||
uint8_t * p_secondary_buf; ///< Pointer to transferred data.
|
||||
} nrfx_twi_xfer_desc_t;
|
||||
|
||||
|
||||
/** @brief Macro for setting the TX transfer descriptor. */
|
||||
#define NRFX_TWI_XFER_DESC_TX(addr, p_data, length) \
|
||||
{ \
|
||||
.type = NRFX_TWI_XFER_TX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (length), \
|
||||
.secondary_length = 0, \
|
||||
.p_primary_buf = (p_data), \
|
||||
.p_secondary_buf = NULL, \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the RX transfer descriptor. */
|
||||
#define NRFX_TWI_XFER_DESC_RX(addr, p_data, length) \
|
||||
{ \
|
||||
.type = NRFX_TWI_XFER_RX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (length), \
|
||||
.secondary_length = 0, \
|
||||
.p_primary_buf = (p_data), \
|
||||
.p_secondary_buf = NULL, \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the TX-RX transfer descriptor. */
|
||||
#define NRFX_TWI_XFER_DESC_TXRX(addr, p_tx, tx_len, p_rx, rx_len) \
|
||||
{ \
|
||||
.type = NRFX_TWI_XFER_TXRX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (tx_len), \
|
||||
.secondary_length = (rx_len), \
|
||||
.p_primary_buf = (p_tx), \
|
||||
.p_secondary_buf = (p_rx), \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the TX-TX transfer descriptor. */
|
||||
#define NRFX_TWI_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \
|
||||
{ \
|
||||
.type = NRFX_TWI_XFER_TXTX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (tx_len), \
|
||||
.secondary_length = (tx_len2), \
|
||||
.p_primary_buf = (p_tx), \
|
||||
.p_secondary_buf = (p_tx2), \
|
||||
}
|
||||
|
||||
/** @brief Structure for a TWI event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twi_evt_type_t type; ///< Event type.
|
||||
nrfx_twi_xfer_desc_t xfer_desc; ///< Transfer details.
|
||||
} nrfx_twi_evt_t;
|
||||
|
||||
/** @brief TWI event handler prototype. */
|
||||
typedef void (* nrfx_twi_evt_handler_t)(nrfx_twi_evt_t const * p_event,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the TWI driver instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user. If NULL, blocking mode is enabled.
|
||||
* @param[in] p_context Context passed to event handler.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization is successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is in invalid state.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_twi_init(nrfx_twi_t const * p_instance,
|
||||
nrfx_twi_config_t const * p_config,
|
||||
nrfx_twi_evt_handler_t event_handler,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the TWI instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twi_uninit(nrfx_twi_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the TWI instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twi_enable(nrfx_twi_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the TWI instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twi_disable(nrfx_twi_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for sending data to a TWI slave.
|
||||
*
|
||||
* The transmission will be stopped when an error occurs. If a transfer is ongoing,
|
||||
* the function returns the error code @ref NRFX_ERROR_BUSY.
|
||||
*
|
||||
* @note This function is deprecated. Use @ref nrfx_twi_xfer instead.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] address Address of a specific slave device (only 7 LSB).
|
||||
* @param[in] p_data Pointer to a transmit buffer.
|
||||
* @param[in] length Number of bytes to send.
|
||||
* @param[in] no_stop If set, the stop condition is not generated on the bus
|
||||
* after the transfer has completed successfully (allowing
|
||||
* for a repeated start in the next transfer).
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_INTERNAL An error is detected by hardware.
|
||||
* @retval NRFX_ERROR_INVALID_STATE RX transaction is suspended on bus.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_ANACK Negative acknowledgement (NACK) is received after sending
|
||||
* the address in polling mode.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_DNACK Negative acknowledgement (NACK) is received after sending
|
||||
* a data byte in polling mode.
|
||||
*/
|
||||
nrfx_err_t nrfx_twi_tx(nrfx_twi_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t const * p_data,
|
||||
size_t length,
|
||||
bool no_stop);
|
||||
|
||||
/**
|
||||
* @brief Function for reading data from a TWI slave.
|
||||
*
|
||||
* The transmission will be stopped when an error occurs. If a transfer is ongoing,
|
||||
* the function returns the error code @ref NRFX_ERROR_BUSY.
|
||||
*
|
||||
* @note This function is deprecated. Use @ref nrfx_twi_xfer instead.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] address Address of a specific slave device (only 7 LSB).
|
||||
* @param[in] p_data Pointer to a receive buffer.
|
||||
* @param[in] length Number of bytes to be received.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_INTERNAL An error is detected by hardware.
|
||||
* @retval NRFX_ERROR_INVALID_STATE TX transaction is suspended on bus.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_OVERRUN The unread data is replaced by new data.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_ANACK Negative acknowledgement (NACK) is received after sending
|
||||
* the address in polling mode.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_DNACK Negative acknowledgement (NACK) is received after sending
|
||||
* a data byte in polling mode.
|
||||
*/
|
||||
nrfx_err_t nrfx_twi_rx(nrfx_twi_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t * p_data,
|
||||
size_t length);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for performing a TWI transfer.
|
||||
*
|
||||
* The following transfer types can be configured (@ref nrfx_twi_xfer_desc_t::type):
|
||||
* - @ref NRFX_TWI_XFER_TXRX - Write operation followed by a read operation (without STOP condition in between).
|
||||
* - @ref NRFX_TWI_XFER_TXTX - Write operation followed by a write operation (without STOP condition in between).
|
||||
* - @ref NRFX_TWI_XFER_TX - Write operation (with or without STOP condition).
|
||||
* - @ref NRFX_TWI_XFER_RX - Read operation (with STOP condition).
|
||||
*
|
||||
* @note TX-RX and TX-TX transfers are supported only in non-blocking mode.
|
||||
*
|
||||
* Additional options are provided using the flags parameter:
|
||||
* - @ref NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER - No user event handler after transfer completion. In most cases, this also means no interrupt at the end of the transfer.
|
||||
* - @ref NRFX_TWI_FLAG_TX_NO_STOP - No stop condition after TX transfer.
|
||||
* - @ref NRFX_TWI_FLAG_SUSPEND - Transfer will be suspended. This allows for combining multiple transfers into one transaction.
|
||||
* Only transactions with the same direction can be combined. To finish the transaction, call the function without this flag.
|
||||
*
|
||||
* @note
|
||||
* Some flag combinations are invalid:
|
||||
* - @ref NRFX_TWI_FLAG_TX_NO_STOP with @ref nrfx_twi_xfer_desc_t::type different than @ref NRFX_TWI_XFER_TX
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_xfer_desc Pointer to the transfer descriptor.
|
||||
* @param[in] flags Transfer options (0 for default settings).
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
|
||||
* @retval NRFX_ERROR_INTERNAL An unexpected transition occurred on the bus.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Other direction of transaction is suspended on the bus.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_OVERRUN The unread data is replaced by new data (TXRX and RX)
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_ANACK Negative acknowledgement (NACK) is received after sending
|
||||
* the address in polling mode.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_DNACK Negative acknowledgement (NACK) is received after sending
|
||||
* a data byte in polling mode.
|
||||
*/
|
||||
nrfx_err_t nrfx_twi_xfer(nrfx_twi_t const * p_instance,
|
||||
nrfx_twi_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief Function for checking the TWI driver state.
|
||||
*
|
||||
* @param[in] p_instance TWI instance.
|
||||
*
|
||||
* @retval true The TWI driver is currently busy performing a transfer.
|
||||
* @retval false The TWI driver is ready for a new transfer.
|
||||
*/
|
||||
bool nrfx_twi_is_busy(nrfx_twi_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the transferred data count.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Data count.
|
||||
*/
|
||||
size_t nrfx_twi_data_count_get(nrfx_twi_t const * const p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of a STOPPED TWI event.
|
||||
*
|
||||
* A STOPPED event can be used to detect the end of a transfer if the @ref NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER
|
||||
* option is used.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return STOPPED event address.
|
||||
*/
|
||||
uint32_t nrfx_twi_stopped_event_get(nrfx_twi_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for recovering the bus.
|
||||
*
|
||||
* This function checks if the bus is not stuck because of a slave holding the SDA line in the low state,
|
||||
* and if needed it performs required number of pulses on the SCL line to make the slave release the SDA line.
|
||||
* Finally, the function generates a STOP condition on the bus to put it into a known state.
|
||||
*
|
||||
* @note This function can be used only if the TWI driver is uninitialized.
|
||||
*
|
||||
* @param[in] scl_pin SCL pin number.
|
||||
* @param[in] sda_pin SDA pin number.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Bus recovery was successful.
|
||||
* @retval NRFX_ERROR_INTERNAL Bus recovery failed.
|
||||
*/
|
||||
__STATIC_INLINE nrfx_err_t nrfx_twi_bus_recover(uint32_t scl_pin, uint32_t sda_pin);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE nrfx_err_t nrfx_twi_bus_recover(uint32_t scl_pin, uint32_t sda_pin)
|
||||
{
|
||||
return nrfx_twi_twim_bus_recover(scl_pin, sda_pin);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_twi_0_irq_handler(void);
|
||||
void nrfx_twi_1_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_TWI_H__
|
||||
56
modules/nrfx/drivers/include/nrfx_twi_twim.h
Normal file
56
modules/nrfx/drivers/include/nrfx_twi_twim.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 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 NRFX_TWI_TWIM_H
|
||||
#define NRFX_TWI_TWIM_H
|
||||
|
||||
#include <nrfx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
nrfx_err_t nrfx_twi_twim_bus_recover(uint32_t scl_pin, uint32_t sda_pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_TWI_TWIM_H
|
||||
448
modules/nrfx/drivers/include/nrfx_twim.h
Normal file
448
modules/nrfx/drivers/include/nrfx_twim.h
Normal file
@@ -0,0 +1,448 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_TWIM_H__
|
||||
#define NRFX_TWIM_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <nrfx_twi_twim.h>
|
||||
#include <hal/nrf_twim.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_twim TWIM driver
|
||||
* @{
|
||||
* @ingroup nrf_twim
|
||||
* @brief Two Wire Interface Master with EasyDMA (TWIM) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Structure for the TWI master driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_TWIM_Type * p_twim; ///< Pointer to a structure with TWIM registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_twim_t;
|
||||
|
||||
/** @brief Macro for creating a TWI master driver instance. */
|
||||
#define NRFX_TWIM_INSTANCE(id) \
|
||||
{ \
|
||||
.p_twim = NRFX_CONCAT_2(NRF_TWIM, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_TWIM, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
|
||||
NRFX_TWIM0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
|
||||
NRFX_TWIM1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIM2_ENABLED)
|
||||
NRFX_TWIM2_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIM3_ENABLED)
|
||||
NRFX_TWIM3_INST_IDX,
|
||||
#endif
|
||||
NRFX_TWIM_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Structure for the TWI master driver instance configuration. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t scl; ///< SCL pin number.
|
||||
uint32_t sda; ///< SDA pin number.
|
||||
nrf_twim_frequency_t frequency; ///< TWIM frequency.
|
||||
uint8_t interrupt_priority; ///< Interrupt priority.
|
||||
bool hold_bus_uninit; ///< Hold pull up state on GPIO pins after uninit.
|
||||
} nrfx_twim_config_t;
|
||||
|
||||
/** @brief TWI master driver instance default configuration. */
|
||||
#define NRFX_TWIM_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.scl = 31, \
|
||||
.sda = 31, \
|
||||
.frequency = (nrf_twim_frequency_t)NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY, \
|
||||
.interrupt_priority = NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
.hold_bus_uninit = NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT, \
|
||||
}
|
||||
|
||||
/** @brief Flag indicating that TX buffer address will be incremented after the transfer. */
|
||||
#define NRFX_TWIM_FLAG_TX_POSTINC (1UL << 0)
|
||||
/** @brief Flag indicating that RX buffer address will be incremented after the transfer. */
|
||||
#define NRFX_TWIM_FLAG_RX_POSTINC (1UL << 1)
|
||||
/** @brief Flag indicating that the interrupt after each transfer will be suppressed, and the event handler will not be called. */
|
||||
#define NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER (1UL << 2)
|
||||
/** @brief Flag indicating that the transfer will be set up, but not started. */
|
||||
#define NRFX_TWIM_FLAG_HOLD_XFER (1UL << 3)
|
||||
/** @brief Flag indicating that the transfer will be executed multiple times. */
|
||||
#define NRFX_TWIM_FLAG_REPEATED_XFER (1UL << 4)
|
||||
/** @brief Flag indicating that the TX transfer will not end with a stop condition. */
|
||||
#define NRFX_TWIM_FLAG_TX_NO_STOP (1UL << 5)
|
||||
/** @brief Flag indicating that checks for spurious STOP condition will not be performed. */
|
||||
#define NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK (1UL << 6)
|
||||
|
||||
/** @brief TWI master driver event types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_TWIM_EVT_DONE, ///< Transfer completed event.
|
||||
NRFX_TWIM_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address.
|
||||
NRFX_TWIM_EVT_DATA_NACK, ///< Error event: NACK received after sending a data byte.
|
||||
NRFX_TWIM_EVT_OVERRUN, ///< Error event: The unread data is replaced by new data.
|
||||
NRFX_TWIM_EVT_BUS_ERROR ///< Error event: An unexpected transition occurred on the bus.
|
||||
} nrfx_twim_evt_type_t;
|
||||
|
||||
/** @brief TWI master driver transfer types. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_TWIM_XFER_TX, ///< TX transfer.
|
||||
NRFX_TWIM_XFER_RX, ///< RX transfer.
|
||||
NRFX_TWIM_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start.
|
||||
NRFX_TWIM_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start.
|
||||
} nrfx_twim_xfer_type_t;
|
||||
|
||||
/** @brief Structure for a TWI transfer descriptor. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twim_xfer_type_t type; ///< Type of transfer.
|
||||
uint8_t address; ///< Slave address.
|
||||
size_t primary_length; ///< Number of bytes transferred.
|
||||
size_t secondary_length; ///< Number of bytes transferred.
|
||||
uint8_t * p_primary_buf; ///< Pointer to transferred data.
|
||||
uint8_t * p_secondary_buf; ///< Pointer to transferred data.
|
||||
} nrfx_twim_xfer_desc_t;
|
||||
|
||||
|
||||
/** @brief Macro for setting the TX transfer descriptor. */
|
||||
#define NRFX_TWIM_XFER_DESC_TX(addr, p_data, length) \
|
||||
{ \
|
||||
.type = NRFX_TWIM_XFER_TX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (length), \
|
||||
.secondary_length = 0, \
|
||||
.p_primary_buf = (p_data), \
|
||||
.p_secondary_buf = NULL, \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the RX transfer descriptor. */
|
||||
#define NRFX_TWIM_XFER_DESC_RX(addr, p_data, length) \
|
||||
{ \
|
||||
.type = NRFX_TWIM_XFER_RX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (length), \
|
||||
.secondary_length = 0, \
|
||||
.p_primary_buf = (p_data), \
|
||||
.p_secondary_buf = NULL, \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the TX-RX transfer descriptor. */
|
||||
#define NRFX_TWIM_XFER_DESC_TXRX(addr, p_tx, tx_len, p_rx, rx_len) \
|
||||
{ \
|
||||
.type = NRFX_TWIM_XFER_TXRX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (tx_len), \
|
||||
.secondary_length = (rx_len), \
|
||||
.p_primary_buf = (p_tx), \
|
||||
.p_secondary_buf = (p_rx), \
|
||||
}
|
||||
|
||||
/** @brief Macro for setting the TX-TX transfer descriptor. */
|
||||
#define NRFX_TWIM_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \
|
||||
{ \
|
||||
.type = NRFX_TWIM_XFER_TXTX, \
|
||||
.address = (addr), \
|
||||
.primary_length = (tx_len), \
|
||||
.secondary_length = (tx_len2), \
|
||||
.p_primary_buf = (p_tx), \
|
||||
.p_secondary_buf = (p_tx2), \
|
||||
}
|
||||
|
||||
/** @brief Structure for a TWI event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twim_evt_type_t type; ///< Event type.
|
||||
nrfx_twim_xfer_desc_t xfer_desc; ///< Transfer details.
|
||||
} nrfx_twim_evt_t;
|
||||
|
||||
/** @brief TWI event handler prototype. */
|
||||
typedef void (* nrfx_twim_evt_handler_t)(nrfx_twim_evt_t const * p_event,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the TWI driver instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user. If NULL, blocking mode is enabled.
|
||||
* @param[in] p_context Context passed to event handler.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is in invalid state.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance,
|
||||
nrfx_twim_config_t const * p_config,
|
||||
nrfx_twim_evt_handler_t event_handler,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the TWI instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twim_uninit(nrfx_twim_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the TWI instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twim_enable(nrfx_twim_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the TWI instance.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twim_disable(nrfx_twim_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for sending data to a TWI slave.
|
||||
*
|
||||
* The transmission will be stopped when an error occurs. If a transfer is ongoing,
|
||||
* the function returns the error code @ref NRFX_ERROR_BUSY.
|
||||
*
|
||||
* @note This function is deprecated. Use @ref nrfx_twim_xfer instead.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including TWIM) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function fails with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] address Address of a specific slave device (only 7 LSB).
|
||||
* @param[in] p_data Pointer to a transmit buffer.
|
||||
* @param[in] length Number of bytes to send. Maximum possible length is
|
||||
* dependent on the used SoC (see the MAXCNT register
|
||||
* description in the Product Specification). The driver
|
||||
* checks it with assertion.
|
||||
* @param[in] no_stop If set, the stop condition is not generated on the bus
|
||||
* after the transfer has completed successfully (allowing
|
||||
* for a repeated start in the next transfer).
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_INTERNAL An unexpected transition occurred on the bus.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffer is not placed in the Data RAM region.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_ANACK NACK is received after sending the address in polling mode.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_DNACK NACK is received after sending a data byte in polling mode.
|
||||
*/
|
||||
nrfx_err_t nrfx_twim_tx(nrfx_twim_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t const * p_data,
|
||||
size_t length,
|
||||
bool no_stop);
|
||||
|
||||
/**
|
||||
* @brief Function for reading data from a TWI slave.
|
||||
*
|
||||
* The transmission will be stopped when an error occurs. If a transfer is ongoing,
|
||||
* the function returns the error code @ref NRFX_ERROR_BUSY.
|
||||
*
|
||||
* @note This function is deprecated. Use @ref nrfx_twim_xfer instead.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] address Address of a specific slave device (only 7 LSB).
|
||||
* @param[in] p_data Pointer to a receive buffer.
|
||||
* @param[in] length Number of bytes to be received. Maximum possible length
|
||||
* is dependent on the used SoC (see the MAXCNT register
|
||||
* description in the Product Specification). The driver
|
||||
* checks it with assertion.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_INTERNAL An unexpected transition occurred on the bus.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_OVERRUN The unread data is replaced by new data.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_ANACK NACK is received after sending the address in polling mode.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_DNACK NACK is received after sending a data byte in polling mode.
|
||||
*/
|
||||
nrfx_err_t nrfx_twim_rx(nrfx_twim_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t * p_data,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* @brief Function for performing a TWI transfer.
|
||||
*
|
||||
* The following transfer types can be configured (@ref nrfx_twim_xfer_desc_t::type):
|
||||
* - @ref NRFX_TWIM_XFER_TXRX - Write operation followed by a read operation (without STOP condition in between).
|
||||
* - @ref NRFX_TWIM_XFER_TXTX - Write operation followed by a write operation (without STOP condition in between).
|
||||
* - @ref NRFX_TWIM_XFER_TX - Write operation (with or without STOP condition).
|
||||
* - @ref NRFX_TWIM_XFER_RX - Read operation (with STOP condition).
|
||||
*
|
||||
* @note TX-RX and TX-TX transfers are supported only in non-blocking mode.
|
||||
*
|
||||
* Additional options are provided using the flags parameter:
|
||||
* - @ref NRFX_TWIM_FLAG_TX_POSTINC and @ref NRFX_TWIM_FLAG_RX_POSTINC - Post-incrementation of buffer addresses.
|
||||
* - @ref NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER - No user event handler after the transfer completion. In most cases, this also means no interrupt at the end of the transfer.
|
||||
* - @ref NRFX_TWIM_FLAG_HOLD_XFER - Driver is not starting the transfer. Use this flag if the transfer is triggered externally by PPI.
|
||||
* Use @ref nrfx_twim_start_task_get to get the address of the start task.
|
||||
* - @ref NRFX_TWIM_FLAG_REPEATED_XFER - Prepare for repeated transfers. You can set up a number of transfers that will be triggered externally (for example by PPI).
|
||||
* An example is a TXRX transfer with the options @ref NRFX_TWIM_FLAG_RX_POSTINC, @ref NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER, and @ref NRFX_TWIM_FLAG_REPEATED_XFER.
|
||||
* After the transfer is set up, a set of transfers can be triggered by PPI that will read, for example, the same register of an
|
||||
* external component and put it into a RAM buffer without any interrupts. @ref nrfx_twim_stopped_event_get can be used to get the
|
||||
* address of the STOPPED event, which can be used to count the number of transfers. If @ref NRFX_TWIM_FLAG_REPEATED_XFER is used,
|
||||
* the driver does not set the driver instance into busy state, so you must ensure that the next transfers are set up
|
||||
* when TWIM is not active.
|
||||
* - @ref NRFX_TWIM_FLAG_TX_NO_STOP - No stop condition after the TX transfer.
|
||||
* - @ref NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK - Checks for spurious STOP conditions are disabled.
|
||||
* Used together with @ref NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER can result in lower power consumption
|
||||
* when transfers are triggered externally and CPU is sleeping.
|
||||
* Use only with I2C standard-compliant slave devices.
|
||||
*
|
||||
* @note
|
||||
* Some flag combinations are invalid:
|
||||
* - @ref NRFX_TWIM_FLAG_TX_NO_STOP with @ref nrfx_twim_xfer_desc_t::type different than @ref NRFX_TWIM_XFER_TX
|
||||
* - @ref NRFX_TWIM_FLAG_REPEATED_XFER with @ref nrfx_twim_xfer_desc_t::type set to @ref NRFX_TWIM_XFER_TXTX
|
||||
*
|
||||
* If @ref nrfx_twim_xfer_desc_t::type is set to @ref NRFX_TWIM_XFER_TX and the @ref NRFX_TWIM_FLAG_TX_NO_STOP and @ref NRFX_TWIM_FLAG_REPEATED_XFER
|
||||
* flags are set, two tasks must be used to trigger a transfer: TASKS_RESUME followed by TASKS_STARTTX. If no stop condition is generated,
|
||||
* TWIM is in SUSPENDED state. Therefore, it must be resumed before the transfer can be started.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including TWIM) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_xfer_desc Pointer to the transfer descriptor.
|
||||
* @param[in] flags Transfer options (0 for default settings).
|
||||
*
|
||||
* @retval NRFX_SUCCESS The procedure is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
|
||||
* @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
|
||||
* @retval NRFX_ERROR_INTERNAL An unexpected transition occurred on the bus.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed in the Data RAM region.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_OVERRUN The unread data is replaced by new data.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_ANACK NACK is received after sending the address.
|
||||
* @retval NRFX_ERROR_DRV_TWI_ERR_DNACK NACK is received after sending a data byte.
|
||||
*/
|
||||
nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance,
|
||||
nrfx_twim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief Function for checking the TWI driver state.
|
||||
*
|
||||
* @param[in] p_instance TWI instance.
|
||||
*
|
||||
* @retval true The TWI driver is currently busy performing a transfer.
|
||||
* @retval false The TWI driver is ready for a new transfer.
|
||||
*/
|
||||
bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of a TWIM start task.
|
||||
*
|
||||
* This function is to be used if @ref nrfx_twim_xfer was called with the flag @ref NRFX_TWIM_FLAG_HOLD_XFER.
|
||||
* In that case, the transfer is not started by the driver, but it must be started externally by PPI.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] xfer_type Transfer type used in the last call of the @ref nrfx_twim_xfer function.
|
||||
*
|
||||
* @return Start task address (TX or RX) depending on the value of xfer_type.
|
||||
*/
|
||||
uint32_t nrfx_twim_start_task_get(nrfx_twim_t const * p_instance, nrfx_twim_xfer_type_t xfer_type);
|
||||
|
||||
/**
|
||||
* @brief Function for returning the address of a STOPPED TWIM event.
|
||||
*
|
||||
* A STOPPED event can be used to detect the end of a transfer if the @ref NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER
|
||||
* option is used.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return STOPPED event address.
|
||||
*/
|
||||
uint32_t nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for recovering the bus.
|
||||
*
|
||||
* This function checks if the bus is not stuck because of a slave holding the SDA line in the low state,
|
||||
* and if needed it performs required number of pulses on the SCL line to make the slave release the SDA line.
|
||||
* Finally, the function generates a STOP condition on the bus to put it into a known state.
|
||||
*
|
||||
* @note This function can be used only if the TWIM driver is uninitialized.
|
||||
*
|
||||
* @param[in] scl_pin SCL pin number.
|
||||
* @param[in] sda_pin SDA pin number.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Bus recovery was successful.
|
||||
* @retval NRFX_ERROR_INTERNAL Bus recovery failed.
|
||||
*/
|
||||
__STATIC_INLINE nrfx_err_t nrfx_twim_bus_recover(uint32_t scl_pin, uint32_t sda_pin);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE nrfx_err_t nrfx_twim_bus_recover(uint32_t scl_pin, uint32_t sda_pin)
|
||||
{
|
||||
return nrfx_twi_twim_bus_recover(scl_pin, sda_pin);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
void nrfx_twim_0_irq_handler(void);
|
||||
void nrfx_twim_1_irq_handler(void);
|
||||
void nrfx_twim_2_irq_handler(void);
|
||||
void nrfx_twim_3_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_TWIM_H__
|
||||
403
modules/nrfx/drivers/include/nrfx_twis.h
Normal file
403
modules/nrfx/drivers/include/nrfx_twis.h
Normal file
@@ -0,0 +1,403 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_TWIS_H__
|
||||
#define NRFX_TWIS_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_twis.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_twis TWIS driver
|
||||
* @{
|
||||
* @ingroup nrf_twis
|
||||
* @brief Two Wire Interface Slave with EasyDMA (TWIS) peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief TWIS driver instance data structure. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_TWIS_Type * p_reg; ///< Pointer to a structure with TWIS registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_twis_t;
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_TWIS0_ENABLED)
|
||||
NRFX_TWIS0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIS1_ENABLED)
|
||||
NRFX_TWIS1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIS2_ENABLED)
|
||||
NRFX_TWIS2_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIS3_ENABLED)
|
||||
NRFX_TWIS3_INST_IDX,
|
||||
#endif
|
||||
NRFX_TWIS_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Macro for creating a TWIS driver instance. */
|
||||
#define NRFX_TWIS_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_TWIS, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_TWIS, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
/** @brief Event callback function event definitions. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_TWIS_EVT_READ_REQ, ///< Read request detected.
|
||||
/**< If there is no buffer prepared, buf_req flag in the even will be set.
|
||||
Call then @ref nrfx_twis_tx_prepare to give parameters for buffer.
|
||||
*/
|
||||
NRFX_TWIS_EVT_READ_DONE, ///< Read request finished - free any data.
|
||||
NRFX_TWIS_EVT_READ_ERROR, ///< Read request finished with error.
|
||||
NRFX_TWIS_EVT_WRITE_REQ, ///< Write request detected.
|
||||
/**< If there is no buffer prepared, buf_req flag in the even will be set.
|
||||
Call then @ref nrfx_twis_rx_prepare to give parameters for buffer.
|
||||
*/
|
||||
NRFX_TWIS_EVT_WRITE_DONE, ///< Write request finished - process data.
|
||||
NRFX_TWIS_EVT_WRITE_ERROR, ///< Write request finished with error.
|
||||
NRFX_TWIS_EVT_GENERAL_ERROR ///< Error that happens not inside WRITE or READ transaction.
|
||||
} nrfx_twis_evt_type_t;
|
||||
|
||||
/**
|
||||
* @brief Possible error sources.
|
||||
*
|
||||
* This is flag enum - values from this enum can be connected using logical or operator.
|
||||
* @note
|
||||
* You can use directly @ref nrf_twis_error_t. Error type enum is redefined here because
|
||||
* of possible future extension (eg. supporting timeouts and synchronous mode).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_TWIS_ERROR_OVERFLOW = NRF_TWIS_ERROR_OVERFLOW, /**< RX buffer overflow detected, and prevented. */
|
||||
NRFX_TWIS_ERROR_DATA_NACK = NRF_TWIS_ERROR_DATA_NACK, /**< NACK sent after receiving a data byte. */
|
||||
NRFX_TWIS_ERROR_OVERREAD = NRF_TWIS_ERROR_OVERREAD, /**< TX buffer over-read detected, and prevented. */
|
||||
NRFX_TWIS_ERROR_UNEXPECTED_EVENT = 1 << 8 /**< Unexpected event detected by state machine. */
|
||||
} nrfx_twis_error_t;
|
||||
|
||||
/** @brief TWIS driver event structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twis_evt_type_t type; ///< Event type.
|
||||
union
|
||||
{
|
||||
bool buf_req; ///< Flag for @ref NRFX_TWIS_EVT_READ_REQ and @ref NRFX_TWIS_EVT_WRITE_REQ.
|
||||
/**< Information if transmission buffer requires to be prepared. */
|
||||
uint32_t tx_amount; ///< Data for @ref NRFX_TWIS_EVT_READ_DONE.
|
||||
uint32_t rx_amount; ///< Data for @ref NRFX_TWIS_EVT_WRITE_DONE.
|
||||
uint32_t error; ///< Data for @ref NRFX_TWIS_EVT_GENERAL_ERROR.
|
||||
} data; ///< Union to store event data.
|
||||
} nrfx_twis_evt_t;
|
||||
|
||||
/**
|
||||
* @brief TWI slave event callback function type.
|
||||
*
|
||||
* @param[in] p_event Event information structure.
|
||||
*/
|
||||
typedef void (*nrfx_twis_event_handler_t)(nrfx_twis_evt_t const * p_event);
|
||||
|
||||
/** @brief Structure for TWIS configuration. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t addr[2]; //!< Set addresses that this slave should respond. Set 0 to disable.
|
||||
uint32_t scl; //!< SCL pin number.
|
||||
uint32_t sda; //!< SDA pin number.
|
||||
nrf_gpio_pin_pull_t scl_pull; //!< SCL pin pull.
|
||||
nrf_gpio_pin_pull_t sda_pull; //!< SDA pin pull.
|
||||
uint8_t interrupt_priority; //!< The priority of interrupt for the module to be set.
|
||||
} nrfx_twis_config_t;
|
||||
|
||||
/** @brief Generate the default configuration for the TWIS driver instance. */
|
||||
#define NRFX_TWIS_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.addr = { NRFX_TWIS_DEFAULT_CONFIG_ADDR0, \
|
||||
NRFX_TWIS_DEFAULT_CONFIG_ADDR1 }, \
|
||||
.scl = 31, \
|
||||
.sda = 31, \
|
||||
.scl_pull = (nrf_gpio_pin_pull_t)NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL, \
|
||||
.sda_pull = (nrf_gpio_pin_pull_t)NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL, \
|
||||
.interrupt_priority = NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the TWIS driver instance.
|
||||
*
|
||||
* Function initializes and enables the TWIS driver.
|
||||
* @attention After driver initialization enable it with @ref nrfx_twis_enable.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @attention @em p_instance has to be global object.
|
||||
* It will be used by interrupts so make it sure that object
|
||||
* is not destroyed when function is leaving.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization is successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if NRFX_PRS_ENABLED
|
||||
* is set to a value other than zero.
|
||||
*/
|
||||
nrfx_err_t nrfx_twis_init(nrfx_twis_t const * p_instance,
|
||||
nrfx_twis_config_t const * p_config,
|
||||
nrfx_twis_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the TWIS driver instance.
|
||||
*
|
||||
* Function uninitializes the peripheral and resets all registers to default values.
|
||||
*
|
||||
* @note
|
||||
* It is safe to call nrfx_twis_uninit even before initialization.
|
||||
* Actually, @ref nrfx_twis_init function calls this function to
|
||||
* make sure that TWIS state is known.
|
||||
* @note
|
||||
* If TWIS driver was in uninitialized state before calling this function,
|
||||
* the selected pins would not be reset to default configuration.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twis_uninit(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the TWIS instance.
|
||||
*
|
||||
* This function enables the TWIS instance.
|
||||
* Function defined if there is need for dynamically enabling and disabling the peripheral.
|
||||
* Use @ref nrfx_twis_enable and @ref nrfx_twis_disable functions.
|
||||
* They do not change any configuration registers.
|
||||
*
|
||||
* @param p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twis_enable(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the TWIS instance.
|
||||
*
|
||||
* This function disables the TWIS instance, which gives possibility to turn off the TWIS while
|
||||
* holding configuration done by @ref nrfx_twis_init.
|
||||
*
|
||||
* @param p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_twis_disable(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for getting and clearing the last error flags.
|
||||
*
|
||||
* This function gets the information about errors.
|
||||
* This is also the only possibility to exit from the error substate of the internal state machine.
|
||||
* @attention
|
||||
* This function clears error state and flags.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Error flags defined in @ref nrfx_twis_error_t.
|
||||
*/
|
||||
uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for preparing the data for sending.
|
||||
*
|
||||
* This function is to be used in response to the @ref NRFX_TWIS_EVT_READ_REQ event.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
* @attention Transmission buffer must be placed in RAM.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_buf Transmission buffer.
|
||||
* @param[in] size Maximum number of bytes that master may read from buffer given.
|
||||
*
|
||||
* @retval NRFX_SUCCESS The preparation finished properly.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The given @em p_buf is not placed inside the RAM.
|
||||
* @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The module is not initialized or not enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
|
||||
void const * p_buf,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the number of transmitted bytes.
|
||||
*
|
||||
* This function returns the number of bytes sent.
|
||||
* This function can be called after @ref NRFX_TWIS_EVT_READ_DONE or @ref NRFX_TWIS_EVT_READ_ERROR events.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Number of bytes sent.
|
||||
*/
|
||||
__STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for preparing the data for receiving.
|
||||
*
|
||||
* This function must be used in response to the @ref NRFX_TWIS_EVT_WRITE_REQ event.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function fails with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_buf Buffer that is to be filled with received data.
|
||||
* @param[in] size Size of the buffer (maximum amount of data to receive).
|
||||
*
|
||||
* @retval NRFX_SUCCESS The preparation finished properly.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR The given @em p_buf is not placed inside the RAM.
|
||||
* @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The module is not initialized or not enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
|
||||
void * p_buf,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the number of received bytes.
|
||||
*
|
||||
* This function returns number of bytes received.
|
||||
* It can be called after @ref NRFX_TWIS_EVT_WRITE_DONE or @ref NRFX_TWIS_EVT_WRITE_ERROR events.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Number of bytes received.
|
||||
*/
|
||||
__STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the driver is busy right now.
|
||||
*
|
||||
* This function tests the actual driver substate.
|
||||
* If the driver is in any other state than IDLE or ERROR, this function returns true.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The driver is in state other than ERROR or IDLE.
|
||||
* @retval false There is no transmission pending.
|
||||
*/
|
||||
bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the driver is waiting for a TX buffer.
|
||||
*
|
||||
* If this function returns true, the driver is stalled expecting
|
||||
* of the @ref nrfx_twis_tx_prepare function call.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The driver is waiting for @ref nrfx_twis_tx_prepare.
|
||||
* @retval false The driver is not in the state where it is waiting for preparing a TX buffer.
|
||||
*/
|
||||
bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the driver is waiting for an RX buffer.
|
||||
*
|
||||
* If this function returns true, the driver is stalled expecting
|
||||
* of the @ref nrfx_twis_rx_prepare function call.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The driver is waiting for @ref nrfx_twis_rx_prepare.
|
||||
* @retval false The driver is not in the state where it is waiting for preparing an RX buffer.
|
||||
*/
|
||||
bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the driver is sending data.
|
||||
*
|
||||
* If this function returns true, there is an ongoing output transmission.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true There is an ongoing output transmission.
|
||||
* @retval false The driver is in other state.
|
||||
*/
|
||||
bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if the driver is receiving data.
|
||||
*
|
||||
* If this function returns true, there is an ongoing input transmission.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true There is an ongoing input transmission.
|
||||
* @retval false The driver is in other state.
|
||||
*/
|
||||
bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance);
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
return nrf_twis_tx_amount_get(p_instance->p_reg);
|
||||
}
|
||||
|
||||
__STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
return nrf_twis_rx_amount_get(p_instance->p_reg);
|
||||
}
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_twis_0_irq_handler(void);
|
||||
void nrfx_twis_1_irq_handler(void);
|
||||
void nrfx_twis_2_irq_handler(void);
|
||||
void nrfx_twis_3_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_TWIS_H__
|
||||
360
modules/nrfx/drivers/include/nrfx_uart.h
Normal file
360
modules/nrfx/drivers/include/nrfx_uart.h
Normal file
@@ -0,0 +1,360 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_UART_H__
|
||||
#define NRFX_UART_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_uart.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_uart UART driver
|
||||
* @{
|
||||
* @ingroup nrf_uart
|
||||
* @brief UART peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Data structure of the UART driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_UART_Type * p_reg; ///< Pointer to a structure with UART registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_uart_t;
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_UART0_ENABLED)
|
||||
NRFX_UART0_INST_IDX,
|
||||
#endif
|
||||
NRFX_UART_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Macro for creating a UART driver instance. */
|
||||
#define NRFX_UART_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_UART, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_UART, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
/** @brief Types of UART driver events. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_UART_EVT_TX_DONE, ///< Requested TX transfer completed.
|
||||
NRFX_UART_EVT_RX_DONE, ///< Requested RX transfer completed.
|
||||
NRFX_UART_EVT_ERROR, ///< Error reported by UART peripheral.
|
||||
} nrfx_uart_evt_type_t;
|
||||
|
||||
/** @brief Structure for the UART configuration. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t pseltxd; ///< TXD pin number.
|
||||
uint32_t pselrxd; ///< RXD pin number.
|
||||
uint32_t pselcts; ///< CTS pin number.
|
||||
uint32_t pselrts; ///< RTS pin number.
|
||||
void * p_context; ///< Context passed to interrupt handler.
|
||||
nrf_uart_hwfc_t hwfc; ///< Flow control configuration.
|
||||
nrf_uart_parity_t parity; ///< Parity configuration.
|
||||
nrf_uart_baudrate_t baudrate; ///< Baud rate.
|
||||
uint8_t interrupt_priority; ///< Interrupt priority.
|
||||
} nrfx_uart_config_t;
|
||||
|
||||
/** @brief UART default configuration. */
|
||||
#define NRFX_UART_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.pseltxd = NRF_UART_PSEL_DISCONNECTED, \
|
||||
.pselrxd = NRF_UART_PSEL_DISCONNECTED, \
|
||||
.pselcts = NRF_UART_PSEL_DISCONNECTED, \
|
||||
.pselrts = NRF_UART_PSEL_DISCONNECTED, \
|
||||
.p_context = NULL, \
|
||||
.hwfc = (nrf_uart_hwfc_t)NRFX_UART_DEFAULT_CONFIG_HWFC, \
|
||||
.parity = (nrf_uart_parity_t)NRFX_UART_DEFAULT_CONFIG_PARITY, \
|
||||
.baudrate = (nrf_uart_baudrate_t)NRFX_UART_DEFAULT_CONFIG_BAUDRATE, \
|
||||
.interrupt_priority = NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/** @brief Structure for the UART transfer completion event. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t * p_data; ///< Pointer to memory used for transfer.
|
||||
uint32_t bytes; ///< Number of bytes transfered.
|
||||
} nrfx_uart_xfer_evt_t;
|
||||
|
||||
/** @brief Structure for the UART error event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_uart_xfer_evt_t rxtx; ///< Transfer details, including number of bytes transferred.
|
||||
uint32_t error_mask; ///< Mask of error flags that generated the event.
|
||||
} nrfx_uart_error_evt_t;
|
||||
|
||||
/** @brief Structure for the UART event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_uart_evt_type_t type; ///< Event type.
|
||||
union
|
||||
{
|
||||
nrfx_uart_xfer_evt_t rxtx; ///< Data provided for transfer completion events.
|
||||
nrfx_uart_error_evt_t error; ///< Data provided for error event.
|
||||
} data; ///< Union to store event data.
|
||||
} nrfx_uart_event_t;
|
||||
|
||||
/**
|
||||
* @brief UART interrupt event handler.
|
||||
*
|
||||
* @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available
|
||||
* only within the context of the event handler.
|
||||
* @param[in] p_context Context passed to the interrupt handler, set on initialization.
|
||||
*/
|
||||
typedef void (*nrfx_uart_event_handler_t)(nrfx_uart_event_t const * p_event,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the UART driver.
|
||||
*
|
||||
* This function configures and enables UART. After this function GPIO pins are controlled by UART.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user. If not provided, the driver works in
|
||||
* blocking mode.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization is successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_uart_init(nrfx_uart_t const * p_instance,
|
||||
nrfx_uart_config_t const * p_config,
|
||||
nrfx_uart_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the UART driver.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uart_uninit(nrfx_uart_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the specified UART task.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] task Task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_uart_task_address_get(nrfx_uart_t const * p_instance,
|
||||
nrf_uart_task_t task);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the specified UART event.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] event Event.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_uart_event_address_get(nrfx_uart_t const * p_instance,
|
||||
nrf_uart_event_t event);
|
||||
|
||||
/**
|
||||
* @brief Function for sending data over UART.
|
||||
*
|
||||
* If an event handler was provided in nrfx_uart_init() call, this function
|
||||
* returns immediately and the handler is called when the transfer is done.
|
||||
* Otherwise, the transfer is performed in blocking mode, that is this function
|
||||
* returns when the transfer is finished. Blocking mode is not using interrupt
|
||||
* so there is no context switching inside the function.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_data Pointer to data.
|
||||
* @param[in] length Number of bytes to send.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_BUSY Driver is already transferring.
|
||||
* @retval NRFX_ERROR_FORBIDDEN The transfer was aborted from a different context
|
||||
* (blocking mode only).
|
||||
*/
|
||||
nrfx_err_t nrfx_uart_tx(nrfx_uart_t const * p_instance,
|
||||
uint8_t const * p_data,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if UART is currently transmitting.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The UART is transmitting.
|
||||
* @retval false The UART is not transmitting.
|
||||
*/
|
||||
bool nrfx_uart_tx_in_progress(nrfx_uart_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting any ongoing transmission.
|
||||
* @note @ref NRFX_UART_EVT_TX_DONE event will be generated in non-blocking mode.
|
||||
* It will contain number of bytes sent until the abort was called. The event
|
||||
* handler will be called from the function context.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uart_tx_abort(nrfx_uart_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for receiving data over UART.
|
||||
*
|
||||
* If an event handler is provided in the nrfx_uart_init() call, this function
|
||||
* returns immediately and the handler is called when the transfer is done.
|
||||
* Otherwise, the transfer is performed in blocking mode, that is this function
|
||||
* returns when the transfer is finished. Blocking mode is not using interrupt so
|
||||
* there is no context switching inside the function.
|
||||
* The receive buffer pointer is double-buffered in non-blocking mode. The secondary
|
||||
* buffer can be set immediately after starting the transfer and will be filled
|
||||
* when the primary buffer is full. The double-buffering feature allows
|
||||
* receiving data continuously.
|
||||
*
|
||||
* If this function is used without a previous call to @ref nrfx_uart_rx_enable, the reception
|
||||
* will be stopped on error or when the supplied buffer fills up. In both cases,
|
||||
* RX FIFO gets disabled. This means that, in case of error, the bytes that follow are lost.
|
||||
* If this nrfx_uart_rx() function is used with the previous call to @ref nrfx_uart_rx_enable,
|
||||
* the reception is stopped in case of error, but FIFO is still ongoing. The receiver is still
|
||||
* working, so after handling the error, an immediate repeated call to this nrfx_uart_rx()
|
||||
* function with fresh data buffer will re-establish reception. To disable the receiver,
|
||||
* you must call @ref nrfx_uart_rx_disable explicitly.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_data Pointer to data.
|
||||
* @param[in] length Number of bytes to receive.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Reception is complete (in case of blocking mode) or it is
|
||||
* successfully started (in case of non-blocking mode).
|
||||
* @retval NRFX_ERROR_BUSY The driver is already receiving
|
||||
* (and the secondary buffer has already been set
|
||||
* in non-blocking mode).
|
||||
* @retval NRFX_ERROR_FORBIDDEN The transfer was aborted from a different context
|
||||
* (blocking mode only, also see @ref nrfx_uart_rx_disable).
|
||||
* @retval NRFX_ERROR_INTERNAL The UART peripheral reported an error.
|
||||
*/
|
||||
nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance,
|
||||
uint8_t * p_data,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* @brief Function for testing the receiver state in blocking mode.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The receiver has at least one byte of data to get.
|
||||
* @retval false The receiver is empty.
|
||||
*/
|
||||
bool nrfx_uart_rx_ready(nrfx_uart_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling the receiver.
|
||||
*
|
||||
* UART has a 6-byte-long RX FIFO and it is used to store incoming data. If a user does not call the
|
||||
* UART receive function before the FIFO is filled, an overrun error will appear. The receiver must be
|
||||
* explicitly closed by the user @sa nrfx_uart_rx_disable.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uart_rx_enable(nrfx_uart_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling the receiver.
|
||||
*
|
||||
* This function must be called to close the receiver after it has been explicitly enabled by
|
||||
* @sa nrfx_uart_rx_enable.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uart_rx_disable(nrfx_uart_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting any ongoing reception.
|
||||
* @note @ref NRFX_UART_EVT_TX_DONE event will be generated in non-blocking mode.
|
||||
* It will contain number of bytes received until the abort was called. The event
|
||||
* handler will be called from the UART interrupt context.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uart_rx_abort(nrfx_uart_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for reading error source mask. Mask contains values from @ref nrf_uart_error_mask_t.
|
||||
* @note Function must be used in blocking mode only. In case of non-blocking mode, an error event is
|
||||
* generated. Function clears error sources after reading.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Mask of reported errors.
|
||||
*/
|
||||
uint32_t nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance);
|
||||
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE uint32_t nrfx_uart_task_address_get(nrfx_uart_t const * p_instance,
|
||||
nrf_uart_task_t task)
|
||||
{
|
||||
return nrf_uart_task_address_get(p_instance->p_reg, task);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_uart_event_address_get(nrfx_uart_t const * p_instance,
|
||||
nrf_uart_event_t event)
|
||||
{
|
||||
return nrf_uart_event_address_get(p_instance->p_reg, event);
|
||||
}
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_uart_0_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_UART_H__
|
||||
359
modules/nrfx/drivers/include/nrfx_uarte.h
Normal file
359
modules/nrfx/drivers/include/nrfx_uarte.h
Normal file
@@ -0,0 +1,359 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 NRFX_UARTE_H__
|
||||
#define NRFX_UARTE_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_uarte.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_uarte UARTE driver
|
||||
* @{
|
||||
* @ingroup nrf_uarte
|
||||
* @brief UARTE peripheral driver.
|
||||
*/
|
||||
|
||||
/** @brief Structure for the UARTE driver instance. */
|
||||
typedef struct
|
||||
{
|
||||
NRF_UARTE_Type * p_reg; ///< Pointer to a structure with UARTE registers.
|
||||
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
|
||||
} nrfx_uarte_t;
|
||||
|
||||
#ifndef __NRFX_DOXYGEN__
|
||||
enum {
|
||||
#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
|
||||
NRFX_UARTE0_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
|
||||
NRFX_UARTE1_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_UARTE2_ENABLED)
|
||||
NRFX_UARTE2_INST_IDX,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_UARTE3_ENABLED)
|
||||
NRFX_UARTE3_INST_IDX,
|
||||
#endif
|
||||
NRFX_UARTE_ENABLED_COUNT
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Macro for creating a UARTE driver instance. */
|
||||
#define NRFX_UARTE_INSTANCE(id) \
|
||||
{ \
|
||||
.p_reg = NRFX_CONCAT_2(NRF_UARTE, id), \
|
||||
.drv_inst_idx = NRFX_CONCAT_3(NRFX_UARTE, id, _INST_IDX), \
|
||||
}
|
||||
|
||||
/** @brief Types of UARTE driver events. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_UARTE_EVT_TX_DONE, ///< Requested TX transfer completed.
|
||||
NRFX_UARTE_EVT_RX_DONE, ///< Requested RX transfer completed.
|
||||
NRFX_UARTE_EVT_ERROR, ///< Error reported by UART peripheral.
|
||||
} nrfx_uarte_evt_type_t;
|
||||
|
||||
/** @brief Structure for the UARTE configuration. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t pseltxd; ///< TXD pin number.
|
||||
uint32_t pselrxd; ///< RXD pin number.
|
||||
uint32_t pselcts; ///< CTS pin number.
|
||||
uint32_t pselrts; ///< RTS pin number.
|
||||
void * p_context; ///< Context passed to interrupt handler.
|
||||
nrf_uarte_hwfc_t hwfc; ///< Flow control configuration.
|
||||
nrf_uarte_parity_t parity; ///< Parity configuration.
|
||||
nrf_uarte_baudrate_t baudrate; ///< Baud rate.
|
||||
uint8_t interrupt_priority; ///< Interrupt priority.
|
||||
} nrfx_uarte_config_t;
|
||||
|
||||
/** @brief UARTE default configuration. */
|
||||
#define NRFX_UARTE_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.pseltxd = NRF_UARTE_PSEL_DISCONNECTED, \
|
||||
.pselrxd = NRF_UARTE_PSEL_DISCONNECTED, \
|
||||
.pselcts = NRF_UARTE_PSEL_DISCONNECTED, \
|
||||
.pselrts = NRF_UARTE_PSEL_DISCONNECTED, \
|
||||
.p_context = NULL, \
|
||||
.hwfc = (nrf_uarte_hwfc_t)NRFX_UARTE_DEFAULT_CONFIG_HWFC, \
|
||||
.parity = (nrf_uarte_parity_t)NRFX_UARTE_DEFAULT_CONFIG_PARITY, \
|
||||
.baudrate = (nrf_uarte_baudrate_t)NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE, \
|
||||
.interrupt_priority = NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/** @brief Structure for the UARTE transfer completion event. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t * p_data; ///< Pointer to memory used for transfer.
|
||||
size_t bytes; ///< Number of bytes transfered.
|
||||
} nrfx_uarte_xfer_evt_t;
|
||||
|
||||
/** @brief Structure for UARTE error event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_uarte_xfer_evt_t rxtx; ///< Transfer details, including number of bytes transferred.
|
||||
uint32_t error_mask; ///< Mask of error flags that generated the event.
|
||||
} nrfx_uarte_error_evt_t;
|
||||
|
||||
/** @brief Structure for UARTE event. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_uarte_evt_type_t type; ///< Event type.
|
||||
union
|
||||
{
|
||||
nrfx_uarte_xfer_evt_t rxtx; ///< Data provided for transfer completion events.
|
||||
nrfx_uarte_error_evt_t error; ///< Data provided for error event.
|
||||
} data; ///< Union to store event data.
|
||||
} nrfx_uarte_event_t;
|
||||
|
||||
/**
|
||||
* @brief UARTE interrupt event handler.
|
||||
*
|
||||
* @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available
|
||||
* only within the context of the event handler.
|
||||
* @param[in] p_context Context passed to the interrupt handler, set on initialization.
|
||||
*/
|
||||
typedef void (*nrfx_uarte_event_handler_t)(nrfx_uarte_event_t const * p_event,
|
||||
void * p_context);
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the UARTE driver.
|
||||
*
|
||||
* This function configures and enables UARTE. After this function GPIO pins are controlled by UARTE.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] event_handler Event handler provided by the user. If not provided driver works in
|
||||
* blocking mode.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Driver is already initialized.
|
||||
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
|
||||
* instance ID is already in use. This is
|
||||
* possible only if @ref nrfx_prs module
|
||||
* is enabled.
|
||||
*/
|
||||
nrfx_err_t nrfx_uarte_init(nrfx_uarte_t const * p_instance,
|
||||
nrfx_uarte_config_t const * p_config,
|
||||
nrfx_uarte_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the UARTE driver.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uarte_uninit(nrfx_uarte_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the specified UARTE task.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] task Task.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_uarte_task_address_get(nrfx_uarte_t const * p_instance,
|
||||
nrf_uarte_task_t task);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of the specified UARTE event.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] event Event.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_uarte_event_address_get(nrfx_uarte_t const * p_instance,
|
||||
nrf_uarte_event_t event);
|
||||
|
||||
/**
|
||||
* @brief Function for sending data over UARTE.
|
||||
*
|
||||
* If an event handler is provided in nrfx_uarte_init() call, this function
|
||||
* returns immediately and the handler is called when the transfer is done.
|
||||
* Otherwise, the transfer is performed in blocking mode, that is this function
|
||||
* returns when the transfer is finished. Blocking mode is not using interrupt
|
||||
* so there is no context switching inside the function.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including UARTE) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_data Pointer to data.
|
||||
* @param[in] length Number of bytes to send. Maximum possible length is
|
||||
* dependent on the used SoC (see the MAXCNT register
|
||||
* description in the Product Specification). The driver
|
||||
* checks it with assertion.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization was successful.
|
||||
* @retval NRFX_ERROR_BUSY Driver is already transferring.
|
||||
* @retval NRFX_ERROR_FORBIDDEN The transfer was aborted from a different context
|
||||
* (blocking mode only).
|
||||
* @retval NRFX_ERROR_INVALID_ADDR p_data does not point to RAM buffer.
|
||||
*/
|
||||
nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance,
|
||||
uint8_t const * p_data,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if UARTE is currently transmitting.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The UARTE is transmitting.
|
||||
* @retval false The UARTE is not transmitting.
|
||||
*/
|
||||
bool nrfx_uarte_tx_in_progress(nrfx_uarte_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting any ongoing transmission.
|
||||
* @note @ref NRFX_UARTE_EVT_TX_DONE event will be generated in non-blocking mode.
|
||||
* It will contain number of bytes sent until the abort was called. The event
|
||||
* handler will be called from the UARTE interrupt context.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uarte_tx_abort(nrfx_uarte_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for receiving data over UARTE.
|
||||
*
|
||||
* If an event handler is provided in the nrfx_uarte_init() call, this function
|
||||
* returns immediately and the handler is called when the transfer is done.
|
||||
* Otherwise, the transfer is performed in blocking mode, that is this function
|
||||
* returns when the transfer is finished. Blocking mode is not using interrupt so
|
||||
* there is no context switching inside the function.
|
||||
* The receive buffer pointer is double-buffered in non-blocking mode. The secondary
|
||||
* buffer can be set immediately after starting the transfer and will be filled
|
||||
* when the primary buffer is full. The double-buffering feature allows
|
||||
* receiving data continuously.
|
||||
*
|
||||
* @note Peripherals using EasyDMA (including UARTE) require the transfer buffers
|
||||
* to be placed in the Data RAM region. If this condition is not met,
|
||||
* this function fails with the error code NRFX_ERROR_INVALID_ADDR.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
* @param[in] p_data Pointer to data.
|
||||
* @param[in] length Number of bytes to receive. Maximum possible length is
|
||||
* dependent on the used SoC (see the MAXCNT register
|
||||
* description in the Product Specification). The driver
|
||||
* checks it with assertion.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization is successful.
|
||||
* @retval NRFX_ERROR_BUSY The driver is already receiving
|
||||
* (and the secondary buffer has already been set
|
||||
* in non-blocking mode).
|
||||
* @retval NRFX_ERROR_FORBIDDEN The transfer is aborted from a different context
|
||||
* (blocking mode only).
|
||||
* @retval NRFX_ERROR_INTERNAL The UARTE peripheral reports an error.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR p_data does not point to RAM buffer.
|
||||
*/
|
||||
nrfx_err_t nrfx_uarte_rx(nrfx_uarte_t const * p_instance,
|
||||
uint8_t * p_data,
|
||||
size_t length);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for testing the receiver state in blocking mode.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @retval true The receiver has at least one byte of data to get.
|
||||
* @retval false The receiver is empty.
|
||||
*/
|
||||
bool nrfx_uarte_rx_ready(nrfx_uarte_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for aborting any ongoing reception.
|
||||
* @note @ref NRFX_UARTE_EVT_RX_DONE event will be generated in non-blocking mode.
|
||||
* It will contain number of bytes received until the abort was called. The event
|
||||
* handler will be called from the UARTE interrupt context.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*/
|
||||
void nrfx_uarte_rx_abort(nrfx_uarte_t const * p_instance);
|
||||
|
||||
/**
|
||||
* @brief Function for reading error source mask. Mask contains values from @ref nrf_uarte_error_mask_t.
|
||||
* @note Function must be used in the blocking mode only. In case of non-blocking mode, an error event is
|
||||
* generated. Function clears error sources after reading.
|
||||
*
|
||||
* @param[in] p_instance Pointer to the driver instance structure.
|
||||
*
|
||||
* @return Mask of reported errors.
|
||||
*/
|
||||
uint32_t nrfx_uarte_errorsrc_get(nrfx_uarte_t const * p_instance);
|
||||
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
__STATIC_INLINE uint32_t nrfx_uarte_task_address_get(nrfx_uarte_t const * p_instance,
|
||||
nrf_uarte_task_t task)
|
||||
{
|
||||
return nrf_uarte_task_address_get(p_instance->p_reg, task);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_uarte_event_address_get(nrfx_uarte_t const * p_instance,
|
||||
nrf_uarte_event_t event)
|
||||
{
|
||||
return nrf_uarte_event_address_get(p_instance->p_reg, event);
|
||||
}
|
||||
#endif // SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_uarte_0_irq_handler(void);
|
||||
void nrfx_uarte_1_irq_handler(void);
|
||||
void nrfx_uarte_2_irq_handler(void);
|
||||
void nrfx_uarte_3_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_UARTE_H__
|
||||
872
modules/nrfx/drivers/include/nrfx_usbd.h
Normal file
872
modules/nrfx/drivers/include/nrfx_usbd.h
Normal file
@@ -0,0 +1,872 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 NRFX_USBD_H__
|
||||
#define NRFX_USBD_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_usbd.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_usbd USBD driver
|
||||
* @{
|
||||
* @ingroup nrf_usbd
|
||||
* @brief Universal Serial Bus Device (USBD) peripheral driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Number of bytes in the endpoint.
|
||||
*/
|
||||
#define NRFX_USBD_EPSIZE 64
|
||||
|
||||
/**
|
||||
* @brief Number of bytes for isochronous endpoints.
|
||||
*
|
||||
* Number of bytes for isochronous endpoints in total.
|
||||
* This number would be shared between IN and OUT endpoint.
|
||||
* It may be also assigned totaly to one endpoint.
|
||||
* @sa nrf_usbd_isosplit_set
|
||||
* @sa nrf_usbd_isosplit_get
|
||||
*/
|
||||
#define NRFX_USBD_ISOSIZE 1024
|
||||
|
||||
/**
|
||||
* @brief The size of internal feeder buffer.
|
||||
*
|
||||
* @sa nrfx_usbd_feeder_buffer_get
|
||||
*/
|
||||
#define NRFX_USBD_FEEDER_BUFFER_SIZE NRFX_USBD_EPSIZE
|
||||
|
||||
/**
|
||||
* @name Macros for creating endpoint identifiers.
|
||||
*
|
||||
* Auxiliary macros for creating endpoint identifiers compatible with the USB specification.
|
||||
* @{
|
||||
* @brief Create identifier for IN endpoint.
|
||||
*
|
||||
* Simple macro to create IN endpoint identifier for given endpoint number.
|
||||
*
|
||||
* @param[in] n Endpoint number.
|
||||
*
|
||||
* @return Endpoint identifier that connects endpoint number and endpoint direction.
|
||||
*/
|
||||
#define NRFX_USBD_EPIN(n) ((nrfx_usbd_ep_t)NRF_USBD_EPIN(n))
|
||||
/**
|
||||
* @brief Create identifier for OUT endpoint.
|
||||
*
|
||||
* Simple macro to create OUT endpoint identifier for given endpoint number.
|
||||
*
|
||||
* @param[in] n Endpoint number.
|
||||
*
|
||||
* @return Endpoint identifier that connects endpoint number and endpoint direction.
|
||||
*/
|
||||
#define NRFX_USBD_EPOUT(n) ((nrfx_usbd_ep_t)NRF_USBD_EPOUT(n))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Endpoint identifier.
|
||||
*
|
||||
* Endpoint identifier used in the driver.
|
||||
* This endpoint number is consistent with USB 2.0 specification.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_USBD_EPOUT0 = NRF_USBD_EPOUT(0), /**< Endpoint OUT 0 */
|
||||
NRFX_USBD_EPOUT1 = NRF_USBD_EPOUT(1), /**< Endpoint OUT 1 */
|
||||
NRFX_USBD_EPOUT2 = NRF_USBD_EPOUT(2), /**< Endpoint OUT 2 */
|
||||
NRFX_USBD_EPOUT3 = NRF_USBD_EPOUT(3), /**< Endpoint OUT 3 */
|
||||
NRFX_USBD_EPOUT4 = NRF_USBD_EPOUT(4), /**< Endpoint OUT 4 */
|
||||
NRFX_USBD_EPOUT5 = NRF_USBD_EPOUT(5), /**< Endpoint OUT 5 */
|
||||
NRFX_USBD_EPOUT6 = NRF_USBD_EPOUT(6), /**< Endpoint OUT 6 */
|
||||
NRFX_USBD_EPOUT7 = NRF_USBD_EPOUT(7), /**< Endpoint OUT 7 */
|
||||
NRFX_USBD_EPOUT8 = NRF_USBD_EPOUT(8), /**< Endpoint OUT 8 */
|
||||
|
||||
NRFX_USBD_EPIN0 = NRF_USBD_EPIN(0), /**< Endpoint IN 0 */
|
||||
NRFX_USBD_EPIN1 = NRF_USBD_EPIN(1), /**< Endpoint IN 1 */
|
||||
NRFX_USBD_EPIN2 = NRF_USBD_EPIN(2), /**< Endpoint IN 2 */
|
||||
NRFX_USBD_EPIN3 = NRF_USBD_EPIN(3), /**< Endpoint IN 3 */
|
||||
NRFX_USBD_EPIN4 = NRF_USBD_EPIN(4), /**< Endpoint IN 4 */
|
||||
NRFX_USBD_EPIN5 = NRF_USBD_EPIN(5), /**< Endpoint IN 5 */
|
||||
NRFX_USBD_EPIN6 = NRF_USBD_EPIN(6), /**< Endpoint IN 6 */
|
||||
NRFX_USBD_EPIN7 = NRF_USBD_EPIN(7), /**< Endpoint IN 7 */
|
||||
NRFX_USBD_EPIN8 = NRF_USBD_EPIN(8), /**< Endpoint IN 8 */
|
||||
} nrfx_usbd_ep_t;
|
||||
|
||||
/**
|
||||
* @brief Events generated by the driver.
|
||||
*
|
||||
* Enumeration of possible events that may be generated by the driver.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_USBD_EVT_SOF, /**< Start Of Frame event on USB bus detected. */
|
||||
NRFX_USBD_EVT_RESET, /**< Reset condition on USB bus detected. */
|
||||
NRFX_USBD_EVT_SUSPEND, /**< This device should go to suspend mode now. */
|
||||
NRFX_USBD_EVT_RESUME, /**< This device should resume from suspend now. */
|
||||
NRFX_USBD_EVT_WUREQ, /**< Wakeup request - the USBD peripheral is ready to generate
|
||||
WAKEUP signal after exiting low power mode. */
|
||||
NRFX_USBD_EVT_SETUP, /**< Setup frame received and decoded. */
|
||||
NRFX_USBD_EVT_EPTRANSFER, /**< For Rx (OUT: Host->Device):
|
||||
* 1. The packet has been received but there is no buffer prepared for transfer already.
|
||||
* 2. Whole transfer has been finished.
|
||||
*
|
||||
* For Tx (IN: Device->Host):
|
||||
* The last packet from requested transfer has been transfered over USB bus and acknowledged.
|
||||
*/
|
||||
NRFX_USBD_EVT_CNT /**< Number of defined events. */
|
||||
} nrfx_usbd_event_type_t;
|
||||
|
||||
/**
|
||||
* @brief Endpoint status codes.
|
||||
*
|
||||
* Status codes that may be returned by @ref nrfx_usbd_ep_status_get or, except for
|
||||
* @ref NRFX_USBD_EP_BUSY, reported together with @ref NRFX_USBD_EVT_EPTRANSFER.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_USBD_EP_OK, /**< No error occured. */
|
||||
NRFX_USBD_EP_WAITING, /**< Data received, no buffer prepared already - waiting for configured transfer. */
|
||||
NRFX_USBD_EP_OVERLOAD, /**< Received number of bytes cannot fit given buffer.
|
||||
* This error would also be returned when next_transfer function has been defined
|
||||
* but currently received data cannot fit completely in current buffer.
|
||||
* No data split from single endpoint transmission is supported.
|
||||
*
|
||||
* When this error is reported - data is left inside endpoint buffer.
|
||||
* Clear endpoint or prepare new buffer and read it.
|
||||
*/
|
||||
NRFX_USBD_EP_ABORTED, /**< EP0 transfer can be aborted when new setup comes.
|
||||
* Any other transfer can be aborted by USB reset or driver stopping.
|
||||
*/
|
||||
NRFX_USBD_EP_BUSY, /**< Transfer is in progress. */
|
||||
} nrfx_usbd_ep_status_t;
|
||||
|
||||
/**
|
||||
* @brief Event structure.
|
||||
*
|
||||
* Structure passed to event handler.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_usbd_event_type_t type; /**< Event type. */
|
||||
union
|
||||
{
|
||||
struct {
|
||||
uint16_t framecnt; /**< Current value of frame counter. */
|
||||
} sof; /**< Data available for @ref NRFX_USBD_EVT_SOF. */
|
||||
struct {
|
||||
nrfx_usbd_ep_t ep; /**< Endpoint number. */
|
||||
} isocrc;
|
||||
struct {
|
||||
nrfx_usbd_ep_t ep; /**< Endpoint number. */
|
||||
nrfx_usbd_ep_status_t status; /**< Status for the endpoint. */
|
||||
} eptransfer;
|
||||
} data; /**< Union to store event data. */
|
||||
} nrfx_usbd_evt_t;
|
||||
|
||||
/**
|
||||
* @brief USBD event callback function type.
|
||||
*
|
||||
* @param[in] p_event Event information structure.
|
||||
*/
|
||||
typedef void (*nrfx_usbd_event_handler_t)(nrfx_usbd_evt_t const * p_event);
|
||||
|
||||
/**
|
||||
* @brief Universal data pointer.
|
||||
*
|
||||
* Universal data pointer that can be used for any type of transfer.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
void const * tx; //!< Constant TX buffer pointer.
|
||||
void * rx; //!< Writable RX buffer pointer.
|
||||
uint32_t addr; //!< Numeric value used internally by the driver.
|
||||
} nrfx_usbd_data_ptr_t;
|
||||
|
||||
/**
|
||||
* @brief Structure to be filled with information about the next transfer.
|
||||
*
|
||||
* This is used mainly for transfer feeders and consumers.
|
||||
* It describes a single endpoint transfer and therefore the size of the buffer
|
||||
* can never be higher than the endpoint size.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_usbd_data_ptr_t p_data; //!< Union with available data pointers used by the driver.
|
||||
size_t size; //!< Size of the requested transfer.
|
||||
} nrfx_usbd_ep_transfer_t;
|
||||
|
||||
/**
|
||||
* @brief Flags for the current transfer.
|
||||
*
|
||||
* Flags configured for the transfer that can be merged using the bitwise 'or' operator (|).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_USBD_TRANSFER_ZLP_FLAG = 1U << 0, //!< Add a zero-length packet.
|
||||
} nrfx_usbd_transfer_flags_t;
|
||||
|
||||
/**
|
||||
* @brief Total transfer configuration.
|
||||
*
|
||||
* This structure is used to configure total transfer information.
|
||||
* It is used by internal built-in feeders and consumers.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_usbd_data_ptr_t p_data; //!< Union with available data pointers used by the driver.
|
||||
size_t size; //!< Total size of the requested transfer.
|
||||
uint32_t flags; //!< Transfer flags.
|
||||
/**< Use the @ref nrfx_usbd_transfer_flags_t values. */
|
||||
} nrfx_usbd_transfer_t;
|
||||
|
||||
/**
|
||||
* @brief Auxiliary macro for declaring IN transfer description with optional flags.
|
||||
*
|
||||
* The base macro for creating transfers with any configuration option.
|
||||
*
|
||||
* @param name Instance name.
|
||||
* @param tx_buff Buffer to transfer.
|
||||
* @param tx_size Transfer size.
|
||||
* @param tx_flags Flags for the transfer (see @ref nrfx_usbd_transfer_flags_t).
|
||||
*
|
||||
* @return Configured variable with total transfer description.
|
||||
*/
|
||||
#define NRFX_USBD_TRANSFER_IN(name, tx_buff, tx_size, tx_flags) \
|
||||
const nrfx_usbd_transfer_t name = { \
|
||||
.p_data = { .tx = (tx_buff) }, \
|
||||
.size = (tx_size), \
|
||||
.flags = (tx_flags) \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper macro for declaring OUT transfer item (@ref nrfx_usbd_transfer_t).
|
||||
*
|
||||
* @param name Instance name.
|
||||
* @param rx_buff Buffer to transfer.
|
||||
* @param rx_size Transfer size.
|
||||
* */
|
||||
#define NRFX_USBD_TRANSFER_OUT(name, rx_buff, rx_size) \
|
||||
const nrfx_usbd_transfer_t name = { \
|
||||
.p_data = { .rx = (rx_buff) }, \
|
||||
.size = (rx_size), \
|
||||
.flags = 0 \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD transfer feeder.
|
||||
*
|
||||
* Pointer for a transfer feeder.
|
||||
* Transfer feeder is a feedback function used to prepare a single
|
||||
* TX (Device->Host) endpoint transfer.
|
||||
*
|
||||
* The transfers provided by the feeder must be simple:
|
||||
* - The size of the transfer provided by this function is limited to a single endpoint buffer.
|
||||
* Bigger transfers are not handled automatically in this case.
|
||||
* - Flash transfers are not automatically supported- you must copy them to the RAM buffer before.
|
||||
*
|
||||
* @note
|
||||
* This function may use @ref nrfx_usbd_feeder_buffer_get to gain a temporary buffer
|
||||
* that can be used to prepare transfer.
|
||||
*
|
||||
* @param[out] p_next Structure with the data for the next transfer to be filled.
|
||||
* Required only if the function returns true.
|
||||
* @param[in,out] p_context Context variable configured with the transfer.
|
||||
* @param[in] ep_size The endpoint size.
|
||||
*
|
||||
* @retval false The current transfer is the last one - you do not need to call
|
||||
* the function again.
|
||||
* @retval true There is more data to be prepared and when the current transfer
|
||||
* finishes, the feeder function is expected to be called again.
|
||||
*/
|
||||
typedef bool (*nrfx_usbd_feeder_t)(nrfx_usbd_ep_transfer_t * p_next,
|
||||
void * p_context,
|
||||
size_t ep_size);
|
||||
|
||||
/**
|
||||
* @brief USBD transfer consumer.
|
||||
*
|
||||
* Pointer for a transfer consumer.
|
||||
* Transfer consumer is a feedback function used to prepare a single
|
||||
* RX (Host->Device) endpoint transfer.
|
||||
*
|
||||
* The transfer must provide a buffer big enough to fit the whole data from the endpoint.
|
||||
* Otherwise, the NRFX_USBD_EP_OVERLOAD event is generated.
|
||||
*
|
||||
* @param[out] p_next Structure with the data for the next transfer to be filled.
|
||||
* Required only if the function returns true.
|
||||
* @param[in,out] p_context Context variable configured with the transfer.
|
||||
* @param[in] ep_size The endpoint size.
|
||||
* @param[in] data_size Number of received bytes in the endpoint buffer.
|
||||
*
|
||||
* @retval false Current transfer is the last one - you do not need to call
|
||||
* the function again.
|
||||
* @retval true There is more data to be prepared and when current transfer
|
||||
* finishes, the feeder function is expected to be called again.
|
||||
*/
|
||||
typedef bool (*nrfx_usbd_consumer_t)(nrfx_usbd_ep_transfer_t * p_next,
|
||||
void * p_context,
|
||||
size_t ep_size,
|
||||
size_t data_size);
|
||||
|
||||
/**
|
||||
* @brief Universal transfer handler.
|
||||
*
|
||||
* Union with feeder and consumer function pointer.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
nrfx_usbd_feeder_t feeder; //!< Feeder function pointer.
|
||||
nrfx_usbd_consumer_t consumer; //!< Consumer function pointer.
|
||||
} nrfx_usbd_handler_t;
|
||||
|
||||
/**
|
||||
* @brief USBD transfer descriptor.
|
||||
*
|
||||
* Universal structure that may hold the setup for callback configuration for
|
||||
* IN or OUT type of the transfer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_usbd_handler_t handler; //!< Handler for the current transfer, function pointer.
|
||||
void * p_context; //!< Context for the transfer handler.
|
||||
} nrfx_usbd_handler_desc_t;
|
||||
|
||||
/**
|
||||
* @brief Setup packet structure.
|
||||
*
|
||||
* Structure that contains interpreted SETUP packet as described in USB specification.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bmRequestType; //!< byte 0
|
||||
uint8_t bRequest; //!< byte 1
|
||||
uint16_t wValue; //!< byte 2, 3
|
||||
uint16_t wIndex; //!< byte 4, 5
|
||||
uint16_t wLength; //!< byte 6, 7
|
||||
} nrfx_usbd_setup_t;
|
||||
|
||||
/**
|
||||
* @brief Driver initialization.
|
||||
*
|
||||
* @param[in] event_handler Event handler provided by the user. Cannot be null.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Initialization successful.
|
||||
* @retval NRFX_ERROR_INVALID_STATE Driver was already initialized.
|
||||
*/
|
||||
nrfx_err_t nrfx_usbd_init(nrfx_usbd_event_handler_t event_handler);
|
||||
|
||||
/**
|
||||
* @brief Driver deinitialization.
|
||||
*/
|
||||
void nrfx_usbd_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Enable the USBD port.
|
||||
*
|
||||
* After calling this function USBD peripheral would be enabled.
|
||||
* The USB LDO would be enabled.
|
||||
* Enabled USBD peripheral would request HFCLK.
|
||||
* This function does not enable external oscillator, so if it is not enabled by other part of the
|
||||
* program after enabling USBD driver HFINT would be used for the USBD peripheral.
|
||||
* It is perfectly fine until USBD is started. See @ref nrfx_usbd_start.
|
||||
*
|
||||
* In normal situation this function should be called in reaction to USBDETECTED
|
||||
* event from POWER peripheral.
|
||||
*
|
||||
* Interrupts and USB pins pull-up would stay disabled until @ref nrfx_usbd_start
|
||||
* function is called.
|
||||
*/
|
||||
void nrfx_usbd_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable the USBD port.
|
||||
*
|
||||
* After calling this function USBD peripheral would be disabled.
|
||||
* No events would be detected or processed by the driver.
|
||||
* Clock for the peripheral would be disconnected.
|
||||
*/
|
||||
void nrfx_usbd_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Start USB functionality.
|
||||
*
|
||||
* After calling this function USBD peripheral should be fully functional
|
||||
* and all new incoming events / interrupts would be processed by the driver.
|
||||
*
|
||||
* Also only after calling this function host sees new connected device.
|
||||
*
|
||||
* Call this function when USBD power LDO regulator is ready - on USBPWRRDY event
|
||||
* from POWER peripheral.
|
||||
*
|
||||
* Before USBD interrupts are enabled, external HFXO is requested.
|
||||
*
|
||||
* @param enable_sof The flag that is used to enable SOF processing.
|
||||
* If it is false, SOF interrupt is left disabled and will not be generated.
|
||||
* This improves power saving if SOF is not required.
|
||||
*
|
||||
* @note If the isochronous endpoints are going to be used,
|
||||
* it is required to enable the SOF.
|
||||
* In other case any isochronous endpoint would stay busy
|
||||
* after first transmission.
|
||||
*/
|
||||
void nrfx_usbd_start(bool enable_sof);
|
||||
|
||||
/**
|
||||
* @brief Stop USB functionality.
|
||||
*
|
||||
* This function disables USBD pull-up and interrupts.
|
||||
*
|
||||
* The HFXO request is released in this function.
|
||||
*
|
||||
* @note
|
||||
* This function can also be used to logically disconnect USB from the HOST that
|
||||
* would force it to enumerate device after calling @ref nrfx_usbd_start.
|
||||
*/
|
||||
void nrfx_usbd_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Check if driver is initialized.
|
||||
*
|
||||
* @retval false Driver is not initialized.
|
||||
* @retval true Driver is initialized.
|
||||
*/
|
||||
bool nrfx_usbd_is_initialized(void);
|
||||
|
||||
/**
|
||||
* @brief Check if driver is enabled.
|
||||
*
|
||||
* @retval false Driver is disabled.
|
||||
* @retval true Driver is enabled.
|
||||
*/
|
||||
bool nrfx_usbd_is_enabled(void);
|
||||
|
||||
/**
|
||||
* @brief Check if driver is started.
|
||||
*
|
||||
* @retval false Driver is not started.
|
||||
* @retval true Driver is started (fully functional).
|
||||
* @note The USBD peripheral interrupt state is checked.
|
||||
*/
|
||||
bool nrfx_usbd_is_started(void);
|
||||
|
||||
/**
|
||||
* @brief Suspend USBD operation.
|
||||
*
|
||||
* The USBD peripheral is forced to go into the low power mode.
|
||||
* The function has to be called in the reaction to @ref NRFX_USBD_EVT_SUSPEND event
|
||||
* when the firmware is ready.
|
||||
*
|
||||
* After successful call of this function most of the USBD registers would be unavailable.
|
||||
*
|
||||
* @note Check returned value for the feedback if suspending was successful.
|
||||
*
|
||||
* @retval true USBD peripheral successfully suspended.
|
||||
* @retval false USBD peripheral was not suspended due to resume detection.
|
||||
*/
|
||||
bool nrfx_usbd_suspend(void);
|
||||
|
||||
/**
|
||||
* @brief Start wake up procedure.
|
||||
*
|
||||
* The USBD peripheral is forced to quit the low power mode.
|
||||
* After calling this function all the USBD registers would be available.
|
||||
*
|
||||
* The hardware starts measuring time when wake up is possible.
|
||||
* This may take 0-5 ms depending on how long the SUSPEND state was kept on the USB line.
|
||||
|
||||
* When NRFX_USBD_EVT_WUREQ event is generated it means that Wake Up signaling has just been
|
||||
* started on the USB lines.
|
||||
*
|
||||
* @note Do not expect only @ref NRFX_USBD_EVT_WUREQ event.
|
||||
* There always may appear @ref NRFX_USBD_EVT_RESUME event.
|
||||
* @note NRFX_USBD_EVT_WUREQ event means that Remote WakeUp signal
|
||||
* has just begun to be generated.
|
||||
* This may take up to 20 ms for the bus to become active.
|
||||
*
|
||||
* @retval true WakeUp procedure started.
|
||||
* @retval false No WakeUp procedure started - bus is already active.
|
||||
*/
|
||||
bool nrfx_usbd_wakeup_req(void);
|
||||
|
||||
/**
|
||||
* @brief Check if USBD is in SUSPEND mode.
|
||||
*
|
||||
* @note This is the information about peripheral itself, not about the bus state.
|
||||
*
|
||||
* @retval true USBD peripheral is suspended.
|
||||
* @retval false USBD peripheral is active.
|
||||
*/
|
||||
bool nrfx_usbd_suspend_check(void);
|
||||
|
||||
/**
|
||||
* @brief Enable only interrupts that should be processed in SUSPEND mode.
|
||||
*
|
||||
* Auxiliary function to help with SUSPEND mode integration.
|
||||
* It enables only the interrupts that can be properly processed without stable HFCLK.
|
||||
*
|
||||
* Normally all the interrupts are enabled.
|
||||
* Use this function to suspend interrupt processing that may require stable HFCLK until the
|
||||
* clock is enabled.
|
||||
*
|
||||
* @sa nrfx_usbd_active_irq_config
|
||||
*/
|
||||
void nrfx_usbd_suspend_irq_config(void);
|
||||
|
||||
/**
|
||||
* @brief Default active interrupt configuration.
|
||||
*
|
||||
* Default interrupt configuration.
|
||||
* Use in a pair with @ref nrfx_usbd_active_irq_config.
|
||||
*
|
||||
* @sa nrfx_usbd_suspend_irq_config
|
||||
*/
|
||||
void nrfx_usbd_active_irq_config(void);
|
||||
|
||||
/**
|
||||
* @brief Check the bus state.
|
||||
*
|
||||
* This function checks if the bus state is suspended.
|
||||
*
|
||||
* @note The value returned by this function changes on SUSPEND and RESUME event processing.
|
||||
*
|
||||
* @retval true USBD bus is suspended.
|
||||
* @retval false USBD bus is active.
|
||||
*/
|
||||
bool nrfx_usbd_bus_suspend_check(void);
|
||||
|
||||
/**
|
||||
* @brief Force the bus state to active
|
||||
*/
|
||||
void nrfx_usbd_force_bus_wakeup(void);
|
||||
|
||||
/**
|
||||
* @brief Configure packet size that should be supported by the endpoint.
|
||||
*
|
||||
* The real endpoint buffer size is always the same.
|
||||
* This value sets max packet size that would be transmitted over the endpoint.
|
||||
* This is required by the driver.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
* @param[in] size Required maximum packet size.
|
||||
*
|
||||
* @note Endpoint size is always set to @ref NRFX_USBD_EPSIZE or @ref NRFX_USBD_ISOSIZE / 2
|
||||
* when @ref nrfx_usbd_ep_enable function is called.
|
||||
*/
|
||||
void nrfx_usbd_ep_max_packet_size_set(nrfx_usbd_ep_t ep, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief Get configured endpoint packet size.
|
||||
*
|
||||
* Function to get configured endpoint size on the buffer.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
*
|
||||
* @return Maximum pocket size configured on selected endpoint.
|
||||
*/
|
||||
uint16_t nrfx_usbd_ep_max_packet_size_get(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Check if the selected endpoint is enabled.
|
||||
*
|
||||
* @param[in] ep Endpoint number to check.
|
||||
*
|
||||
* @retval true Endpoint is enabled.
|
||||
* @retval false Endpoint is disabled.
|
||||
*/
|
||||
bool nrfx_usbd_ep_enable_check(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Enable selected endpoint.
|
||||
*
|
||||
* This function enables endpoint itself and its interrupts.
|
||||
*
|
||||
* @param[in] ep Endpoint number to enable.
|
||||
*
|
||||
* @note
|
||||
* Max packet size is set to endpoint default maximum value.
|
||||
*
|
||||
* @sa nrfx_usbd_ep_max_packet_size_set
|
||||
*/
|
||||
void nrfx_usbd_ep_enable(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Disable selected endpoint.
|
||||
*
|
||||
* This function disables endpoint itself and its interrupts.
|
||||
*
|
||||
* @param[in] ep Endpoint number to disable.
|
||||
*/
|
||||
void nrfx_usbd_ep_disable(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Disable all endpoints except for EP0.
|
||||
*
|
||||
* Disable all endpoints that can be disabled in USB device while it is still active.
|
||||
*/
|
||||
void nrfx_usbd_ep_default_config(void);
|
||||
|
||||
/**
|
||||
* @brief Start sending data over endpoint.
|
||||
*
|
||||
* Function initializes endpoint transmission.
|
||||
* This is asynchronous function - it finishes immediately after configuration
|
||||
* for transmission is prepared.
|
||||
*
|
||||
* @note Data buffer pointed by p_data have to be kept active till
|
||||
* @ref NRFX_USBD_EVT_EPTRANSFER event is generated.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
* For IN endpoint sending would be initiated.
|
||||
* For OUT endpoint receiving would be initiated.
|
||||
* @param[in] p_transfer Transfer parameters.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Transfer queued or started.
|
||||
* @retval NRFX_ERROR_BUSY Selected endpoint is pending.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR Unexpected transfer on EPIN0 or EPOUT0.
|
||||
*/
|
||||
nrfx_err_t nrfx_usbd_ep_transfer(nrfx_usbd_ep_t ep,
|
||||
nrfx_usbd_transfer_t const * p_transfer);
|
||||
|
||||
/**
|
||||
* @brief Start sending data over the endpoint using the transfer handler function.
|
||||
*
|
||||
* This function initializes an endpoint transmission.
|
||||
* Just before data is transmitted, the transfer handler
|
||||
* is called and it prepares a data chunk.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
* For an IN endpoint, sending is initiated.
|
||||
* For an OUT endpoint, receiving is initiated.
|
||||
* @param[in] p_handler Transfer handler - feeder for IN direction and consumer for
|
||||
* OUT direction.
|
||||
*
|
||||
* @retval NRFX_SUCCESS Transfer queued or started.
|
||||
* @retval NRFX_ERROR_BUSY Selected endpoint is pending.
|
||||
* @retval NRFX_ERROR_INVALID_ADDR Unexpected transfer on EPIN0 or EPOUT0.
|
||||
*/
|
||||
nrfx_err_t nrfx_usbd_ep_handled_transfer(nrfx_usbd_ep_t ep,
|
||||
nrfx_usbd_handler_desc_t const * p_handler);
|
||||
|
||||
/**
|
||||
* @brief Get the temporary buffer to be used by the feeder.
|
||||
*
|
||||
* This buffer is used for TX transfers and it can be reused automatically
|
||||
* when the transfer is finished.
|
||||
* Use it for transfer preparation.
|
||||
*
|
||||
* May be used inside the feeder configured in @ref nrfx_usbd_ep_handled_transfer.
|
||||
*
|
||||
* @return Pointer to the buffer that can be used temporarily.
|
||||
*
|
||||
* @sa NRFX_USBD_FEEDER_BUFFER_SIZE
|
||||
*/
|
||||
void * nrfx_usbd_feeder_buffer_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get the information about last finished or current transfer.
|
||||
*
|
||||
* Function returns the status of the last buffer set for transfer on selected endpoint.
|
||||
* The status considers last buffer set by @ref nrfx_usbd_ep_transfer function or
|
||||
* by transfer callback function.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
* @param[out] p_size Information about the current/last transfer size.
|
||||
*
|
||||
* @return Endpoint status.
|
||||
*
|
||||
* @sa nrfx_usbd_ep_status_t
|
||||
*/
|
||||
nrfx_usbd_ep_status_t nrfx_usbd_ep_status_get(nrfx_usbd_ep_t ep, size_t * p_size);
|
||||
|
||||
/**
|
||||
* @brief Get number of received bytes.
|
||||
*
|
||||
* Get the number of received bytes.
|
||||
* The function behavior is undefined when called on IN endpoint.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
*
|
||||
* @return Number of received bytes.
|
||||
*/
|
||||
size_t nrfx_usbd_epout_size_get(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Check if endpoint buffer is ready or is under USB IP control.
|
||||
*
|
||||
* Function to test if endpoint is busy.
|
||||
* Endpoint that is busy cannot be accessed by MCU.
|
||||
* It means that:
|
||||
* - OUT (TX) endpoint: Last uploaded data is still in endpoint and is waiting
|
||||
* to be received by the host.
|
||||
* - IN (RX) endpoint: Endpoint is ready to receive data from the host
|
||||
* and the endpoint does not have any data.
|
||||
* When endpoint is not busy:
|
||||
* - OUT (TX) endpoint: New data can be uploaded.
|
||||
* - IN (RX) endpoint: New data can be downloaded using @ref nrfx_usbd_ep_transfer
|
||||
* function.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
*
|
||||
* @retval false Endpoint is not busy.
|
||||
* @retval true Endpoint is busy.
|
||||
*/
|
||||
bool nrfx_usbd_ep_is_busy(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Stall endpoint
|
||||
*
|
||||
* Stall endpoit to send error information during next transfer request from
|
||||
* the host.
|
||||
*
|
||||
* @note To stall endpoint it is safer to use @ref nrfx_usbd_setup_stall
|
||||
* @note Stalled endpoint would not be cleared when DMA transfer finishes.
|
||||
*
|
||||
* @param[in] ep Endpoint number to stall.
|
||||
*/
|
||||
void nrfx_usbd_ep_stall(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Clear stall flag on endpoint.
|
||||
*
|
||||
* This function clears endpoint that is stalled.
|
||||
* @note
|
||||
* If it is OUT endpoint (receiving) it would be also prepared for reception.
|
||||
* It means that busy flag would be set.
|
||||
* @note
|
||||
* In endpoint (transmitting) would not be cleared - it gives possibility to
|
||||
* write new data before transmitting.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
*/
|
||||
void nrfx_usbd_ep_stall_clear(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Check if endpoint is stalled.
|
||||
*
|
||||
* This function gets stall state of selected endpoint.
|
||||
*
|
||||
* @param[in] ep Endpoint number to check.
|
||||
*
|
||||
* @retval false Endpoint is not stalled.
|
||||
* @retval true Endpoint is stalled.
|
||||
*/
|
||||
bool nrfx_usbd_ep_stall_check(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Clear current endpoint data toggle.
|
||||
*
|
||||
* @param[in] ep Endpoint number to clear.
|
||||
*/
|
||||
void nrfx_usbd_ep_dtoggle_clear(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Get parsed setup data.
|
||||
*
|
||||
* Function fills the parsed setup data structure.
|
||||
*
|
||||
* @param[out] p_setup Pointer to data structure that would be filled by
|
||||
* parsed data.
|
||||
*/
|
||||
void nrfx_usbd_setup_get(nrfx_usbd_setup_t * p_setup);
|
||||
|
||||
/**
|
||||
* @brief Clear the control endpoint for packet reception during DATA stage.
|
||||
*
|
||||
* This function may be called if any more data in control write transfer is expected.
|
||||
* Clears only OUT endpoint to be able to take another OUT data token.
|
||||
* It does not allow STATUS stage.
|
||||
* @sa nrfx_usbd_setup_clear
|
||||
*/
|
||||
void nrfx_usbd_setup_data_clear(void);
|
||||
|
||||
/**
|
||||
* @brief Clear setup endpoint.
|
||||
*
|
||||
* This function acknowledges setup when SETUP command was received and processed.
|
||||
* It has to be called if no data respond for the SETUP command is sent.
|
||||
*/
|
||||
void nrfx_usbd_setup_clear(void);
|
||||
|
||||
/**
|
||||
* @brief Stall setup endpoint.
|
||||
*
|
||||
* Mark an error on setup endpoint.
|
||||
*/
|
||||
void nrfx_usbd_setup_stall(void);
|
||||
|
||||
/**
|
||||
* @brief Abort pending transfer on selected endpoint.
|
||||
*
|
||||
* @param[in] ep Endpoint number.
|
||||
*/
|
||||
void nrfx_usbd_ep_abort(nrfx_usbd_ep_t ep);
|
||||
|
||||
/**
|
||||
* @brief Get the information about expected transfer SETUP data direction.
|
||||
*
|
||||
* Function returns the information about last expected transfer direction.
|
||||
*
|
||||
* @retval NRFX_USBD_EPOUT0 Expecting OUT (Host->Device) direction or no data.
|
||||
* @retval NRFX_USBD_EPIN0 Expecting IN (Device->Host) direction.
|
||||
*/
|
||||
nrfx_usbd_ep_t nrfx_usbd_last_setup_dir_get(void);
|
||||
|
||||
/**
|
||||
* @brief Drop transfer on OUT endpoint.
|
||||
*
|
||||
* @param[in] ep OUT endpoint ID.
|
||||
*/
|
||||
void nrfx_usbd_transfer_out_drop(nrfx_usbd_ep_t ep);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_usbd_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_USBD_H__
|
||||
168
modules/nrfx/drivers/include/nrfx_wdt.h
Normal file
168
modules/nrfx/drivers/include/nrfx_wdt.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 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 NRFX_WDT_H__
|
||||
#define NRFX_WDT_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <hal/nrf_wdt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_wdt WDT driver
|
||||
* @{
|
||||
* @ingroup nrf_wdt
|
||||
* @brief Watchdog Timer (WDT) peripheral driver.
|
||||
*/
|
||||
|
||||
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ) || defined(__NRFX_DOXYGEN__)
|
||||
/** @brief WDT instance interrupt priority configuration. */
|
||||
#define NRFX_WDT_IRQ_CONFIG .interrupt_priority = NRFX_WDT_CONFIG_IRQ_PRIORITY
|
||||
#else
|
||||
#define NRFX_WDT_IRQ_CONFIG
|
||||
#endif
|
||||
|
||||
/**@brief Struct for WDT initialization. */
|
||||
typedef struct
|
||||
{
|
||||
nrf_wdt_behaviour_t behaviour; /**< WDT behaviour when CPU in sleep/halt mode. */
|
||||
uint32_t reload_value; /**< WDT reload value in ms. */
|
||||
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ) || defined(__NRFX_DOXYGEN__)
|
||||
uint8_t interrupt_priority; /**< WDT interrupt priority */
|
||||
#endif
|
||||
} nrfx_wdt_config_t;
|
||||
|
||||
/** @brief WDT event handler function type. */
|
||||
typedef void (*nrfx_wdt_event_handler_t)(void);
|
||||
|
||||
/** @brief WDT channel ID type. */
|
||||
typedef nrf_wdt_rr_register_t nrfx_wdt_channel_id;
|
||||
|
||||
/** @brief WDT driver default configuration. */
|
||||
#define NRFX_WDT_DEAFULT_CONFIG \
|
||||
{ \
|
||||
.behaviour = (nrf_wdt_behaviour_t)NRFX_WDT_CONFIG_BEHAVIOUR, \
|
||||
.reload_value = NRFX_WDT_CONFIG_RELOAD_VALUE, \
|
||||
NRFX_WDT_IRQ_CONFIG \
|
||||
}
|
||||
/**
|
||||
* @brief This function initializes the watchdog.
|
||||
*
|
||||
* @param[in] p_config Pointer to the structure with the initial configuration.
|
||||
* @param[in] wdt_event_handler Event handler provided by the user. Ignored when
|
||||
* @ref NRFX_WDT_CONFIG_NO_IRQ option is enabled.
|
||||
*
|
||||
* @return NRFX_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
|
||||
nrfx_wdt_event_handler_t wdt_event_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for allocating a watchdog channel.
|
||||
*
|
||||
* @note This function can not be called after nrfx_wdt_start(void).
|
||||
*
|
||||
* @param[out] p_channel_id ID of granted channel.
|
||||
*
|
||||
* @return NRFX_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
nrfx_err_t nrfx_wdt_channel_alloc(nrfx_wdt_channel_id * p_channel_id);
|
||||
|
||||
/**
|
||||
* @brief Function for starting the watchdog.
|
||||
*
|
||||
* @note After calling this function the watchdog is started, so the user needs to feed all allocated
|
||||
* watchdog channels to avoid reset. At least one watchdog channel must be allocated.
|
||||
*/
|
||||
void nrfx_wdt_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for feeding the watchdog.
|
||||
*
|
||||
* @details Function feeds all allocated watchdog channels.
|
||||
*/
|
||||
void nrfx_wdt_feed(void);
|
||||
|
||||
/**
|
||||
* @brief Function for feeding an invidual watchdog channel.
|
||||
*
|
||||
* @param[in] channel_id ID of watchdog channel.
|
||||
*/
|
||||
void nrfx_wdt_channel_feed(nrfx_wdt_channel_id channel_id);
|
||||
|
||||
/**
|
||||
* @brief Function for returning a requested task address for the WDT driver module.
|
||||
*
|
||||
* @param[in] task One of the peripheral tasks.
|
||||
*
|
||||
* @return Task address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_wdt_ppi_task_addr(nrf_wdt_task_t task)
|
||||
{
|
||||
return nrf_wdt_task_address_get(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for returning a requested event address for the wdt driver module.
|
||||
*
|
||||
* @param[in] event One of the peripheral events.
|
||||
*
|
||||
* @return Event address.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_wdt_ppi_event_addr(nrf_wdt_event_t event)
|
||||
{
|
||||
return nrf_wdt_event_address_get(event);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
void nrfx_wdt_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
342
modules/nrfx/drivers/nrfx_common.h
Normal file
342
modules/nrfx/drivers/nrfx_common.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 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 NRFX_COMMON_H__
|
||||
#define NRFX_COMMON_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <nrf.h>
|
||||
#include <nrf_peripherals.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_common Common module
|
||||
* @{
|
||||
* @ingroup nrfx
|
||||
* @brief Common module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Macro for checking if the specified identifier is defined and it has
|
||||
* a non-zero value.
|
||||
*
|
||||
* Normally, preprocessors treat all undefined identifiers as having the value
|
||||
* zero. However, some tools, like static code analyzers, can issue a warning
|
||||
* when such identifier is evaluated. This macro gives the possibility to suppress
|
||||
* such warnings only in places where this macro is used for evaluation, not in
|
||||
* the whole analyzed code.
|
||||
*/
|
||||
#define NRFX_CHECK(module_enabled) (module_enabled)
|
||||
|
||||
/**
|
||||
* @brief Macro for concatenating two tokens in macro expansion.
|
||||
*
|
||||
* @note This macro is expanded in two steps so that tokens given as macros
|
||||
* themselves are fully expanded before they are merged.
|
||||
*
|
||||
* @param[in] p1 First token.
|
||||
* @param[in] p2 Second token.
|
||||
*
|
||||
* @return The two tokens merged into one, unless they cannot together form
|
||||
* a valid token (in such case, the preprocessor issues a warning and
|
||||
* does not perform the concatenation).
|
||||
*
|
||||
* @sa NRFX_CONCAT_3
|
||||
*/
|
||||
#define NRFX_CONCAT_2(p1, p2) NRFX_CONCAT_2_(p1, p2)
|
||||
|
||||
/** @brief Internal macro used by @ref NRFX_CONCAT_2 to perform the expansion in two steps. */
|
||||
#define NRFX_CONCAT_2_(p1, p2) p1 ## p2
|
||||
|
||||
/**
|
||||
* @brief Macro for concatenating three tokens in macro expansion.
|
||||
*
|
||||
* @note This macro is expanded in two steps so that tokens given as macros
|
||||
* themselves are fully expanded before they are merged.
|
||||
*
|
||||
* @param[in] p1 First token.
|
||||
* @param[in] p2 Second token.
|
||||
* @param[in] p3 Third token.
|
||||
*
|
||||
* @return The three tokens merged into one, unless they cannot together form
|
||||
* a valid token (in such case, the preprocessor issues a warning and
|
||||
* does not perform the concatenation).
|
||||
*
|
||||
* @sa NRFX_CONCAT_2
|
||||
*/
|
||||
#define NRFX_CONCAT_3(p1, p2, p3) NRFX_CONCAT_3_(p1, p2, p3)
|
||||
|
||||
/** @brief Internal macro used by @ref NRFX_CONCAT_3 to perform the expansion in two steps. */
|
||||
#define NRFX_CONCAT_3_(p1, p2, p3) p1 ## p2 ## p3
|
||||
|
||||
/**
|
||||
* @brief Macro for performing rounded integer division (as opposed to
|
||||
* truncating the result).
|
||||
*
|
||||
* @param[in] a Numerator.
|
||||
* @param[in] b Denominator.
|
||||
*
|
||||
* @return Rounded (integer) result of dividing @c a by @c b.
|
||||
*/
|
||||
#define NRFX_ROUNDED_DIV(a, b) (((a) + ((b) / 2)) / (b))
|
||||
|
||||
/**
|
||||
* @brief Macro for performing integer division, making sure the result is rounded up.
|
||||
*
|
||||
* @details A typical use case for this macro is to compute the number of objects
|
||||
* with size @c b required to hold @c a number of bytes.
|
||||
*
|
||||
* @param[in] a Numerator.
|
||||
* @param[in] b Denominator.
|
||||
*
|
||||
* @return Integer result of dividing @c a by @c b, rounded up.
|
||||
*/
|
||||
#define NRFX_CEIL_DIV(a, b) ((((a) - 1) / (b)) + 1)
|
||||
|
||||
/**
|
||||
* @brief Macro for getting the number of elements in an array.
|
||||
*
|
||||
* @param[in] array Name of the array.
|
||||
*
|
||||
* @return Array element count.
|
||||
*/
|
||||
#define NRFX_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
|
||||
/**
|
||||
* @brief Macro for getting the offset (in bytes) from the beginning of a structure
|
||||
* of the specified type to its specified member.
|
||||
*
|
||||
* @param[in] type Structure type.
|
||||
* @param[in] member Structure member whose offset is searched for.
|
||||
*
|
||||
* @return Member offset in bytes.
|
||||
*/
|
||||
#define NRFX_OFFSETOF(type, member) ((size_t)&(((type *)0)->member))
|
||||
|
||||
/**@brief Macro for checking if given lengths of EasyDMA transfers do not exceed
|
||||
* the limit of the specified peripheral.
|
||||
*
|
||||
* @param[in] peripheral Peripheral to check the lengths against.
|
||||
* @param[in] length1 First length to be checked.
|
||||
* @param[in] length2 Second length to be checked (pass 0 if not needed).
|
||||
*
|
||||
* @retval true The length of buffers does not exceed the limit of the specified peripheral.
|
||||
* @retval false The length of buffers exceeds the limit of the specified peripheral.
|
||||
*/
|
||||
#define NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, length1, length2) \
|
||||
(((length1) < (1U << NRFX_CONCAT_2(peripheral, _EASYDMA_MAXCNT_SIZE))) && \
|
||||
((length2) < (1U << NRFX_CONCAT_2(peripheral, _EASYDMA_MAXCNT_SIZE))))
|
||||
|
||||
/**
|
||||
* @brief Macro for waiting until condition is met.
|
||||
*
|
||||
* @param[in] condition Condition to meet.
|
||||
* @param[in] attempts Maximum number of condition checks. Must not be 0.
|
||||
* @param[in] delay_us Delay between consecutive checks, in microseconds.
|
||||
* @param[out] result Boolean variable to store the result of the wait process.
|
||||
* Set to true if the condition is met or false otherwise.
|
||||
*/
|
||||
#define NRFX_WAIT_FOR(condition, attempts, delay_us, result) \
|
||||
do { \
|
||||
result = false; \
|
||||
uint32_t remaining_attempts = (attempts); \
|
||||
do { \
|
||||
if (condition) \
|
||||
{ \
|
||||
result = true; \
|
||||
break; \
|
||||
} \
|
||||
NRFX_DELAY_US(delay_us); \
|
||||
} while (--remaining_attempts); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Macro for getting the ID number of the specified peripheral.
|
||||
*
|
||||
* For peripherals in Nordic SoCs, there is a direct relationship between their
|
||||
* ID numbers and their base addresses. See the chapter "Peripheral interface"
|
||||
* (section "Peripheral ID") in the Product Specification.
|
||||
*
|
||||
* @param[in] base_addr Peripheral base address or pointer.
|
||||
*
|
||||
* @return ID number associated with the specified peripheral.
|
||||
*/
|
||||
#define NRFX_PERIPHERAL_ID_GET(base_addr) (uint8_t)((uint32_t)(base_addr) >> 12)
|
||||
|
||||
/**
|
||||
* @brief Macro for getting the interrupt number assigned to a specific
|
||||
* peripheral.
|
||||
*
|
||||
* For peripherals in Nordic SoCs, the IRQ number assigned to a peripheral is
|
||||
* equal to its ID number. See the chapter "Peripheral interface" (sections
|
||||
* "Peripheral ID" and "Interrupts") in the Product Specification.
|
||||
*
|
||||
* @param[in] base_addr Peripheral base address or pointer.
|
||||
*
|
||||
* @return Interrupt number associated with the specified peripheral.
|
||||
*/
|
||||
#define NRFX_IRQ_NUMBER_GET(base_addr) NRFX_PERIPHERAL_ID_GET(base_addr)
|
||||
|
||||
/** @brief IRQ handler type. */
|
||||
typedef void (* nrfx_irq_handler_t)(void);
|
||||
|
||||
/** @brief Driver state. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_DRV_STATE_UNINITIALIZED, ///< Uninitialized.
|
||||
NRFX_DRV_STATE_INITIALIZED, ///< Initialized but powered off.
|
||||
NRFX_DRV_STATE_POWERED_ON, ///< Initialized and powered on.
|
||||
} nrfx_drv_state_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for checking if an object is placed in the Data RAM region.
|
||||
*
|
||||
* Several peripherals (the ones using EasyDMA) require the transfer buffers
|
||||
* to be placed in the Data RAM region. This function can be used to check if
|
||||
* this condition is met.
|
||||
*
|
||||
* @param[in] p_object Pointer to an object whose location is to be checked.
|
||||
*
|
||||
* @retval true The pointed object is located in the Data RAM region.
|
||||
* @retval false The pointed object is not located in the Data RAM region.
|
||||
*/
|
||||
__STATIC_INLINE bool nrfx_is_in_ram(void const * p_object);
|
||||
|
||||
/**
|
||||
* @brief Function for checking if an object is aligned to a 32-bit word
|
||||
*
|
||||
* Several peripherals (the ones using EasyDMA) require the transfer buffers
|
||||
* to be aligned to a 32-bit word. This function can be used to check if
|
||||
* this condition is met.
|
||||
*
|
||||
* @param[in] p_object Pointer to an object whose location is to be checked.
|
||||
*
|
||||
* @retval true The pointed object is aligned to a 32-bit word.
|
||||
* @retval false The pointed object is not aligned to a 32-bit word.
|
||||
*/
|
||||
__STATIC_INLINE bool nrfx_is_word_aligned(void const * p_object);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the interrupt number for the specified peripheral.
|
||||
*
|
||||
* @param[in] p_reg Peripheral base pointer.
|
||||
*
|
||||
* @return Interrupt number associated with the pointed peripheral.
|
||||
*/
|
||||
__STATIC_INLINE IRQn_Type nrfx_get_irq_number(void const * p_reg);
|
||||
|
||||
/**
|
||||
* @brief Function for converting an INTEN register bit position to the
|
||||
* corresponding event identifier.
|
||||
*
|
||||
* The event identifier is the offset between the event register address and
|
||||
* the peripheral base address, and is equal (thus, can be directly cast) to
|
||||
* the corresponding value of the enumerated type from HAL (nrf_*_event_t).
|
||||
*
|
||||
* @param[in] bit INTEN register bit position.
|
||||
*
|
||||
* @return Event identifier.
|
||||
*
|
||||
* @sa nrfx_event_to_bitpos
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_bitpos_to_event(uint32_t bit);
|
||||
|
||||
/**
|
||||
* @brief Function for converting an event identifier to the corresponding
|
||||
* INTEN register bit position.
|
||||
*
|
||||
* The event identifier is the offset between the event register address and
|
||||
* the peripheral base address, and is equal (thus, can be directly cast) to
|
||||
* the corresponding value of the enumerated type from HAL (nrf_*_event_t).
|
||||
*
|
||||
* @param[in] event Event identifier.
|
||||
*
|
||||
* @return INTEN register bit position.
|
||||
*
|
||||
* @sa nrfx_bitpos_to_event
|
||||
*/
|
||||
__STATIC_INLINE uint32_t nrfx_event_to_bitpos(uint32_t event);
|
||||
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE bool nrfx_is_in_ram(void const * p_object)
|
||||
{
|
||||
return ((((uint32_t)p_object) & 0xE0000000u) == 0x20000000u);
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool nrfx_is_word_aligned(void const * p_object)
|
||||
{
|
||||
return ((((uint32_t)p_object) & 0x3u) == 0u);
|
||||
}
|
||||
|
||||
__STATIC_INLINE IRQn_Type nrfx_get_irq_number(void const * p_reg)
|
||||
{
|
||||
return (IRQn_Type)NRFX_IRQ_NUMBER_GET(p_reg);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_bitpos_to_event(uint32_t bit)
|
||||
{
|
||||
static const uint32_t event_reg_offset = 0x100u;
|
||||
return event_reg_offset + (bit * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t nrfx_event_to_bitpos(uint32_t event)
|
||||
{
|
||||
static const uint32_t event_reg_offset = 0x100u;
|
||||
return (event - event_reg_offset) / sizeof(uint32_t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_COMMON_H__
|
||||
85
modules/nrfx/drivers/nrfx_errors.h
Normal file
85
modules/nrfx/drivers/nrfx_errors.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 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 NRFX_ERRORS_H__
|
||||
#define NRFX_ERRORS_H__
|
||||
|
||||
#if !NRFX_CHECK(NRFX_CUSTOM_ERROR_CODES)
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_error_codes Global Error Codes
|
||||
* @{
|
||||
* @ingroup nrfx
|
||||
*
|
||||
* @brief Global error code definitions.
|
||||
*/
|
||||
|
||||
/** @brief Base number of error codes. */
|
||||
#define NRFX_ERROR_BASE_NUM 0x0BAD0000
|
||||
|
||||
/** @brief Base number of driver error codes. */
|
||||
#define NRFX_ERROR_DRIVERS_BASE_NUM (NRFX_ERROR_BASE_NUM + 0x10000)
|
||||
|
||||
/** @brief Enumerated type for error codes. */
|
||||
typedef enum {
|
||||
NRFX_SUCCESS = (NRFX_ERROR_BASE_NUM + 0), ///< Operation performed successfully.
|
||||
NRFX_ERROR_INTERNAL = (NRFX_ERROR_BASE_NUM + 1), ///< Internal error.
|
||||
NRFX_ERROR_NO_MEM = (NRFX_ERROR_BASE_NUM + 2), ///< No memory for operation.
|
||||
NRFX_ERROR_NOT_SUPPORTED = (NRFX_ERROR_BASE_NUM + 3), ///< Not supported.
|
||||
NRFX_ERROR_INVALID_PARAM = (NRFX_ERROR_BASE_NUM + 4), ///< Invalid parameter.
|
||||
NRFX_ERROR_INVALID_STATE = (NRFX_ERROR_BASE_NUM + 5), ///< Invalid state, operation disallowed in this state.
|
||||
NRFX_ERROR_INVALID_LENGTH = (NRFX_ERROR_BASE_NUM + 6), ///< Invalid length.
|
||||
NRFX_ERROR_TIMEOUT = (NRFX_ERROR_BASE_NUM + 7), ///< Operation timed out.
|
||||
NRFX_ERROR_FORBIDDEN = (NRFX_ERROR_BASE_NUM + 8), ///< Operation is forbidden.
|
||||
NRFX_ERROR_NULL = (NRFX_ERROR_BASE_NUM + 9), ///< Null pointer.
|
||||
NRFX_ERROR_INVALID_ADDR = (NRFX_ERROR_BASE_NUM + 10), ///< Bad memory address.
|
||||
NRFX_ERROR_BUSY = (NRFX_ERROR_BASE_NUM + 11), ///< Busy.
|
||||
NRFX_ERROR_ALREADY_INITIALIZED = (NRFX_ERROR_BASE_NUM + 12), ///< Module already initialized.
|
||||
|
||||
NRFX_ERROR_DRV_TWI_ERR_OVERRUN = (NRFX_ERROR_DRIVERS_BASE_NUM + 0), ///< TWI error: Overrun.
|
||||
NRFX_ERROR_DRV_TWI_ERR_ANACK = (NRFX_ERROR_DRIVERS_BASE_NUM + 1), ///< TWI error: Address not acknowledged.
|
||||
NRFX_ERROR_DRV_TWI_ERR_DNACK = (NRFX_ERROR_DRIVERS_BASE_NUM + 2) ///< TWI error: Data not acknowledged.
|
||||
} nrfx_err_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif // !NRFX_CHECK(NRFX_CUSTOM_ERROR_CODES)
|
||||
|
||||
#endif // NRFX_ERRORS_H__
|
||||
340
modules/nrfx/drivers/src/nrfx_adc.c
Normal file
340
modules/nrfx/drivers/src/nrfx_adc.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_ADC_ENABLED)
|
||||
|
||||
#include <nrfx_adc.h>
|
||||
|
||||
#define NRFX_LOG_MODULE ADC
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) (event == NRF_ADC_EVENT_END ? "NRF_ADC_EVENT_END" : "UNKNOWN EVENT")
|
||||
|
||||
typedef struct
|
||||
{
|
||||
nrfx_adc_event_handler_t event_handler;
|
||||
nrfx_adc_channel_t * p_head;
|
||||
nrfx_adc_channel_t * p_current_conv;
|
||||
nrf_adc_value_t * p_buffer;
|
||||
uint16_t size;
|
||||
uint16_t idx;
|
||||
nrfx_drv_state_t state;
|
||||
} adc_cb_t;
|
||||
|
||||
static adc_cb_t m_cb;
|
||||
|
||||
nrfx_err_t nrfx_adc_init(nrfx_adc_config_t const * p_config,
|
||||
nrfx_adc_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrf_adc_event_clear(NRF_ADC_EVENT_END);
|
||||
if (event_handler)
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(ADC_IRQn, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(ADC_IRQn);
|
||||
}
|
||||
m_cb.event_handler = event_handler;
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_adc_uninit(void)
|
||||
{
|
||||
NRFX_IRQ_DISABLE(ADC_IRQn);
|
||||
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
|
||||
nrf_adc_task_trigger(NRF_ADC_TASK_STOP);
|
||||
|
||||
// Disable all channels. This must be done after the interrupt is disabled
|
||||
// because adc_sample_process() dereferences this pointer when it needs to
|
||||
// switch back to the first channel in the list (when the number of samples
|
||||
// to read is bigger than the number of enabled channels).
|
||||
m_cb.p_head = NULL;
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
void nrfx_adc_channel_enable(nrfx_adc_channel_t * const p_channel)
|
||||
{
|
||||
NRFX_ASSERT(!nrfx_adc_is_busy());
|
||||
|
||||
p_channel->p_next = NULL;
|
||||
if (m_cb.p_head == NULL)
|
||||
{
|
||||
m_cb.p_head = p_channel;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrfx_adc_channel_t * p_curr_channel = m_cb.p_head;
|
||||
while (p_curr_channel->p_next != NULL)
|
||||
{
|
||||
NRFX_ASSERT(p_channel != p_curr_channel);
|
||||
p_curr_channel = p_curr_channel->p_next;
|
||||
}
|
||||
p_curr_channel->p_next = p_channel;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Enabled.");
|
||||
}
|
||||
|
||||
void nrfx_adc_channel_disable(nrfx_adc_channel_t * const p_channel)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.p_head);
|
||||
NRFX_ASSERT(!nrfx_adc_is_busy());
|
||||
|
||||
nrfx_adc_channel_t * p_curr_channel = m_cb.p_head;
|
||||
nrfx_adc_channel_t * p_prev_channel = NULL;
|
||||
while (p_curr_channel != p_channel)
|
||||
{
|
||||
p_prev_channel = p_curr_channel;
|
||||
p_curr_channel = p_curr_channel->p_next;
|
||||
NRFX_ASSERT(p_curr_channel != NULL);
|
||||
}
|
||||
if (p_prev_channel)
|
||||
{
|
||||
p_prev_channel->p_next = p_curr_channel->p_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cb.p_head = p_curr_channel->p_next;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Disabled.");
|
||||
}
|
||||
|
||||
void nrfx_adc_all_channels_disable(void)
|
||||
{
|
||||
NRFX_ASSERT(!nrfx_adc_is_busy());
|
||||
|
||||
m_cb.p_head = NULL;
|
||||
}
|
||||
|
||||
void nrfx_adc_sample(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(!nrf_adc_busy_check());
|
||||
nrf_adc_task_trigger(NRF_ADC_TASK_START);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_adc_sample_convert(nrfx_adc_channel_t const * const p_channel,
|
||||
nrf_adc_value_t * p_value)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
if (m_cb.state == NRFX_DRV_STATE_POWERED_ON)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cb.state = NRFX_DRV_STATE_POWERED_ON;
|
||||
|
||||
nrf_adc_init(&p_channel->config);
|
||||
nrf_adc_enable();
|
||||
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
|
||||
nrf_adc_task_trigger(NRF_ADC_TASK_START);
|
||||
if (p_value)
|
||||
{
|
||||
while (!nrf_adc_event_check(NRF_ADC_EVENT_END)) {}
|
||||
nrf_adc_event_clear(NRF_ADC_EVENT_END);
|
||||
*p_value = (nrf_adc_value_t)nrf_adc_result_get();
|
||||
nrf_adc_disable();
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRFX_ASSERT(m_cb.event_handler);
|
||||
m_cb.p_buffer = NULL;
|
||||
nrf_adc_int_enable(NRF_ADC_INT_END_MASK);
|
||||
}
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
|
||||
static bool adc_sample_process()
|
||||
{
|
||||
nrf_adc_event_clear(NRF_ADC_EVENT_END);
|
||||
nrf_adc_disable();
|
||||
m_cb.p_buffer[m_cb.idx] = (nrf_adc_value_t)nrf_adc_result_get();
|
||||
m_cb.idx++;
|
||||
if (m_cb.idx < m_cb.size)
|
||||
{
|
||||
bool task_trigger = false;
|
||||
if (m_cb.p_current_conv->p_next == NULL)
|
||||
{
|
||||
// Make sure the list of channels has not been somehow removed
|
||||
// (it is when all channels are disabled).
|
||||
NRFX_ASSERT(m_cb.p_head);
|
||||
|
||||
m_cb.p_current_conv = m_cb.p_head;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cb.p_current_conv = m_cb.p_current_conv->p_next;
|
||||
task_trigger = true;
|
||||
}
|
||||
nrf_adc_init(&m_cb.p_current_conv->config);
|
||||
nrf_adc_enable();
|
||||
if (task_trigger)
|
||||
{
|
||||
nrf_adc_task_trigger(NRF_ADC_TASK_START);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_adc_buffer_convert(nrf_adc_value_t * buffer, uint16_t size)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
NRFX_LOG_INFO("Number of samples requested to convert: %d.", size);
|
||||
|
||||
if (m_cb.state == NRFX_DRV_STATE_POWERED_ON)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cb.state = NRFX_DRV_STATE_POWERED_ON;
|
||||
m_cb.p_current_conv = m_cb.p_head;
|
||||
m_cb.size = size;
|
||||
m_cb.idx = 0;
|
||||
m_cb.p_buffer = buffer;
|
||||
nrf_adc_init(&m_cb.p_current_conv->config);
|
||||
nrf_adc_event_clear(NRF_ADC_EVENT_END);
|
||||
nrf_adc_enable();
|
||||
if (m_cb.event_handler)
|
||||
{
|
||||
nrf_adc_int_enable(NRF_ADC_INT_END_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
while (!nrf_adc_event_check(NRF_ADC_EVENT_END)){}
|
||||
|
||||
if (adc_sample_process())
|
||||
{
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
|
||||
bool nrfx_adc_is_busy(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
return (m_cb.state == NRFX_DRV_STATE_POWERED_ON) ? true : false;
|
||||
}
|
||||
|
||||
void nrfx_adc_irq_handler(void)
|
||||
{
|
||||
if (m_cb.p_buffer == NULL)
|
||||
{
|
||||
nrf_adc_event_clear(NRF_ADC_EVENT_END);
|
||||
NRFX_LOG_DEBUG("Event: %s.",NRFX_LOG_ERROR_STRING_GET(NRF_ADC_EVENT_END));
|
||||
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
|
||||
nrf_adc_disable();
|
||||
nrfx_adc_evt_t evt;
|
||||
evt.type = NRFX_ADC_EVT_SAMPLE;
|
||||
evt.data.sample.sample = (nrf_adc_value_t)nrf_adc_result_get();
|
||||
NRFX_LOG_DEBUG("ADC data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)(&evt.data.sample.sample), sizeof(nrf_adc_value_t));
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
m_cb.event_handler(&evt);
|
||||
}
|
||||
else if (adc_sample_process())
|
||||
{
|
||||
NRFX_LOG_DEBUG("Event: %s.", NRFX_LOG_ERROR_STRING_GET(NRF_ADC_EVENT_END));
|
||||
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
|
||||
nrfx_adc_evt_t evt;
|
||||
evt.type = NRFX_ADC_EVT_DONE;
|
||||
evt.data.done.p_buffer = m_cb.p_buffer;
|
||||
evt.data.done.size = m_cb.size;
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_DEBUG("ADC data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)m_cb.p_buffer, m_cb.size * sizeof(nrf_adc_value_t));
|
||||
m_cb.event_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_ADC_ENABLED)
|
||||
395
modules/nrfx/drivers/src/nrfx_clock.c
Normal file
395
modules/nrfx/drivers/src/nrfx_clock.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
|
||||
#include <nrfx_clock.h>
|
||||
|
||||
#define NRFX_LOG_MODULE CLOCK
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
extern bool nrfx_power_irq_enabled;
|
||||
#endif
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \
|
||||
(event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \
|
||||
(event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \
|
||||
(event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \
|
||||
"UNKNOWN EVENT"))))
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
#if (NRF_CLOCK_HAS_CALIBRATION == 0)
|
||||
#error "Calibration is not available in the SoC that is used."
|
||||
#endif
|
||||
#if (NRFX_CLOCK_CONFIG_LF_SRC != CLOCK_LFCLKSRC_SRC_RC)
|
||||
#error "Calibration can be performed only for the RC Oscillator."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(USE_WORKAROUND_FOR_ANOMALY_132) && \
|
||||
(defined(NRF52832_XXAA) || defined(NRF52832_XXAB))
|
||||
// ANOMALY 132 - LFCLK needs to avoid frame from 66us to 138us after LFCLK stop. This solution
|
||||
// applies delay of 138us before starting LFCLK.
|
||||
#define USE_WORKAROUND_FOR_ANOMALY_132 1
|
||||
|
||||
// Convert time to cycles (nRF52832 is clocked with 64 MHz, use delay of 138 us).
|
||||
#define ANOMALY_132_DELAY_CYCLES (64UL * 138)
|
||||
#endif
|
||||
|
||||
#if !defined(USE_WORKAROUND_FOR_ANOMALY_192) && \
|
||||
(defined(NRF52810_XXAA) || \
|
||||
defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
|
||||
defined(NRF52840_XXAA))
|
||||
// Enable workaround for nRF52 anomaly 192 (LFRC oscillator frequency is wrong
|
||||
// after calibration, exceeding 500 ppm).
|
||||
#define USE_WORKAROUND_FOR_ANOMALY_192 1
|
||||
#endif
|
||||
|
||||
#if !defined(USE_WORKAROUND_FOR_ANOMALY_201) && \
|
||||
(defined(NRF52810_XXAA) || \
|
||||
defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
|
||||
defined(NRF52840_XXAA))
|
||||
// Enable workaround for nRF52 anomaly 201 (EVENTS_HFCLKSTARTED might be generated twice).
|
||||
#define USE_WORKAROUND_FOR_ANOMALY_201 1
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
typedef enum
|
||||
{
|
||||
CAL_STATE_IDLE,
|
||||
CAL_STATE_CAL
|
||||
} nrfx_clock_cal_state_t;
|
||||
#endif
|
||||
|
||||
/**@brief CLOCK control block. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_clock_event_handler_t event_handler;
|
||||
bool module_initialized; /*< Indicate the state of module */
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
|
||||
bool hfclk_started; /*< Anomaly 201 workaround. */
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
volatile nrfx_clock_cal_state_t cal_state;
|
||||
#endif
|
||||
} nrfx_clock_cb_t;
|
||||
|
||||
static nrfx_clock_cb_t m_clock_cb;
|
||||
|
||||
/**
|
||||
* This variable is used to check whether common POWER_CLOCK common interrupt
|
||||
* should be disabled or not if @ref nrfx_power tries to disable the interrupt.
|
||||
*/
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
bool nrfx_clock_irq_enabled;
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132)
|
||||
/**
|
||||
* @brief Function for applying delay of 138us before starting LFCLK.
|
||||
*/
|
||||
static void nrfx_clock_anomaly_132(void)
|
||||
{
|
||||
uint32_t cyccnt_inital;
|
||||
uint32_t core_debug;
|
||||
uint32_t dwt_ctrl;
|
||||
|
||||
// Preserve DEMCR register to do not influence into its configuration. Enable the trace and
|
||||
// debug blocks. It is required to read and write data to DWT block.
|
||||
core_debug = CoreDebug->DEMCR;
|
||||
CoreDebug->DEMCR = core_debug | CoreDebug_DEMCR_TRCENA_Msk;
|
||||
|
||||
// Preserve CTRL register in DWT block to do not influence into its configuration. Make sure
|
||||
// that cycle counter is enabled.
|
||||
dwt_ctrl = DWT->CTRL;
|
||||
DWT->CTRL = dwt_ctrl | DWT_CTRL_CYCCNTENA_Msk;
|
||||
|
||||
// Store start value of cycle counter.
|
||||
cyccnt_inital = DWT->CYCCNT;
|
||||
|
||||
// Delay required time.
|
||||
while ((DWT->CYCCNT - cyccnt_inital) < ANOMALY_132_DELAY_CYCLES)
|
||||
{}
|
||||
|
||||
// Restore preserved registers.
|
||||
DWT->CTRL = dwt_ctrl;
|
||||
CoreDebug->DEMCR = core_debug;
|
||||
}
|
||||
#endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132)
|
||||
|
||||
nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(event_handler);
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
if (m_clock_cb.module_initialized)
|
||||
{
|
||||
err_code = NRFX_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
m_clock_cb.cal_state = CAL_STATE_IDLE;
|
||||
#endif
|
||||
m_clock_cb.event_handler = event_handler;
|
||||
m_clock_cb.module_initialized = true;
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
|
||||
m_clock_cb.hfclk_started = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_clock_enable(void)
|
||||
{
|
||||
NRFX_ASSERT(m_clock_cb.module_initialized);
|
||||
nrfx_power_clock_irq_init();
|
||||
nrf_clock_lf_src_set((nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC);
|
||||
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
nrfx_clock_irq_enabled = true;
|
||||
#endif
|
||||
|
||||
NRFX_LOG_INFO("Module enabled.");
|
||||
}
|
||||
|
||||
void nrfx_clock_disable(void)
|
||||
{
|
||||
NRFX_ASSERT(m_clock_cb.module_initialized);
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
NRFX_ASSERT(nrfx_clock_irq_enabled);
|
||||
if (!nrfx_power_irq_enabled)
|
||||
#endif
|
||||
{
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(NRF_CLOCK));
|
||||
}
|
||||
nrf_clock_int_disable(CLOCK_INTENSET_HFCLKSTARTED_Msk |
|
||||
CLOCK_INTENSET_LFCLKSTARTED_Msk |
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
CLOCK_INTENSET_DONE_Msk |
|
||||
CLOCK_INTENSET_CTTO_Msk |
|
||||
#endif
|
||||
0);
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
nrfx_clock_irq_enabled = false;
|
||||
#endif
|
||||
NRFX_LOG_INFO("Module disabled.");
|
||||
}
|
||||
|
||||
void nrfx_clock_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_clock_cb.module_initialized);
|
||||
nrfx_clock_lfclk_stop();
|
||||
nrfx_clock_hfclk_stop();
|
||||
m_clock_cb.module_initialized = false;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
void nrfx_clock_lfclk_start(void)
|
||||
{
|
||||
NRFX_ASSERT(m_clock_cb.module_initialized);
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
|
||||
nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK);
|
||||
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132)
|
||||
nrfx_clock_anomaly_132();
|
||||
#endif
|
||||
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
|
||||
}
|
||||
|
||||
void nrfx_clock_lfclk_stop(void)
|
||||
{
|
||||
NRFX_ASSERT(m_clock_cb.module_initialized);
|
||||
|
||||
nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP);
|
||||
while (nrf_clock_lf_is_running())
|
||||
{}
|
||||
}
|
||||
|
||||
void nrfx_clock_hfclk_start(void)
|
||||
{
|
||||
NRFX_ASSERT(m_clock_cb.module_initialized);
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
|
||||
nrf_clock_int_enable(NRF_CLOCK_INT_HF_STARTED_MASK);
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART);
|
||||
}
|
||||
|
||||
void nrfx_clock_hfclk_stop(void)
|
||||
{
|
||||
NRFX_ASSERT(m_clock_cb.module_initialized);
|
||||
|
||||
nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP);
|
||||
while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY))
|
||||
{}
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
|
||||
m_clock_cb.hfclk_started = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_clock_calibration_start(void)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
if (nrfx_clock_hfclk_is_running() == false)
|
||||
{
|
||||
return NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (nrfx_clock_lfclk_is_running() == false)
|
||||
{
|
||||
return NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (m_clock_cb.cal_state == CAL_STATE_IDLE)
|
||||
{
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
|
||||
nrf_clock_int_enable(NRF_CLOCK_INT_DONE_MASK);
|
||||
m_clock_cb.cal_state = CAL_STATE_CAL;
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_192)
|
||||
*(volatile uint32_t *)0x40000C34 = 0x00000002;
|
||||
#endif
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_CAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_clock_is_calibrating(void)
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
if (m_clock_cb.cal_state == CAL_STATE_CAL)
|
||||
{
|
||||
return NRFX_ERROR_BUSY;
|
||||
}
|
||||
#endif
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
void nrfx_clock_calibration_timer_start(uint8_t interval)
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
nrf_clock_cal_timer_timeout_set(interval);
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
|
||||
nrf_clock_int_enable(NRF_CLOCK_INT_CTTO_MASK);
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTART);
|
||||
#endif
|
||||
}
|
||||
|
||||
void nrfx_clock_calibration_timer_stop(void)
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTOP);
|
||||
#endif
|
||||
}
|
||||
|
||||
void nrfx_clock_irq_handler(void)
|
||||
{
|
||||
if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED))
|
||||
{
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED));
|
||||
nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);
|
||||
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
|
||||
if (!m_clock_cb.hfclk_started)
|
||||
{
|
||||
m_clock_cb.hfclk_started = true;
|
||||
m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
|
||||
}
|
||||
#else
|
||||
m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
|
||||
#endif
|
||||
}
|
||||
if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED))
|
||||
{
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED));
|
||||
nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);
|
||||
|
||||
m_clock_cb.event_handler(NRFX_CLOCK_EVT_LFCLK_STARTED);
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO))
|
||||
{
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_CTTO));
|
||||
nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
|
||||
|
||||
m_clock_cb.event_handler(NRFX_CLOCK_EVT_CTTO);
|
||||
}
|
||||
|
||||
if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE))
|
||||
{
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_192)
|
||||
*(volatile uint32_t *)0x40000C34 = 0x00000000;
|
||||
#endif
|
||||
nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_DONE));
|
||||
nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK);
|
||||
m_clock_cb.cal_state = CAL_STATE_IDLE;
|
||||
m_clock_cb.event_handler(NRFX_CLOCK_EVT_CAL_DONE);
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
211
modules/nrfx/drivers/src/nrfx_comp.c
Normal file
211
modules/nrfx/drivers/src/nrfx_comp.c
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_COMP_ENABLED)
|
||||
|
||||
#include <nrfx_comp.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
|
||||
#define NRFX_LOG_MODULE COMP
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_COMP_EVENT_READY ? "NRF_COMP_EVENT_READY" : \
|
||||
(event == NRF_COMP_EVENT_DOWN ? "NRF_COMP_EVENT_DOWN" : \
|
||||
(event == NRF_COMP_EVENT_UP ? "NRF_COMP_EVENT_UP" : \
|
||||
(event == NRF_COMP_EVENT_CROSS ? "NRF_COMP_EVENT_CROSS" : \
|
||||
"UNKNOWN ERROR"))))
|
||||
|
||||
|
||||
static nrfx_comp_event_handler_t m_comp_event_handler = NULL;
|
||||
static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
|
||||
static void comp_execute_handler(nrf_comp_event_t event, uint32_t event_mask)
|
||||
{
|
||||
if (nrf_comp_event_check(event) && nrf_comp_int_enable_check(event_mask))
|
||||
{
|
||||
nrf_comp_event_clear(event);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(event));
|
||||
|
||||
m_comp_event_handler(event);
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_comp_irq_handler(void)
|
||||
{
|
||||
comp_execute_handler(NRF_COMP_EVENT_READY, COMP_INTENSET_READY_Msk);
|
||||
comp_execute_handler(NRF_COMP_EVENT_DOWN, COMP_INTENSET_DOWN_Msk);
|
||||
comp_execute_handler(NRF_COMP_EVENT_UP, COMP_INTENSET_UP_Msk);
|
||||
comp_execute_handler(NRF_COMP_EVENT_CROSS, COMP_INTENSET_CROSS_Msk);
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_comp_init(nrfx_comp_config_t const * p_config,
|
||||
nrfx_comp_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(event_handler);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{ // COMP driver is already initialized
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_comp_event_handler = event_handler;
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
if (nrfx_prs_acquire(NRF_COMP, nrfx_comp_irq_handler) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
nrf_comp_task_trigger(NRF_COMP_TASK_STOP);
|
||||
nrf_comp_enable();
|
||||
|
||||
// Clear events to be sure there are no leftovers.
|
||||
nrf_comp_event_clear(NRF_COMP_EVENT_READY);
|
||||
nrf_comp_event_clear(NRF_COMP_EVENT_DOWN);
|
||||
nrf_comp_event_clear(NRF_COMP_EVENT_UP);
|
||||
nrf_comp_event_clear(NRF_COMP_EVENT_CROSS);
|
||||
|
||||
nrf_comp_ref_set(p_config->reference);
|
||||
|
||||
//If external source is chosen, write to appropriate register.
|
||||
if (p_config->reference == COMP_REFSEL_REFSEL_ARef)
|
||||
{
|
||||
nrf_comp_ext_ref_set(p_config->ext_ref);
|
||||
}
|
||||
|
||||
nrf_comp_th_set(p_config->threshold);
|
||||
nrf_comp_main_mode_set(p_config->main_mode);
|
||||
nrf_comp_speed_mode_set(p_config->speed_mode);
|
||||
nrf_comp_hysteresis_set(p_config->hyst);
|
||||
#if defined (COMP_ISOURCE_ISOURCE_Msk)
|
||||
nrf_comp_isource_set(p_config->isource);
|
||||
#endif
|
||||
nrf_comp_shorts_disable(NRFX_COMP_SHORT_STOP_AFTER_CROSS_EVT |
|
||||
NRFX_COMP_SHORT_STOP_AFTER_UP_EVT |
|
||||
NRFX_COMP_SHORT_STOP_AFTER_DOWN_EVT);
|
||||
nrf_comp_int_disable(COMP_INTENCLR_CROSS_Msk |
|
||||
COMP_INTENCLR_UP_Msk |
|
||||
COMP_INTENCLR_DOWN_Msk |
|
||||
COMP_INTENCLR_READY_Msk);
|
||||
|
||||
nrf_comp_input_select(p_config->input);
|
||||
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(NRF_COMP), p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(NRF_COMP));
|
||||
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_comp_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(NRF_COMP));
|
||||
nrf_comp_disable();
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(NRF_COMP);
|
||||
#endif
|
||||
m_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
m_comp_event_handler = NULL;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
void nrfx_comp_pin_select(nrf_comp_input_t psel)
|
||||
{
|
||||
bool comp_enable_state = nrf_comp_enable_check();
|
||||
nrf_comp_task_trigger(NRF_COMP_TASK_STOP);
|
||||
if (m_state == NRFX_DRV_STATE_POWERED_ON)
|
||||
{
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
}
|
||||
nrf_comp_disable();
|
||||
nrf_comp_input_select(psel);
|
||||
if (comp_enable_state == true)
|
||||
{
|
||||
nrf_comp_enable();
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_comp_start(uint32_t comp_int_mask, uint32_t comp_shorts_mask)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
nrf_comp_int_enable(comp_int_mask);
|
||||
nrf_comp_shorts_enable(comp_shorts_mask);
|
||||
nrf_comp_task_trigger(NRF_COMP_TASK_START);
|
||||
m_state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Enabled.");
|
||||
}
|
||||
|
||||
void nrfx_comp_stop(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
|
||||
nrf_comp_shorts_disable(UINT32_MAX);
|
||||
nrf_comp_int_disable(UINT32_MAX);
|
||||
nrf_comp_task_trigger(NRF_COMP_TASK_STOP);
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Disabled.");
|
||||
}
|
||||
|
||||
uint32_t nrfx_comp_sample()
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
|
||||
nrf_comp_task_trigger(NRF_COMP_TASK_SAMPLE);
|
||||
return nrf_comp_result_get();
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_COMP_ENABLED)
|
||||
319
modules/nrfx/drivers/src/nrfx_dppi.c
Normal file
319
modules/nrfx/drivers/src/nrfx_dppi.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/**
|
||||
* Copyright (c) 2018 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_DPPI_ENABLED)
|
||||
|
||||
#include <nrfx_dppi.h>
|
||||
|
||||
#define NRFX_LOG_MODULE DPPI
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#if !defined(NRFX_DPPI_CHANNELS_USED)
|
||||
// Default mask of DPPI channels reserved for other modules.
|
||||
#define NRFX_DPPI_CHANNELS_USED 0x00000000uL
|
||||
#endif
|
||||
|
||||
#if !defined(NRFX_DPPI_GROUPS_USED)
|
||||
// Default mask of DPPI groups reserved for other modules.
|
||||
#define NRFX_DPPI_GROUPS_USED 0x00000000uL
|
||||
#endif
|
||||
|
||||
#define DPPI_AVAILABLE_CHANNELS_MASK \
|
||||
(((1UL << DPPI_CH_NUM) - 1) & (~NRFX_DPPI_CHANNELS_USED))
|
||||
|
||||
#define DPPI_AVAILABLE_GROUPS_MASK \
|
||||
(((1UL << DPPI_GROUP_NUM) - 1) & (~NRFX_DPPI_GROUPS_USED))
|
||||
|
||||
/** @brief Set bit at given position. */
|
||||
#define DPPI_BIT_SET(pos) (1uL << (pos))
|
||||
|
||||
static uint32_t m_allocated_channels;
|
||||
|
||||
static uint8_t m_allocated_groups;
|
||||
|
||||
__STATIC_INLINE bool channel_is_allocated(uint8_t channel)
|
||||
{
|
||||
return ((m_allocated_channels & DPPI_BIT_SET(channel)) != 0);
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool group_is_allocated(nrf_dppi_channel_group_t group)
|
||||
{
|
||||
return ((m_allocated_groups & DPPI_BIT_SET(group)) != 0);
|
||||
}
|
||||
|
||||
void nrfx_dppi_free(void)
|
||||
{
|
||||
uint32_t mask = m_allocated_groups;
|
||||
nrf_dppi_channel_group_t group = NRF_DPPI_CHANNEL_GROUP0;
|
||||
|
||||
// Disable all channels
|
||||
nrf_dppi_channels_disable(NRF_DPPIC, m_allocated_channels);
|
||||
|
||||
// Clear all groups configurations
|
||||
while (mask)
|
||||
{
|
||||
if (mask & DPPI_BIT_SET(group))
|
||||
{
|
||||
nrf_dppi_group_clear(NRF_DPPIC, group);
|
||||
mask &= ~DPPI_BIT_SET(group);
|
||||
}
|
||||
group++;
|
||||
}
|
||||
|
||||
// Clear all allocated channels.
|
||||
m_allocated_channels = 0;
|
||||
|
||||
// Clear all allocated groups.
|
||||
m_allocated_groups = 0;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_channel_alloc(uint8_t * p_channel)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
|
||||
// Get mask of available DPPI channels
|
||||
uint32_t remaining_channels = DPPI_AVAILABLE_CHANNELS_MASK & ~(m_allocated_channels);
|
||||
uint8_t channel = 0;
|
||||
|
||||
if (!remaining_channels)
|
||||
{
|
||||
err_code = NRFX_ERROR_NO_MEM;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// Find first free channel
|
||||
while (!(remaining_channels & DPPI_BIT_SET(channel)))
|
||||
{
|
||||
channel++;
|
||||
}
|
||||
|
||||
m_allocated_channels |= DPPI_BIT_SET(channel);
|
||||
*p_channel = channel;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Allocated channel: %d.", channel);
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_channel_free(uint8_t channel)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!channel_is_allocated(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
// First disable this channel
|
||||
nrf_dppi_channels_disable(NRF_DPPIC, DPPI_BIT_SET(channel));
|
||||
// Clear channel allocated indication.
|
||||
m_allocated_channels &= ~DPPI_BIT_SET(channel);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_channel_enable(uint8_t channel)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!channel_is_allocated(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_channels_enable(NRF_DPPIC, DPPI_BIT_SET(channel));
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_channel_disable(uint8_t channel)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!channel_is_allocated(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_channels_disable(NRF_DPPIC, DPPI_BIT_SET(channel));
|
||||
err_code = NRFX_SUCCESS;
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_group_alloc(nrf_dppi_channel_group_t * p_group)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
|
||||
// Get mask of available DPPI groups
|
||||
uint32_t remaining_groups = DPPI_AVAILABLE_GROUPS_MASK & ~(m_allocated_groups);
|
||||
nrf_dppi_channel_group_t group = NRF_DPPI_CHANNEL_GROUP0;
|
||||
|
||||
if (!remaining_groups)
|
||||
{
|
||||
err_code = NRFX_ERROR_NO_MEM;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// Find first free group
|
||||
while (!(remaining_groups & DPPI_BIT_SET(group)))
|
||||
{
|
||||
group++;
|
||||
}
|
||||
|
||||
m_allocated_groups |= DPPI_BIT_SET(group);
|
||||
*p_group = group;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Allocated channel: %d.", group);
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_group_free(nrf_dppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!group_is_allocated(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_group_disable(NRF_DPPIC, group);
|
||||
// Set bit value to zero at position corresponding to the group number.
|
||||
m_allocated_groups &= ~DPPI_BIT_SET(group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_channel_include_in_group(uint8_t channel,
|
||||
nrf_dppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!group_is_allocated(group) || !channel_is_allocated(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_channels_include_in_group(NRF_DPPIC, DPPI_BIT_SET(channel), group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_channel_remove_from_group(uint8_t channel,
|
||||
nrf_dppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!group_is_allocated(group) || !channel_is_allocated(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_channels_remove_from_group(NRF_DPPIC, DPPI_BIT_SET(channel), group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_group_clear(nrf_dppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!group_is_allocated(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_channels_remove_from_group(NRF_DPPIC, DPPI_AVAILABLE_CHANNELS_MASK, group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_group_enable(nrf_dppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!group_is_allocated(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_group_enable(NRF_DPPIC, group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_dppi_group_disable(nrf_dppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!group_is_allocated(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dppi_group_disable(NRF_DPPIC, group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_DPPI_ENABLED)
|
||||
934
modules/nrfx/drivers/src/nrfx_gpiote.c
Normal file
934
modules/nrfx/drivers/src/nrfx_gpiote.c
Normal file
@@ -0,0 +1,934 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_GPIOTE_ENABLED)
|
||||
|
||||
#include <nrfx_gpiote.h>
|
||||
#include "nrf_bitmask.h"
|
||||
#include <string.h>
|
||||
|
||||
#define NRFX_LOG_MODULE GPIOTE
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#if (GPIO_COUNT == 1)
|
||||
#define MAX_PIN_NUMBER 32
|
||||
#elif (GPIO_COUNT == 2)
|
||||
#define MAX_PIN_NUMBER (32 + P1_PIN_NUM)
|
||||
#else
|
||||
#error "Not supported."
|
||||
#endif
|
||||
|
||||
#define FORBIDDEN_HANDLER_ADDRESS ((nrfx_gpiote_evt_handler_t)UINT32_MAX)
|
||||
#define PIN_NOT_USED (-1)
|
||||
#define PIN_USED (-2)
|
||||
#define NO_CHANNELS (-1)
|
||||
#define POLARITY_FIELD_POS (6)
|
||||
#define POLARITY_FIELD_MASK (0xC0)
|
||||
|
||||
/* Check if every pin can be encoded on provided number of bits. */
|
||||
NRFX_STATIC_ASSERT(MAX_PIN_NUMBER <= (1 << POLARITY_FIELD_POS));
|
||||
|
||||
/**
|
||||
* @brief Macro for converting task-event index to an address of an event register.
|
||||
*
|
||||
* Macro utilizes the fact that registers are grouped together in ascending order.
|
||||
*/
|
||||
#define TE_IDX_TO_EVENT_ADDR(idx) (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0 + \
|
||||
(sizeof(uint32_t) * (idx)))
|
||||
|
||||
/**
|
||||
* @brief Macro for converting task-event index of OUT task to an address of a task register.
|
||||
*
|
||||
* Macro utilizes the fact that registers are grouped together in ascending order.
|
||||
*/
|
||||
#define TE_OUT_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0 + \
|
||||
(sizeof(uint32_t) * (idx)))
|
||||
|
||||
#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Macro for converting task-event index of SET task to an address of a task register.
|
||||
*
|
||||
* Macro utilizes the fact that registers are grouped together in ascending order.
|
||||
*/
|
||||
#define TE_SET_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_SET_0 + \
|
||||
(sizeof(uint32_t) * (idx)))
|
||||
|
||||
#endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
/**
|
||||
* @brief Macro for converting task-event index of CLR task to an address of a task register.
|
||||
*
|
||||
* Macro utilizes the fact that registers are grouped together in ascending order.
|
||||
*/
|
||||
#define TE_CLR_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_CLR_0 + \
|
||||
(sizeof(uint32_t) * (idx)))
|
||||
|
||||
#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
|
||||
|
||||
/*lint -save -e571*/ /* Suppress "Warning 571: Suspicious cast" */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_gpiote_evt_handler_t handlers[GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
|
||||
int8_t pin_assignments[MAX_PIN_NUMBER];
|
||||
int8_t port_handlers_pins[NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
|
||||
uint8_t configured_pins[((MAX_PIN_NUMBER)+7) / 8];
|
||||
nrfx_drv_state_t state;
|
||||
} gpiote_control_block_t;
|
||||
|
||||
static gpiote_control_block_t m_cb;
|
||||
|
||||
__STATIC_INLINE bool pin_in_use(uint32_t pin)
|
||||
{
|
||||
return (m_cb.pin_assignments[pin] != PIN_NOT_USED);
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
|
||||
{
|
||||
return (m_cb.pin_assignments[pin] == PIN_USED);
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
|
||||
{
|
||||
return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < GPIOTE_CH_NUM) ?
|
||||
true : false;
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
|
||||
{
|
||||
return (m_cb.pin_assignments[pin] >= GPIOTE_CH_NUM);
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
|
||||
{
|
||||
return (m_cb.pin_assignments[pin] >= 0);
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin,
|
||||
uint32_t channel_id,
|
||||
nrfx_gpiote_evt_handler_t handler,
|
||||
bool is_channel)
|
||||
{
|
||||
m_cb.pin_assignments[pin] = channel_id;
|
||||
m_cb.handlers[channel_id] = handler;
|
||||
if (!is_channel)
|
||||
{
|
||||
m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)pin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE void pin_in_use_set(uint32_t pin)
|
||||
{
|
||||
m_cb.pin_assignments[pin] = PIN_USED;
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE void pin_in_use_clear(uint32_t pin)
|
||||
{
|
||||
m_cb.pin_assignments[pin] = PIN_NOT_USED;
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE void pin_configured_set(uint32_t pin)
|
||||
{
|
||||
nrf_bitmask_bit_set(pin, m_cb.configured_pins);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void pin_configured_clear(uint32_t pin)
|
||||
{
|
||||
nrf_bitmask_bit_clear(pin, m_cb.configured_pins);
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool pin_configured_check(uint32_t pin)
|
||||
{
|
||||
return 0 != nrf_bitmask_bit_is_set(pin, m_cb.configured_pins);
|
||||
}
|
||||
|
||||
__STATIC_INLINE int8_t channel_port_get(uint32_t pin)
|
||||
{
|
||||
return m_cb.pin_assignments[pin];
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE nrfx_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
|
||||
{
|
||||
return m_cb.handlers[channel];
|
||||
}
|
||||
|
||||
static nrfx_gpiote_pin_t port_handler_pin_get(uint32_t handler_idx)
|
||||
{
|
||||
uint8_t pin_and_polarity = (uint8_t)m_cb.port_handlers_pins[handler_idx];
|
||||
return (nrfx_gpiote_pin_t)(pin_and_polarity & ~POLARITY_FIELD_MASK);
|
||||
}
|
||||
|
||||
static nrf_gpiote_polarity_t port_handler_polarity_get(uint32_t handler_idx)
|
||||
{
|
||||
uint8_t pin_and_polarity = (uint8_t)m_cb.port_handlers_pins[handler_idx];
|
||||
return (nrf_gpiote_polarity_t)((pin_and_polarity & POLARITY_FIELD_MASK) >> POLARITY_FIELD_POS);
|
||||
}
|
||||
|
||||
static int8_t channel_port_alloc(uint32_t pin, nrfx_gpiote_evt_handler_t handler, bool channel)
|
||||
{
|
||||
int8_t channel_id = NO_CHANNELS;
|
||||
uint32_t i;
|
||||
|
||||
uint32_t start_idx = channel ? 0 : GPIOTE_CH_NUM;
|
||||
uint32_t end_idx =
|
||||
channel ? GPIOTE_CH_NUM : (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
|
||||
|
||||
// critical section
|
||||
|
||||
for (i = start_idx; i < end_idx; i++)
|
||||
{
|
||||
if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
|
||||
{
|
||||
pin_in_use_by_te_set(pin, i, handler, channel);
|
||||
channel_id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// critical section
|
||||
return channel_id;
|
||||
}
|
||||
|
||||
|
||||
static void channel_free(uint8_t channel_id)
|
||||
{
|
||||
m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
|
||||
if (channel_id >= GPIOTE_CH_NUM)
|
||||
{
|
||||
m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)PIN_NOT_USED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_gpiote_init(void)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < MAX_PIN_NUMBER; i++)
|
||||
{
|
||||
if (nrf_gpio_pin_present_check(i))
|
||||
{
|
||||
pin_in_use_clear(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
|
||||
{
|
||||
channel_free(i);
|
||||
}
|
||||
|
||||
memset(m_cb.configured_pins, 0, sizeof(m_cb.configured_pins));
|
||||
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(NRF_GPIOTE), NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(NRF_GPIOTE));
|
||||
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
|
||||
nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
bool nrfx_gpiote_is_init(void)
|
||||
{
|
||||
return (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_PIN_NUMBER; i++)
|
||||
{
|
||||
if (nrf_gpio_pin_present_check(i))
|
||||
{
|
||||
if (pin_in_use_as_non_task_out(i))
|
||||
{
|
||||
nrfx_gpiote_out_uninit(i);
|
||||
}
|
||||
else if (pin_in_use_by_gpiote(i))
|
||||
{
|
||||
/* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on
|
||||
* so it can be called on all pins used by GPIOTE.
|
||||
*/
|
||||
nrfx_gpiote_in_uninit(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin,
|
||||
nrfx_gpiote_out_config_t const * p_config)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
|
||||
NRFX_ASSERT(p_config);
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (pin_in_use(pin))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p_config->task_pin)
|
||||
{
|
||||
int8_t channel = channel_port_alloc(pin, NULL, true);
|
||||
|
||||
if (channel != NO_CHANNELS)
|
||||
{
|
||||
nrf_gpiote_task_configure((uint32_t)channel,
|
||||
pin,
|
||||
p_config->action,
|
||||
p_config->init_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
err_code = NRFX_ERROR_NO_MEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pin_in_use_set(pin);
|
||||
}
|
||||
|
||||
if (err_code == NRFX_SUCCESS)
|
||||
{
|
||||
if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
|
||||
{
|
||||
nrf_gpio_pin_set(pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_clear(pin);
|
||||
}
|
||||
|
||||
nrf_gpio_cfg_output(pin);
|
||||
pin_configured_set(pin);
|
||||
}
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
|
||||
if (pin_in_use_by_te(pin))
|
||||
{
|
||||
channel_free((uint8_t)channel_port_get(pin));
|
||||
nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
|
||||
}
|
||||
pin_in_use_clear(pin);
|
||||
|
||||
if (pin_configured_check(pin))
|
||||
{
|
||||
nrf_gpio_cfg_default(pin);
|
||||
pin_configured_clear(pin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(!pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpio_pin_set(pin);
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(!pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpio_pin_clear(pin);
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(!pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpio_pin_toggle(pin);
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpiote_task_enable((uint32_t)m_cb.pin_assignments[pin]);
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpiote_task_disable((uint32_t)m_cb.pin_assignments[pin]);
|
||||
}
|
||||
|
||||
|
||||
nrf_gpiote_tasks_t nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
return TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
nrf_gpiote_tasks_t task = nrfx_gpiote_out_task_get(pin);
|
||||
return nrf_gpiote_task_addr_get(task);
|
||||
}
|
||||
|
||||
|
||||
#if defined(GPIOTE_FEATURE_SET_PRESENT)
|
||||
nrf_gpiote_tasks_t nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
return TE_SET_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
nrf_gpiote_tasks_t task = nrfx_gpiote_set_task_get(pin);
|
||||
return nrf_gpiote_task_addr_get(task);
|
||||
}
|
||||
#endif // defined(GPIOTE_FEATURE_SET_PRESENT)
|
||||
|
||||
|
||||
#if defined(GPIOTE_FEATURE_CLR_PRESENT)
|
||||
nrf_gpiote_tasks_t nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
return TE_CLR_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
nrf_gpiote_tasks_t task = nrfx_gpiote_clr_task_get(pin);
|
||||
return nrf_gpiote_task_addr_get(task);
|
||||
}
|
||||
#endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
|
||||
|
||||
|
||||
void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpiote_outinit_t init_val =
|
||||
state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
|
||||
nrf_gpiote_task_force((uint32_t)m_cb.pin_assignments[pin], init_val);
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
|
||||
nrf_gpiote_task_set(task);
|
||||
}
|
||||
|
||||
|
||||
#if defined(GPIOTE_FEATURE_SET_PRESENT)
|
||||
void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpiote_tasks_t task = TE_SET_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
|
||||
nrf_gpiote_task_set(task);
|
||||
}
|
||||
|
||||
|
||||
#endif // defined(GPIOTE_FEATURE_SET_PRESENT)
|
||||
|
||||
#if defined(GPIOTE_FEATURE_CLR_PRESENT)
|
||||
void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_te(pin));
|
||||
|
||||
nrf_gpiote_tasks_t task = TE_CLR_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
|
||||
nrf_gpiote_task_set(task);
|
||||
}
|
||||
|
||||
|
||||
#endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
|
||||
|
||||
nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,
|
||||
nrfx_gpiote_in_config_t const * p_config,
|
||||
nrfx_gpiote_evt_handler_t evt_handler)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
/* Only one GPIOTE channel can be assigned to one physical pin. */
|
||||
if (pin_in_use_by_gpiote(pin))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
|
||||
if (channel != NO_CHANNELS)
|
||||
{
|
||||
if (!p_config->skip_gpio_setup)
|
||||
{
|
||||
if (p_config->is_watcher)
|
||||
{
|
||||
nrf_gpio_cfg_watcher(pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_cfg_input(pin, p_config->pull);
|
||||
}
|
||||
pin_configured_set(pin);
|
||||
}
|
||||
|
||||
if (p_config->hi_accuracy)
|
||||
{
|
||||
nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] |= (p_config->sense) <<
|
||||
POLARITY_FIELD_POS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err_code = NRFX_ERROR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_gpiote(pin));
|
||||
if (pin_in_use_by_port(pin))
|
||||
{
|
||||
nrf_gpiote_polarity_t polarity =
|
||||
port_handler_polarity_get(channel_port_get(pin) - GPIOTE_CH_NUM);
|
||||
nrf_gpio_pin_sense_t sense;
|
||||
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
|
||||
{
|
||||
/* read current pin state and set for next sense to oposit */
|
||||
sense = (nrf_gpio_pin_read(pin)) ?
|
||||
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
|
||||
NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
|
||||
}
|
||||
nrf_gpio_cfg_sense_set(pin, sense);
|
||||
}
|
||||
else if (pin_in_use_by_te(pin))
|
||||
{
|
||||
int32_t channel = (int32_t)channel_port_get(pin);
|
||||
nrf_gpiote_events_t event = TE_IDX_TO_EVENT_ADDR((uint32_t)channel);
|
||||
|
||||
nrf_gpiote_event_enable((uint32_t)channel);
|
||||
|
||||
nrf_gpiote_event_clear(event);
|
||||
if (int_enable)
|
||||
{
|
||||
nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
|
||||
// Enable the interrupt only if event handler was provided.
|
||||
if (handler)
|
||||
{
|
||||
nrf_gpiote_int_enable(1 << channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_gpiote(pin));
|
||||
if (pin_in_use_by_port(pin))
|
||||
{
|
||||
nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
|
||||
}
|
||||
else if (pin_in_use_by_te(pin))
|
||||
{
|
||||
int32_t channel = (int32_t)channel_port_get(pin);
|
||||
nrf_gpiote_event_disable((uint32_t)channel);
|
||||
nrf_gpiote_int_disable(1 << channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_gpiote(pin));
|
||||
nrfx_gpiote_in_event_disable(pin);
|
||||
if (pin_in_use_by_te(pin))
|
||||
{
|
||||
nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
|
||||
}
|
||||
if (pin_configured_check(pin))
|
||||
{
|
||||
nrf_gpio_cfg_default(pin);
|
||||
pin_configured_clear(pin);
|
||||
}
|
||||
channel_free((uint8_t)channel_port_get(pin));
|
||||
pin_in_use_clear(pin);
|
||||
}
|
||||
|
||||
|
||||
bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
return nrf_gpio_pin_read(pin) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
nrf_gpiote_events_t nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
|
||||
NRFX_ASSERT(pin_in_use_by_port(pin) || pin_in_use_by_te(pin));
|
||||
|
||||
if (pin_in_use_by_te(pin))
|
||||
{
|
||||
return TE_IDX_TO_EVENT_ADDR((uint32_t)channel_port_get(pin));
|
||||
}
|
||||
|
||||
return NRF_GPIOTE_EVENTS_PORT;
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin)
|
||||
{
|
||||
nrf_gpiote_events_t event = nrfx_gpiote_in_event_get(pin);
|
||||
return nrf_gpiote_event_addr_get(event);
|
||||
}
|
||||
|
||||
#if defined(NRF_GPIO_LATCH_PRESENT)
|
||||
static bool latch_pending_read_and_check(uint32_t * latch)
|
||||
{
|
||||
nrf_gpio_latches_read_and_clear(0, GPIO_COUNT, latch);
|
||||
|
||||
for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
|
||||
{
|
||||
if (latch[port_idx])
|
||||
{
|
||||
/* If any of the latch bits is still set, it means another edge has been captured
|
||||
* before or during the interrupt processing. Therefore event-processing loop
|
||||
* should be executed again. */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void port_event_handle(uint32_t * latch)
|
||||
{
|
||||
do {
|
||||
for (uint32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
|
||||
{
|
||||
if (m_cb.port_handlers_pins[i] == PIN_NOT_USED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Process pin further only if LATCH bit associated with this pin was set. */
|
||||
nrfx_gpiote_pin_t pin = port_handler_pin_get(i);
|
||||
if (nrf_bitmask_bit_is_set(pin, latch))
|
||||
{
|
||||
nrf_gpiote_polarity_t polarity = port_handler_polarity_get(i);
|
||||
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
|
||||
|
||||
NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);
|
||||
|
||||
/* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
|
||||
* can be deasserted. Therefore PORT event generated again,
|
||||
* unless some other PINx.DETECT signal is still active. */
|
||||
nrf_gpio_pin_sense_t next_sense =
|
||||
(sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW :
|
||||
NRF_GPIO_PIN_SENSE_HIGH;
|
||||
nrf_gpio_cfg_sense_set(pin, next_sense);
|
||||
|
||||
/* Try to clear LATCH bit corresponding to currently processed pin.
|
||||
* This may not succeed if the pin's state changed during the interrupt processing
|
||||
* and now it matches the new sense configuration. In such case,
|
||||
* the pin will be processed again in another iteration of the outer loop. */
|
||||
nrf_gpio_pin_latch_clear(pin);
|
||||
|
||||
/* Invoke user handler only if the sensed pin level
|
||||
* matches its polarity configuration. */
|
||||
nrfx_gpiote_evt_handler_t handler =
|
||||
channel_handler_get((uint32_t)channel_port_get(pin));
|
||||
if (handler &&
|
||||
((polarity == NRF_GPIOTE_POLARITY_TOGGLE) ||
|
||||
(sense == NRF_GPIO_PIN_SENSE_HIGH && polarity == NRF_GPIOTE_POLARITY_LOTOHI) ||
|
||||
(sense == NRF_GPIO_PIN_SENSE_LOW && polarity == NRF_GPIOTE_POLARITY_HITOLO)))
|
||||
{
|
||||
handler(pin, polarity);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (latch_pending_read_and_check(latch));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool input_read_and_check(uint32_t * input, uint32_t * pins_to_check)
|
||||
{
|
||||
bool process_inputs_again;
|
||||
uint32_t new_input[GPIO_COUNT];
|
||||
|
||||
nrf_gpio_ports_read(0, GPIO_COUNT, new_input);
|
||||
|
||||
process_inputs_again = false;
|
||||
for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
|
||||
{
|
||||
/* Execute XOR to find out which inputs have changed. */
|
||||
uint32_t input_diff = input[port_idx] ^ new_input[port_idx];
|
||||
input[port_idx] = new_input[port_idx];
|
||||
if (input_diff)
|
||||
{
|
||||
/* If any differences among inputs were found, mark those pins
|
||||
* to be processed again. */
|
||||
pins_to_check[port_idx] = input_diff;
|
||||
process_inputs_again = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pins_to_check[port_idx] = 0;
|
||||
}
|
||||
}
|
||||
return process_inputs_again;
|
||||
}
|
||||
|
||||
static void port_event_handle(uint32_t * input)
|
||||
{
|
||||
uint32_t pins_to_check[GPIO_COUNT];
|
||||
|
||||
for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
|
||||
{
|
||||
pins_to_check[port_idx] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
do {
|
||||
for (uint32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
|
||||
{
|
||||
if (m_cb.port_handlers_pins[i] == PIN_NOT_USED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
nrfx_gpiote_pin_t pin = port_handler_pin_get(i);
|
||||
if (nrf_bitmask_bit_is_set(pin, pins_to_check))
|
||||
{
|
||||
nrf_gpiote_polarity_t polarity = port_handler_polarity_get(i);
|
||||
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
|
||||
bool pin_state = nrf_bitmask_bit_is_set(pin, input);
|
||||
|
||||
/* Process pin further only if its state matches its sense level. */
|
||||
if ((pin_state && (sense == NRF_GPIO_PIN_SENSE_HIGH)) ||
|
||||
(!pin_state && (sense == NRF_GPIO_PIN_SENSE_LOW)) )
|
||||
{
|
||||
/* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
|
||||
* can be deasserted. Therefore PORT event can be generated again,
|
||||
* unless some other PINx.DETECT signal is still active. */
|
||||
NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);
|
||||
nrf_gpio_pin_sense_t next_sense =
|
||||
(sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW :
|
||||
NRF_GPIO_PIN_SENSE_HIGH;
|
||||
nrf_gpio_cfg_sense_set(pin, next_sense);
|
||||
|
||||
/* Invoke user handler only if the sensed pin level
|
||||
* matches its polarity configuration. */
|
||||
nrfx_gpiote_evt_handler_t handler =
|
||||
channel_handler_get((uint32_t)channel_port_get(pin));
|
||||
if (handler &&
|
||||
((polarity == NRF_GPIOTE_POLARITY_TOGGLE) ||
|
||||
(sense == NRF_GPIO_PIN_SENSE_HIGH &&
|
||||
polarity == NRF_GPIOTE_POLARITY_LOTOHI) ||
|
||||
(sense == NRF_GPIO_PIN_SENSE_LOW &&
|
||||
polarity == NRF_GPIOTE_POLARITY_HITOLO)))
|
||||
{
|
||||
handler(pin, polarity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (input_read_and_check(input, pins_to_check));
|
||||
}
|
||||
#endif // defined(NRF_GPIO_LATCH_PRESENT)
|
||||
|
||||
void nrfx_gpiote_irq_handler(void)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
uint32_t input[GPIO_COUNT] = {0};
|
||||
|
||||
/* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
|
||||
uint32_t i;
|
||||
nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;
|
||||
uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
|
||||
|
||||
for (i = 0; i < GPIOTE_CH_NUM; i++)
|
||||
{
|
||||
if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask))
|
||||
{
|
||||
nrf_gpiote_event_clear(event);
|
||||
status |= mask;
|
||||
}
|
||||
mask <<= 1;
|
||||
/* Incrementing to next event, utilizing the fact that events are grouped together
|
||||
* in ascending order. */
|
||||
event = (nrf_gpiote_events_t)((uint32_t)event + sizeof(uint32_t));
|
||||
}
|
||||
|
||||
/* collect PORT status event, if event is set read pins state. Processing is postponed to the
|
||||
* end of interrupt. */
|
||||
if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
|
||||
{
|
||||
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
|
||||
status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
|
||||
#if defined(NRF_GPIO_LATCH_PRESENT)
|
||||
nrf_gpio_latches_read_and_clear(0, GPIO_COUNT, input);
|
||||
#else
|
||||
nrf_gpio_ports_read(0, GPIO_COUNT, input);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Process pin events. */
|
||||
if (status & NRF_GPIOTE_INT_IN_MASK)
|
||||
{
|
||||
mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
|
||||
|
||||
for (i = 0; i < GPIOTE_CH_NUM; i++)
|
||||
{
|
||||
if (mask & status)
|
||||
{
|
||||
nrfx_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
|
||||
NRFX_LOG_DEBUG("Event in number: %d.", i);
|
||||
nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);
|
||||
nrfx_gpiote_evt_handler_t handler = channel_handler_get(i);
|
||||
NRFX_LOG_DEBUG("Pin: %d, polarity: %d.", pin, polarity);
|
||||
if (handler)
|
||||
{
|
||||
handler(pin, polarity);
|
||||
}
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process PORT event. */
|
||||
if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
|
||||
{
|
||||
port_event_handle(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*lint -restore*/
|
||||
#endif // NRFX_CHECK(NRFX_GPIOTE_ENABLED)
|
||||
445
modules/nrfx/drivers/src/nrfx_i2s.c
Normal file
445
modules/nrfx/drivers/src/nrfx_i2s.c
Normal file
@@ -0,0 +1,445 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_I2S_ENABLED)
|
||||
|
||||
#include <nrfx_i2s.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE I2S
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_I2S_EVENT_RXPTRUPD ? "NRF_I2S_EVENT_RXPTRUPD" : \
|
||||
(event == NRF_I2S_EVENT_TXPTRUPD ? "NRF_I2S_EVENT_TXPTRUPD" : \
|
||||
(event == NRF_I2S_EVENT_STOPPED ? "NRF_I2S_EVENT_STOPPED" : \
|
||||
"UNKNOWN EVENT")))
|
||||
|
||||
#if !defined(USE_WORKAROUND_FOR_I2S_STOP_ANOMALY) && \
|
||||
(defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || defined(NRF52840_XXAA) || \
|
||||
defined(NRF9160_XXAA))
|
||||
// Enable workaround for nRF52832 and nRF52840 anomaly 194 / nrf9160 anomaly 1
|
||||
// (STOP task does not switch off all resources).
|
||||
#define USE_WORKAROUND_FOR_I2S_STOP_ANOMALY 1
|
||||
#endif
|
||||
|
||||
// Control block - driver instance local data.
|
||||
typedef struct
|
||||
{
|
||||
nrfx_i2s_data_handler_t handler;
|
||||
nrfx_drv_state_t state;
|
||||
|
||||
bool use_rx : 1;
|
||||
bool use_tx : 1;
|
||||
bool rx_ready : 1;
|
||||
bool tx_ready : 1;
|
||||
bool buffers_needed : 1;
|
||||
bool buffers_reused : 1;
|
||||
|
||||
uint16_t buffer_size;
|
||||
nrfx_i2s_buffers_t next_buffers;
|
||||
nrfx_i2s_buffers_t current_buffers;
|
||||
} i2s_control_block_t;
|
||||
static i2s_control_block_t m_cb;
|
||||
|
||||
|
||||
static void configure_pins(nrfx_i2s_config_t const * p_config)
|
||||
{
|
||||
uint32_t mck_pin, sdout_pin, sdin_pin;
|
||||
|
||||
// Configure pins used by the peripheral:
|
||||
|
||||
// - SCK and LRCK (required) - depending on the mode of operation these
|
||||
// pins are configured as outputs (in Master mode) or inputs (in Slave
|
||||
// mode).
|
||||
if (p_config->mode == NRF_I2S_MODE_MASTER)
|
||||
{
|
||||
nrf_gpio_cfg_output(p_config->sck_pin);
|
||||
nrf_gpio_cfg_output(p_config->lrck_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_cfg_input(p_config->sck_pin, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_cfg_input(p_config->lrck_pin, NRF_GPIO_PIN_NOPULL);
|
||||
}
|
||||
|
||||
// - MCK (optional) - always output,
|
||||
if (p_config->mck_pin != NRFX_I2S_PIN_NOT_USED)
|
||||
{
|
||||
mck_pin = p_config->mck_pin;
|
||||
nrf_gpio_cfg_output(mck_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
mck_pin = NRF_I2S_PIN_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
// - SDOUT (optional) - always output,
|
||||
if (p_config->sdout_pin != NRFX_I2S_PIN_NOT_USED)
|
||||
{
|
||||
sdout_pin = p_config->sdout_pin;
|
||||
nrf_gpio_cfg_output(sdout_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
sdout_pin = NRF_I2S_PIN_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
// - SDIN (optional) - always input.
|
||||
if (p_config->sdin_pin != NRFX_I2S_PIN_NOT_USED)
|
||||
{
|
||||
sdin_pin = p_config->sdin_pin;
|
||||
nrf_gpio_cfg_input(sdin_pin, NRF_GPIO_PIN_NOPULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
sdin_pin = NRF_I2S_PIN_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
nrf_i2s_pins_set(NRF_I2S,
|
||||
p_config->sck_pin,
|
||||
p_config->lrck_pin,
|
||||
mck_pin,
|
||||
sdout_pin,
|
||||
sdin_pin);
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_i2s_init(nrfx_i2s_config_t const * p_config,
|
||||
nrfx_i2s_data_handler_t handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(handler);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (!nrf_i2s_configure(NRF_I2S,
|
||||
p_config->mode,
|
||||
p_config->format,
|
||||
p_config->alignment,
|
||||
p_config->sample_width,
|
||||
p_config->channels,
|
||||
p_config->mck_setup,
|
||||
p_config->ratio))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
configure_pins(p_config);
|
||||
|
||||
m_cb.handler = handler;
|
||||
|
||||
NRFX_IRQ_PRIORITY_SET(I2S_IRQn, p_config->irq_priority);
|
||||
NRFX_IRQ_ENABLE(I2S_IRQn);
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
NRFX_LOG_INFO("Initialized.");
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_i2s_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
nrfx_i2s_stop();
|
||||
|
||||
NRFX_IRQ_DISABLE(I2S_IRQn);
|
||||
|
||||
nrf_i2s_pins_set(NRF_I2S,
|
||||
NRF_I2S_PIN_NOT_CONNECTED,
|
||||
NRF_I2S_PIN_NOT_CONNECTED,
|
||||
NRF_I2S_PIN_NOT_CONNECTED,
|
||||
NRF_I2S_PIN_NOT_CONNECTED,
|
||||
NRF_I2S_PIN_NOT_CONNECTED);
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_i2s_start(nrfx_i2s_buffers_t const * p_initial_buffers,
|
||||
uint16_t buffer_size,
|
||||
uint8_t flags)
|
||||
{
|
||||
NRFX_ASSERT(p_initial_buffers != NULL);
|
||||
NRFX_ASSERT(p_initial_buffers->p_rx_buffer != NULL ||
|
||||
p_initial_buffers->p_tx_buffer != NULL);
|
||||
NRFX_ASSERT((p_initial_buffers->p_rx_buffer == NULL) ||
|
||||
(nrfx_is_in_ram(p_initial_buffers->p_rx_buffer) &&
|
||||
nrfx_is_word_aligned(p_initial_buffers->p_rx_buffer)));
|
||||
NRFX_ASSERT((p_initial_buffers->p_tx_buffer == NULL) ||
|
||||
(nrfx_is_in_ram(p_initial_buffers->p_tx_buffer) &&
|
||||
nrfx_is_word_aligned(p_initial_buffers->p_tx_buffer)));
|
||||
NRFX_ASSERT(buffer_size != 0);
|
||||
(void)(flags);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_cb.state != NRFX_DRV_STATE_INITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (((p_initial_buffers->p_rx_buffer != NULL)
|
||||
&& !nrfx_is_in_ram(p_initial_buffers->p_rx_buffer))
|
||||
||
|
||||
((p_initial_buffers->p_tx_buffer != NULL)
|
||||
&& !nrfx_is_in_ram(p_initial_buffers->p_tx_buffer)))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_cb.use_rx = (p_initial_buffers->p_rx_buffer != NULL);
|
||||
m_cb.use_tx = (p_initial_buffers->p_tx_buffer != NULL);
|
||||
m_cb.rx_ready = false;
|
||||
m_cb.tx_ready = false;
|
||||
m_cb.buffers_needed = false;
|
||||
m_cb.buffer_size = buffer_size;
|
||||
|
||||
// Set the provided initial buffers as next, they will become the current
|
||||
// ones after the IRQ handler is called for the first time, what will occur
|
||||
// right after the START task is triggered.
|
||||
m_cb.next_buffers = *p_initial_buffers;
|
||||
m_cb.current_buffers.p_rx_buffer = NULL;
|
||||
m_cb.current_buffers.p_tx_buffer = NULL;
|
||||
|
||||
nrf_i2s_transfer_set(NRF_I2S,
|
||||
m_cb.buffer_size,
|
||||
m_cb.next_buffers.p_rx_buffer,
|
||||
m_cb.next_buffers.p_tx_buffer);
|
||||
|
||||
nrf_i2s_enable(NRF_I2S);
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_POWERED_ON;
|
||||
|
||||
nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD);
|
||||
nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD);
|
||||
nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_STOPPED);
|
||||
nrf_i2s_int_enable(NRF_I2S, (m_cb.use_rx ? NRF_I2S_INT_RXPTRUPD_MASK : 0) |
|
||||
(m_cb.use_tx ? NRF_I2S_INT_TXPTRUPD_MASK : 0) |
|
||||
NRF_I2S_INT_STOPPED_MASK);
|
||||
nrf_i2s_task_trigger(NRF_I2S, NRF_I2S_TASK_START);
|
||||
|
||||
NRFX_LOG_INFO("Started.");
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_i2s_next_buffers_set(nrfx_i2s_buffers_t const * p_buffers)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_POWERED_ON);
|
||||
NRFX_ASSERT(p_buffers);
|
||||
NRFX_ASSERT((p_buffers->p_rx_buffer == NULL) ||
|
||||
(nrfx_is_in_ram(p_buffers->p_rx_buffer) &&
|
||||
nrfx_is_word_aligned(p_buffers->p_rx_buffer)));
|
||||
NRFX_ASSERT((p_buffers->p_tx_buffer == NULL) ||
|
||||
(nrfx_is_in_ram(p_buffers->p_tx_buffer) &&
|
||||
nrfx_is_word_aligned(p_buffers->p_tx_buffer)));
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (!m_cb.buffers_needed)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (((p_buffers->p_rx_buffer != NULL)
|
||||
&& !nrfx_is_in_ram(p_buffers->p_rx_buffer))
|
||||
||
|
||||
((p_buffers->p_tx_buffer != NULL)
|
||||
&& !nrfx_is_in_ram(p_buffers->p_tx_buffer)))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (m_cb.use_tx)
|
||||
{
|
||||
NRFX_ASSERT(p_buffers->p_tx_buffer != NULL);
|
||||
nrf_i2s_tx_buffer_set(NRF_I2S, p_buffers->p_tx_buffer);
|
||||
}
|
||||
if (m_cb.use_rx)
|
||||
{
|
||||
NRFX_ASSERT(p_buffers->p_rx_buffer != NULL);
|
||||
nrf_i2s_rx_buffer_set(NRF_I2S, p_buffers->p_rx_buffer);
|
||||
}
|
||||
|
||||
m_cb.next_buffers = *p_buffers;
|
||||
m_cb.buffers_needed = false;
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_i2s_stop(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
m_cb.buffers_needed = false;
|
||||
|
||||
// First disable interrupts, then trigger the STOP task, so no spurious
|
||||
// RXPTRUPD and TXPTRUPD events (see nRF52 anomaly 55) are processed.
|
||||
nrf_i2s_int_disable(NRF_I2S, NRF_I2S_INT_RXPTRUPD_MASK |
|
||||
NRF_I2S_INT_TXPTRUPD_MASK);
|
||||
nrf_i2s_task_trigger(NRF_I2S, NRF_I2S_TASK_STOP);
|
||||
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_I2S_STOP_ANOMALY)
|
||||
*((volatile uint32_t *)(((uint32_t)NRF_I2S) + 0x38)) = 1;
|
||||
*((volatile uint32_t *)(((uint32_t)NRF_I2S) + 0x3C)) = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void nrfx_i2s_irq_handler(void)
|
||||
{
|
||||
if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD))
|
||||
{
|
||||
nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD);
|
||||
m_cb.tx_ready = true;
|
||||
if (m_cb.use_tx && m_cb.buffers_needed)
|
||||
{
|
||||
m_cb.buffers_reused = true;
|
||||
}
|
||||
}
|
||||
if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD))
|
||||
{
|
||||
nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD);
|
||||
m_cb.rx_ready = true;
|
||||
if (m_cb.use_rx && m_cb.buffers_needed)
|
||||
{
|
||||
m_cb.buffers_reused = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_STOPPED))
|
||||
{
|
||||
nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_STOPPED);
|
||||
nrf_i2s_int_disable(NRF_I2S, NRF_I2S_INT_STOPPED_MASK);
|
||||
nrf_i2s_disable(NRF_I2S);
|
||||
|
||||
// When stopped, release all buffers, including these scheduled for
|
||||
// the next transfer.
|
||||
m_cb.handler(&m_cb.current_buffers, 0);
|
||||
m_cb.handler(&m_cb.next_buffers, 0);
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Stopped.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if the requested transfer has been completed:
|
||||
// - full-duplex mode
|
||||
if ((m_cb.use_tx && m_cb.use_rx && m_cb.tx_ready && m_cb.rx_ready) ||
|
||||
// - TX only mode
|
||||
(!m_cb.use_rx && m_cb.tx_ready) ||
|
||||
// - RX only mode
|
||||
(!m_cb.use_tx && m_cb.rx_ready))
|
||||
{
|
||||
m_cb.tx_ready = false;
|
||||
m_cb.rx_ready = false;
|
||||
|
||||
// If the application did not supply the buffers for the next
|
||||
// part of the transfer until this moment, the current buffers
|
||||
// cannot be released, since the I2S peripheral already started
|
||||
// using them. Signal this situation to the application by
|
||||
// passing NULL instead of the structure with released buffers.
|
||||
if (m_cb.buffers_reused)
|
||||
{
|
||||
m_cb.buffers_reused = false;
|
||||
// This will most likely be set at this point. However, there is
|
||||
// a small time window between TXPTRUPD and RXPTRUPD events,
|
||||
// and it is theoretically possible that next buffers will be
|
||||
// set in this window, so to be sure this flag is set to true,
|
||||
// set it explicitly.
|
||||
m_cb.buffers_needed = true;
|
||||
m_cb.handler(NULL,
|
||||
NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Buffers that have been used by the I2S peripheral (current)
|
||||
// are now released and will be returned to the application,
|
||||
// and the ones scheduled to be used as next become the current
|
||||
// ones.
|
||||
nrfx_i2s_buffers_t released_buffers = m_cb.current_buffers;
|
||||
m_cb.current_buffers = m_cb.next_buffers;
|
||||
m_cb.next_buffers.p_rx_buffer = NULL;
|
||||
m_cb.next_buffers.p_tx_buffer = NULL;
|
||||
m_cb.buffers_needed = true;
|
||||
m_cb.handler(&released_buffers,
|
||||
NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_I2S_ENABLED)
|
||||
174
modules/nrfx/drivers/src/nrfx_lpcomp.c
Normal file
174
modules/nrfx/drivers/src/nrfx_lpcomp.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_LPCOMP_ENABLED)
|
||||
|
||||
#include <nrfx_lpcomp.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
|
||||
#define NRFX_LOG_MODULE LPCOMP
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_LPCOMP_EVENT_READY ? "NRF_LPCOMP_EVENT_READY" : \
|
||||
(event == NRF_LPCOMP_EVENT_DOWN ? "NRF_LPCOMP_EVENT_DOWN" : \
|
||||
(event == NRF_LPCOMP_EVENT_UP ? "NRF_LPCOMP_EVENT_UP" : \
|
||||
(event == NRF_LPCOMP_EVENT_CROSS ? "NRF_LPCOMP_EVENT_CROSS" : \
|
||||
"UNKNOWN EVENT"))))
|
||||
|
||||
|
||||
static nrfx_lpcomp_event_handler_t m_lpcomp_event_handler = NULL;
|
||||
static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
|
||||
static void lpcomp_execute_handler(nrf_lpcomp_event_t event, uint32_t event_mask)
|
||||
{
|
||||
if (nrf_lpcomp_event_check(event) && nrf_lpcomp_int_enable_check(event_mask))
|
||||
{
|
||||
nrf_lpcomp_event_clear(event);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(event));
|
||||
|
||||
m_lpcomp_event_handler(event);
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_lpcomp_irq_handler(void)
|
||||
{
|
||||
lpcomp_execute_handler(NRF_LPCOMP_EVENT_READY, LPCOMP_INTENSET_READY_Msk);
|
||||
lpcomp_execute_handler(NRF_LPCOMP_EVENT_DOWN, LPCOMP_INTENSET_DOWN_Msk);
|
||||
lpcomp_execute_handler(NRF_LPCOMP_EVENT_UP, LPCOMP_INTENSET_UP_Msk);
|
||||
lpcomp_execute_handler(NRF_LPCOMP_EVENT_CROSS, LPCOMP_INTENSET_CROSS_Msk);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_lpcomp_init(nrfx_lpcomp_config_t const * p_config,
|
||||
nrfx_lpcomp_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(event_handler);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{ // LPCOMP driver is already initialized
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_lpcomp_event_handler = event_handler;
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
if (nrfx_prs_acquire(NRF_LPCOMP, nrfx_lpcomp_irq_handler) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
nrf_lpcomp_configure(&(p_config->hal));
|
||||
|
||||
nrf_lpcomp_input_select(p_config->input);
|
||||
|
||||
switch (p_config->hal.detection)
|
||||
{
|
||||
case NRF_LPCOMP_DETECT_UP:
|
||||
nrf_lpcomp_int_enable(LPCOMP_INTENSET_UP_Msk);
|
||||
break;
|
||||
|
||||
case NRF_LPCOMP_DETECT_DOWN:
|
||||
nrf_lpcomp_int_enable(LPCOMP_INTENSET_DOWN_Msk);
|
||||
break;
|
||||
|
||||
case NRF_LPCOMP_DETECT_CROSS:
|
||||
nrf_lpcomp_int_enable(LPCOMP_INTENSET_CROSS_Msk);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nrf_lpcomp_shorts_enable(NRF_LPCOMP_SHORT_READY_SAMPLE_MASK);
|
||||
|
||||
NRFX_IRQ_PRIORITY_SET(LPCOMP_IRQn, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(LPCOMP_IRQn);
|
||||
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_lpcomp_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_IRQ_DISABLE(LPCOMP_IRQn);
|
||||
nrfx_lpcomp_disable();
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(NRF_LPCOMP);
|
||||
#endif
|
||||
m_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
m_lpcomp_event_handler = NULL;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
void nrfx_lpcomp_enable(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
nrf_lpcomp_enable();
|
||||
nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_START);
|
||||
m_state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Enabled.");
|
||||
}
|
||||
|
||||
void nrfx_lpcomp_disable(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
|
||||
nrf_lpcomp_disable();
|
||||
nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_STOP);
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Disabled.");
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_LPCOMP_ENABLED)
|
||||
848
modules/nrfx/drivers/src/nrfx_nfct.c
Normal file
848
modules/nrfx/drivers/src/nrfx_nfct.c
Normal file
@@ -0,0 +1,848 @@
|
||||
/**
|
||||
* Copyright (c) 2018 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_NFCT_ENABLED)
|
||||
|
||||
#include <nrfx_nfct.h>
|
||||
|
||||
#define NRFX_LOG_MODULE NFCT
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
|
||||
defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
#define USE_TIMER_WORKAROUND
|
||||
#endif
|
||||
|
||||
#if defined(USE_TIMER_WORKAROUND)
|
||||
#include <nrfx_timer.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const nrfx_timer_t timer; /**< Timer instance that supports the correct NFC field detection. */
|
||||
#if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
bool fieldevents_filter_active; /**< Flag that indicates that the field events are ignored. */
|
||||
bool is_hfclk_on; /**< HFCLK has started - one of the NFC activation conditions. */
|
||||
bool is_delayed; /**< Required time delay has passed - one of the NFC activation conditions. */
|
||||
#else
|
||||
uint32_t field_state_cnt; /**< Counter of the FIELDLOST events. */
|
||||
#endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
} nrfx_nfct_timer_workaround_t;
|
||||
|
||||
#if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
#define NRFX_NFCT_ACTIVATE_DELAY 1000 /**< Minimal delay in us between NFC field detection and activation of NFCT. */
|
||||
#define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_ACTIVATE_DELAY
|
||||
#else
|
||||
#define NRFX_NFCT_FIELDLOST_THR 7
|
||||
#define NRFX_NFCT_FIELD_TIMER_PERIOD 100 /**< Field polling period in us. */
|
||||
#define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_FIELD_TIMER_PERIOD
|
||||
#endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
#define NRFX_NFCT_TIMER_INSTANCE 4 /**< Timer instance used for various workarounds for the NFCT HW issues.*/
|
||||
|
||||
static nrfx_nfct_timer_workaround_t m_timer_workaround =
|
||||
{
|
||||
.timer = NRFX_TIMER_INSTANCE(NRFX_NFCT_TIMER_INSTANCE),
|
||||
};
|
||||
#endif // defined(USE_TIMER_WORKAROUND)
|
||||
|
||||
#define NRFX_NFCT_FWT_MAX_DIFF 1u /**< The maximal difference between the requested FWT and HW-limited FWT settings.*/
|
||||
#define NFCT_FRAMEDELAYMAX_DEFAULT (0x00001000UL) /**< Default value of the FRAMEDELAYMAX. */
|
||||
|
||||
/* Mask of all possible interrupts that are relevant for data reception. */
|
||||
#define NRFX_NFCT_RX_INT_MASK (NRF_NFCT_INT_RXFRAMESTART_MASK | \
|
||||
NRF_NFCT_INT_RXFRAMEEND_MASK | \
|
||||
NRF_NFCT_INT_RXERROR_MASK)
|
||||
|
||||
/* Mask of all possible interrupts that are relevant for data transmission. */
|
||||
#define NRFX_NFCT_TX_INT_MASK (NRF_NFCT_INT_TXFRAMESTART_MASK | \
|
||||
NRF_NFCT_INT_TXFRAMEEND_MASK)
|
||||
|
||||
|
||||
/* Mask of all possible errors from the @ref NRF_NFCT_EVENT_RXERROR event. */
|
||||
#define NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK (NRF_NFCT_RX_FRAME_STATUS_CRC_MASK | \
|
||||
NRF_NFCT_RX_FRAME_STATUS_PARITY_MASK | \
|
||||
NRF_NFCT_RX_FRAME_STATUS_OVERRUN_MASK)
|
||||
|
||||
/* Mask of all possible errors from the @ref NRF_NFCT_EVENT_ERROR event. */
|
||||
#if defined (NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
#define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK | \
|
||||
NRF_NFCT_ERROR_NFCFIELDTOOSTRONG_MASK | \
|
||||
NRF_NFCT_ERROR_NFCFIELDTOOWEAK_MASK)
|
||||
#else
|
||||
#define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
|
||||
#endif
|
||||
|
||||
/* Macros for conversion of bits to bytes. */
|
||||
#define NRFX_NFCT_BYTES_TO_BITS(_bytes) ((_bytes) << 3)
|
||||
#define NRFX_NFCT_BITS_TO_BYTES(_bits) ((_bits) >> 3)
|
||||
|
||||
/* Macro for checking whether the NFCT interrupt is active. */
|
||||
#define NRFX_NFCT_EVT_ACTIVE(_name) (nrf_nfct_event_check(NRFX_CONCAT_2(NRF_NFCT_EVENT_, _name)) && \
|
||||
nrf_nfct_int_enable_check(NRFX_CONCAT_3(NRF_NFCT_INT_, _name, _MASK)))
|
||||
|
||||
/* Macro for callback execution. */
|
||||
#define NRFX_NFCT_CB_HANDLE(_cb, _evt) \
|
||||
if (_cb != NULL) \
|
||||
{ \
|
||||
_cb(&_evt); \
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NRFX_NFC_FIELD_STATE_NONE, /**< Initial value that indicates no NFCT field events. */
|
||||
NRFX_NFC_FIELD_STATE_OFF, /**< The NFCT FIELDLOST event has been set. */
|
||||
NRFX_NFC_FIELD_STATE_ON, /**< The NFCT FIELDDETECTED event has been set. */
|
||||
NRFX_NFC_FIELD_STATE_UNKNOWN /**< Both NFCT field events have been set - ambiguous state. */
|
||||
} nrfx_nfct_field_state_t;
|
||||
|
||||
/**@brief NFCT control block. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_nfct_config_t config;
|
||||
nrfx_drv_state_t state;
|
||||
volatile bool field_on;
|
||||
uint32_t frame_delay_max;
|
||||
} nrfx_nfct_control_block_t;
|
||||
|
||||
static nrfx_nfct_control_block_t m_nfct_cb;
|
||||
|
||||
/**
|
||||
* @brief Common part of the setup used for the NFCT initialization and reinitialization.
|
||||
*/
|
||||
static void nrfx_nfct_hw_init_setup(void)
|
||||
{
|
||||
// Use Window Grid frame delay mode.
|
||||
nrf_nfct_frame_delay_mode_set(NRF_NFCT_FRAME_DELAY_MODE_WINDOWGRID);
|
||||
|
||||
/* Begin: Workaround for anomaly 25 */
|
||||
/* Workaround for wrong SENSRES values require using SDD00001, but here SDD00100 is used
|
||||
because it is required to operate with Windows Phone */
|
||||
nrf_nfct_sensres_bit_frame_sdd_set(NRF_NFCT_SENSRES_BIT_FRAME_SDD_00100);
|
||||
/* End: Workaround for anomaly 25 */
|
||||
}
|
||||
|
||||
static void nrfx_nfct_frame_delay_max_set(bool default_delay)
|
||||
{
|
||||
if (default_delay)
|
||||
{
|
||||
nrf_nfct_frame_delay_max_set(NFCT_FRAMEDELAYMAX_DEFAULT);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_nfct_frame_delay_max_set(m_nfct_cb.frame_delay_max);
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for evaluating and handling the NFC field events.
|
||||
*
|
||||
* @param[in] field_state Current field state.
|
||||
*/
|
||||
static void nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)
|
||||
{
|
||||
nrfx_nfct_evt_t nfct_evt;
|
||||
|
||||
#if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
if(m_timer_workaround.fieldevents_filter_active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
|
||||
if (field_state == NRFX_NFC_FIELD_STATE_UNKNOWN)
|
||||
{
|
||||
/* Probe NFC field */
|
||||
field_state = (nrfx_nfct_field_check()) ? NRFX_NFC_FIELD_STATE_ON : NRFX_NFC_FIELD_STATE_OFF;
|
||||
}
|
||||
|
||||
/* Field event service. Only take action on field transition -
|
||||
* based on the value of m_nfct_cb.field_on
|
||||
*/
|
||||
switch (field_state)
|
||||
{
|
||||
case NRFX_NFC_FIELD_STATE_ON:
|
||||
if (!m_nfct_cb.field_on)
|
||||
{
|
||||
#if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
/* Begin: Workaround for anomaly 190 */
|
||||
m_timer_workaround.is_hfclk_on = false;
|
||||
m_timer_workaround.is_delayed = false;
|
||||
m_timer_workaround.fieldevents_filter_active = true;
|
||||
|
||||
nrfx_timer_clear(&m_timer_workaround.timer);
|
||||
nrfx_timer_enable(&m_timer_workaround.timer);
|
||||
/* End: Workaround for anomaly 190 */
|
||||
#elif defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
nrfx_timer_clear(&m_timer_workaround.timer);
|
||||
nrfx_timer_enable(&m_timer_workaround.timer);
|
||||
m_timer_workaround.field_state_cnt = 0;
|
||||
#endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
|
||||
m_nfct_cb.field_on = true;
|
||||
nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_DETECTED;
|
||||
NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
|
||||
}
|
||||
break;
|
||||
|
||||
case NRFX_NFC_FIELD_STATE_OFF:
|
||||
if (m_nfct_cb.field_on)
|
||||
{
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_SENSE);
|
||||
nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
|
||||
m_nfct_cb.field_on = false;
|
||||
nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_LOST;
|
||||
|
||||
/* Begin: Workaround for anomaly 218 */
|
||||
nrfx_nfct_frame_delay_max_set(true);
|
||||
/* End: Workaround for anomaly 218 */
|
||||
|
||||
NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No implementation required */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_TIMER_WORKAROUND)
|
||||
|
||||
#if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
static void nrfx_nfct_activate_check(void)
|
||||
{
|
||||
static bool is_field_validation_pending = false;
|
||||
|
||||
if (is_field_validation_pending)
|
||||
{
|
||||
is_field_validation_pending = false;
|
||||
m_timer_workaround.fieldevents_filter_active = false;
|
||||
|
||||
// Check the field status and take action if field is lost.
|
||||
nrfx_nfct_field_event_handler(NRFX_NFC_FIELD_STATE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_timer_workaround.is_hfclk_on) && (m_timer_workaround.is_delayed))
|
||||
{
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_ACTIVATE);
|
||||
is_field_validation_pending = true;
|
||||
|
||||
// Start the timer second time to validate whether the tag has locked to the field.
|
||||
nrfx_timer_clear(&m_timer_workaround.timer);
|
||||
nrfx_timer_enable(&m_timer_workaround.timer);
|
||||
}
|
||||
}
|
||||
#endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
|
||||
#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
/* Begin: Workaround for anomaly 116 */
|
||||
static inline void nrfx_nfct_reset(void)
|
||||
{
|
||||
uint32_t fdm;
|
||||
uint32_t int_enabled;
|
||||
uint8_t nfcid1[NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE];
|
||||
nrf_nfct_sensres_nfcid1_size_t nfcid1_size;
|
||||
nrf_nfct_selres_protocol_t protocol;
|
||||
|
||||
// Save parameter settings before the reset of the NFCT peripheral.
|
||||
fdm = nrf_nfct_frame_delay_max_get();
|
||||
nfcid1_size = nrf_nfct_nfcid1_get(nfcid1);
|
||||
protocol = nrf_nfct_selsres_protocol_get();
|
||||
int_enabled = nrf_nfct_int_enable_get();
|
||||
|
||||
// Reset the NFCT peripheral.
|
||||
*(volatile uint32_t *)0x40005FFC = 0;
|
||||
*(volatile uint32_t *)0x40005FFC;
|
||||
*(volatile uint32_t *)0x40005FFC = 1;
|
||||
|
||||
// Restore parameter settings after the reset of the NFCT peripheral.
|
||||
nrf_nfct_frame_delay_max_set(fdm);
|
||||
nrf_nfct_nfcid1_set(nfcid1, nfcid1_size);
|
||||
nrf_nfct_selres_protocol_set(protocol);
|
||||
|
||||
// Restore general HW configuration.
|
||||
nrfx_nfct_hw_init_setup();
|
||||
|
||||
// Restore interrupts.
|
||||
nrf_nfct_int_enable(int_enabled);
|
||||
|
||||
// Disable interrupts associated with data exchange.
|
||||
nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
|
||||
|
||||
NRFX_LOG_INFO("Reinitialize");
|
||||
}
|
||||
/* End: Workaround for anomaly 116 */
|
||||
|
||||
static void nrfx_nfct_field_poll(void)
|
||||
{
|
||||
if (!nrfx_nfct_field_check())
|
||||
{
|
||||
if (++m_timer_workaround.field_state_cnt > NRFX_NFCT_FIELDLOST_THR)
|
||||
{
|
||||
nrfx_nfct_evt_t nfct_evt =
|
||||
{
|
||||
.evt_id = NRFX_NFCT_EVT_FIELD_LOST,
|
||||
};
|
||||
|
||||
nrfx_timer_disable(&m_timer_workaround.timer);
|
||||
m_nfct_cb.field_on = false;
|
||||
|
||||
/* Begin: Workaround for anomaly 218 */
|
||||
nrfx_nfct_frame_delay_max_set(true);
|
||||
/* End: Workaround for anomaly 218 */
|
||||
|
||||
/* Begin: Workaround for anomaly 116 */
|
||||
/* resume the NFCT to initialized state */
|
||||
nrfx_nfct_reset();
|
||||
/* End: Workaround for anomaly 116 */
|
||||
|
||||
NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_timer_workaround.field_state_cnt = 0;
|
||||
}
|
||||
#endif // defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
|
||||
static void nrfx_nfct_field_timer_handler(nrf_timer_event_t event_type, void * p_context)
|
||||
{
|
||||
(void)p_context;
|
||||
|
||||
if (event_type != NRF_TIMER_EVENT_COMPARE0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
m_timer_workaround.is_delayed = true;
|
||||
|
||||
nrfx_timer_disable(&m_timer_workaround.timer);
|
||||
nrfx_nfct_activate_check();
|
||||
#else
|
||||
nrfx_nfct_field_poll();
|
||||
#endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
}
|
||||
|
||||
static inline nrfx_err_t nrfx_nfct_field_timer_config(void)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
nrfx_timer_config_t timer_cfg =
|
||||
{
|
||||
.frequency = NRF_TIMER_FREQ_1MHz,
|
||||
.mode = NRF_TIMER_MODE_TIMER,
|
||||
.bit_width = NRF_TIMER_BIT_WIDTH_16,
|
||||
.interrupt_priority = NRFX_NFCT_CONFIG_IRQ_PRIORITY
|
||||
};
|
||||
|
||||
err_code = nrfx_timer_init(&m_timer_workaround.timer, &timer_cfg, nrfx_nfct_field_timer_handler);
|
||||
if (err_code != NRFX_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_timer_extended_compare(&m_timer_workaround.timer,
|
||||
NRF_TIMER_CC_CHANNEL0,
|
||||
nrfx_timer_us_to_ticks(&m_timer_workaround.timer, NRFX_NFCT_TIMER_PERIOD),
|
||||
NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
|
||||
true);
|
||||
return err_code;
|
||||
}
|
||||
#endif // defined(USE_TIMER_WORKAROUND)
|
||||
|
||||
static inline nrf_nfct_sensres_nfcid1_size_t nrf_nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)
|
||||
{
|
||||
switch (nfcid1_size)
|
||||
{
|
||||
case NRFX_NFCT_NFCID1_SINGLE_SIZE:
|
||||
return NRF_NFCT_SENSRES_NFCID1_SIZE_SINGLE;
|
||||
|
||||
case NRFX_NFCT_NFCID1_DOUBLE_SIZE:
|
||||
return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
|
||||
|
||||
case NRFX_NFCT_NFCID1_TRIPLE_SIZE:
|
||||
return NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE;
|
||||
|
||||
default:
|
||||
return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)
|
||||
{
|
||||
nrf_nfct_int_enable(rxtx_int_mask & m_nfct_cb.config.rxtx_int_mask);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_nfct_init(nrfx_nfct_config_t const * p_config)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (m_nfct_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
return NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
m_nfct_cb.config = *p_config;
|
||||
nrfx_nfct_hw_init_setup();
|
||||
|
||||
NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
|
||||
NRFX_IRQ_PRIORITY_SET(NFCT_IRQn, NRFX_NFCT_CONFIG_IRQ_PRIORITY);
|
||||
NRFX_IRQ_ENABLE(NFCT_IRQn);
|
||||
|
||||
#if defined(USE_TIMER_WORKAROUND)
|
||||
/* Initialize Timer module as the workaround for NFCT HW issues. */
|
||||
err_code = nrfx_nfct_field_timer_config();
|
||||
#endif // defined(USE_TIMER_WORKAROUND)
|
||||
|
||||
if (err_code == NRFX_SUCCESS)
|
||||
{
|
||||
uint8_t default_nfcid1[NRFX_NFCT_NFCID1_DEFAULT_LEN];
|
||||
err_code = nrfx_nfct_nfcid1_default_bytes_get(default_nfcid1, sizeof(default_nfcid1));
|
||||
NRFX_ASSERT(err_code == NRFX_SUCCESS);
|
||||
nrf_nfct_nfcid1_set(default_nfcid1, NRF_NFCT_SENSRES_NFCID1_SIZE_DEFAULT);
|
||||
}
|
||||
else
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_nfct_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
m_nfct_cb.frame_delay_max = NFCT_FRAMEDELAYMAX_DEFAULT;
|
||||
|
||||
NRFX_LOG_INFO("Initialized");
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_nfct_uninit(void)
|
||||
{
|
||||
nrfx_nfct_disable();
|
||||
|
||||
NRFX_IRQ_DISABLE(NFCT_IRQn);
|
||||
NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
|
||||
|
||||
#if defined(USE_TIMER_WORKAROUND)
|
||||
/* De-initialize Timer module as the workaround for NFCT HW issues. */
|
||||
nrfx_timer_uninit(&m_timer_workaround.timer);
|
||||
#endif // defined(USE_TIMER_WORKAROUND)
|
||||
|
||||
m_nfct_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
void nrfx_nfct_enable(void)
|
||||
{
|
||||
nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_SENSE);
|
||||
|
||||
nrf_nfct_int_enable(NRF_NFCT_INT_FIELDDETECTED_MASK | NRF_NFCT_INT_ERROR_MASK |
|
||||
NRF_NFCT_INT_SELECTED_MASK);
|
||||
#if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
|
||||
nrf_nfct_int_enable(NRF_NFCT_INT_FIELDLOST_MASK);
|
||||
#endif // !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
|
||||
|
||||
NRFX_LOG_INFO("Start");
|
||||
}
|
||||
|
||||
void nrfx_nfct_disable(void)
|
||||
{
|
||||
nrf_nfct_int_disable(NRF_NFCT_DISABLE_ALL_INT);
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_DISABLE);
|
||||
|
||||
NRFX_LOG_INFO("Stop");
|
||||
}
|
||||
|
||||
bool nrfx_nfct_field_check(void)
|
||||
{
|
||||
uint32_t const field_state = nrf_nfct_field_status_get();
|
||||
|
||||
if (((field_state & NRF_NFCT_FIELD_STATE_PRESENT_MASK) == 0) &&
|
||||
((field_state & NRF_NFCT_FIELD_STATE_LOCK_MASK) == 0))
|
||||
{
|
||||
/* Field is not active */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_tx_data)
|
||||
{
|
||||
NRFX_ASSERT(p_tx_data);
|
||||
|
||||
nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
|
||||
|
||||
nrfx_nfct_rxtx_int_enable(NRFX_NFCT_RX_INT_MASK);
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_ENABLERXDATA);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,
|
||||
nrf_nfct_frame_delay_mode_t delay_mode)
|
||||
{
|
||||
NRFX_ASSERT(p_tx_data);
|
||||
NRFX_ASSERT(p_tx_data->p_data);
|
||||
|
||||
if (p_tx_data->data_size == 0)
|
||||
{
|
||||
return NRFX_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
|
||||
nrf_nfct_tx_bits_set(NRFX_NFCT_BYTES_TO_BITS(p_tx_data->data_size));
|
||||
nrf_nfct_frame_delay_mode_set((nrf_nfct_frame_delay_mode_t) delay_mode);
|
||||
|
||||
nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_STARTTX);
|
||||
|
||||
NRFX_LOG_INFO("Tx start");
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
void nrfx_nfct_state_force(nrfx_nfct_state_t state)
|
||||
{
|
||||
#if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
if (state == NRFX_NFCT_STATE_ACTIVATED)
|
||||
{
|
||||
m_timer_workaround.is_hfclk_on = true;
|
||||
/* NFCT will be activated based on additional conditions */
|
||||
nrfx_nfct_activate_check();
|
||||
return;
|
||||
}
|
||||
#endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
nrf_nfct_task_trigger((nrf_nfct_task_t) state);
|
||||
}
|
||||
|
||||
void nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)
|
||||
{
|
||||
if (sub_state == NRFX_NFCT_ACTIVE_STATE_DEFAULT)
|
||||
{
|
||||
#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
if (((*(uint32_t volatile *)(0x40005420)) & 0x1UL) == (1UL))
|
||||
#else
|
||||
if (nrf_nfct_sleep_state_get() == NRF_NFCT_SLEEP_STATE_SLEEP_A)
|
||||
#endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
{
|
||||
// Default state is SLEEP_A
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_GOSLEEP);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default state is IDLE
|
||||
nrf_nfct_task_trigger(NRF_NFCT_TASK_GOIDLE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_nfct_task_trigger((nrf_nfct_task_t) sub_state);
|
||||
}
|
||||
|
||||
/* Begin: Workaround for anomaly 218 */
|
||||
nrfx_nfct_frame_delay_max_set(true);
|
||||
/* End: Workaround for anomaly 218 */
|
||||
|
||||
/* Disable TX/RX here (will be enabled at SELECTED) */
|
||||
nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)
|
||||
{
|
||||
NRFX_ASSERT(p_param);
|
||||
|
||||
switch (p_param->id)
|
||||
{
|
||||
case NRFX_NFCT_PARAM_ID_FDT:
|
||||
{
|
||||
uint32_t delay = p_param->data.fdt;
|
||||
uint32_t delay_thr = NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk;
|
||||
|
||||
// Delay validation.
|
||||
if (delay > (delay_thr + NRFX_NFCT_FWT_MAX_DIFF))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
delay = (delay > delay_thr) ? delay_thr : delay;
|
||||
m_nfct_cb.frame_delay_max = delay;
|
||||
break;
|
||||
}
|
||||
|
||||
case NRFX_NFCT_PARAM_ID_SEL_RES:
|
||||
if (p_param->data.sel_res_protocol > NRF_NFCT_SELRES_PROTOCOL_NFCDEP_T4AT)
|
||||
{
|
||||
return NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
nrf_nfct_selres_protocol_set((nrf_nfct_selres_protocol_t) p_param->data.sel_res_protocol);
|
||||
break;
|
||||
|
||||
case NRFX_NFCT_PARAM_ID_NFCID1:
|
||||
{
|
||||
nrf_nfct_sensres_nfcid1_size_t id_size_mask;
|
||||
|
||||
id_size_mask = nrf_nfct_nfcid1_size_to_sensres_size(p_param->data.nfcid1.id_size);
|
||||
nrf_nfct_nfcid1_set(p_param->data.nfcid1.p_id, id_size_mask);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,
|
||||
uint32_t nfcid1_buff_len)
|
||||
{
|
||||
if ((nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE) &&
|
||||
(nfcid1_buff_len != NRFX_NFCT_NFCID1_DOUBLE_SIZE) &&
|
||||
(nfcid1_buff_len != NRFX_NFCT_NFCID1_TRIPLE_SIZE))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
uint32_t nfc_tag_header0 = NRF_FICR->NFC.TAGHEADER0;
|
||||
uint32_t nfc_tag_header1 = NRF_FICR->NFC.TAGHEADER1;
|
||||
uint32_t nfc_tag_header2 = NRF_FICR->NFC.TAGHEADER2;
|
||||
|
||||
p_nfcid1_buff[0] = (uint8_t) (nfc_tag_header0 >> 0);
|
||||
p_nfcid1_buff[1] = (uint8_t) (nfc_tag_header0 >> 8);
|
||||
p_nfcid1_buff[2] = (uint8_t) (nfc_tag_header0 >> 16);
|
||||
p_nfcid1_buff[3] = (uint8_t) (nfc_tag_header1 >> 0);
|
||||
|
||||
if (nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE)
|
||||
{
|
||||
p_nfcid1_buff[4] = (uint8_t) (nfc_tag_header1 >> 8);
|
||||
p_nfcid1_buff[5] = (uint8_t) (nfc_tag_header1 >> 16);
|
||||
p_nfcid1_buff[6] = (uint8_t) (nfc_tag_header1 >> 24);
|
||||
|
||||
if (nfcid1_buff_len == NRFX_NFCT_NFCID1_TRIPLE_SIZE)
|
||||
{
|
||||
p_nfcid1_buff[7] = (uint8_t) (nfc_tag_header2 >> 0);
|
||||
p_nfcid1_buff[8] = (uint8_t) (nfc_tag_header2 >> 8);
|
||||
p_nfcid1_buff[9] = (uint8_t) (nfc_tag_header2 >> 16);
|
||||
}
|
||||
/* Begin: Workaround for anomaly 181. */
|
||||
/* Workaround for wrong value in NFCID1. Value 0x88 cannot be used as byte 3
|
||||
of a double-size NFCID1, according to the NFC Forum Digital Protocol specification. */
|
||||
else if (p_nfcid1_buff[3] == 0x88)
|
||||
{
|
||||
p_nfcid1_buff[3] |= 0x11;
|
||||
}
|
||||
/* End: Workaround for anomaly 181 */
|
||||
}
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
void nrfx_nfct_autocolres_enable(void)
|
||||
{
|
||||
#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
(*(uint32_t *)(0x4000559C)) &= (~(0x1UL));
|
||||
#else
|
||||
nrf_nfct_autocolres_enable();
|
||||
#endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
}
|
||||
|
||||
void nrfx_nfct_autocolres_disable(void)
|
||||
{
|
||||
#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
(*(uint32_t *)(0x4000559C)) |= (0x1UL);
|
||||
#else
|
||||
nrf_nfct_autocolres_disable();
|
||||
#endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
|
||||
}
|
||||
|
||||
void nrfx_nfct_irq_handler(void)
|
||||
{
|
||||
nrfx_nfct_field_state_t current_field = NRFX_NFC_FIELD_STATE_NONE;
|
||||
|
||||
if (NRFX_NFCT_EVT_ACTIVE(FIELDDETECTED))
|
||||
{
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDDETECTED);
|
||||
current_field = NRFX_NFC_FIELD_STATE_ON;
|
||||
|
||||
NRFX_LOG_DEBUG("Field detected");
|
||||
}
|
||||
|
||||
#if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
|
||||
if (NRFX_NFCT_EVT_ACTIVE(FIELDLOST))
|
||||
{
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDLOST);
|
||||
current_field = (current_field == NRFX_NFC_FIELD_STATE_NONE) ?
|
||||
NRFX_NFC_FIELD_STATE_OFF : NRFX_NFC_FIELD_STATE_UNKNOWN;
|
||||
|
||||
NRFX_LOG_DEBUG("Field lost");
|
||||
}
|
||||
#endif //!defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
|
||||
|
||||
/* Perform actions if any FIELD event is active */
|
||||
if (current_field != NRFX_NFC_FIELD_STATE_NONE)
|
||||
{
|
||||
nrfx_nfct_field_event_handler(current_field);
|
||||
}
|
||||
|
||||
if (NRFX_NFCT_EVT_ACTIVE(RXFRAMEEND))
|
||||
{
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
|
||||
|
||||
nrfx_nfct_evt_t nfct_evt =
|
||||
{
|
||||
.evt_id = NRFX_NFCT_EVT_RX_FRAMEEND
|
||||
};
|
||||
|
||||
/* Take into account only the number of whole bytes. */
|
||||
nfct_evt.params.rx_frameend.rx_status = 0;
|
||||
nfct_evt.params.rx_frameend.rx_data.p_data = nrf_nfct_rxtx_buffer_get();
|
||||
nfct_evt.params.rx_frameend.rx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_rx_bits_get(true));
|
||||
|
||||
if (NRFX_NFCT_EVT_ACTIVE(RXERROR))
|
||||
{
|
||||
nfct_evt.params.rx_frameend.rx_status =
|
||||
(nrf_nfct_rx_frame_status_get() & NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
|
||||
|
||||
NRFX_LOG_DEBUG("Rx error (0x%x)", (unsigned int) nfct_evt.params.rx_frameend.rx_status);
|
||||
|
||||
/* Clear rx frame status */
|
||||
nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
|
||||
}
|
||||
|
||||
NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
|
||||
|
||||
/* Clear TXFRAMESTART EVENT so it can be checked in hal_nfc_send */
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
|
||||
|
||||
NRFX_LOG_DEBUG("Rx fend");
|
||||
}
|
||||
|
||||
if (NRFX_NFCT_EVT_ACTIVE(TXFRAMEEND))
|
||||
{
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
|
||||
|
||||
nrfx_nfct_evt_t nfct_evt =
|
||||
{
|
||||
.evt_id = NRFX_NFCT_EVT_TX_FRAMEEND
|
||||
};
|
||||
|
||||
/* Disable TX END event to ignore frame transmission other than READ response */
|
||||
nrf_nfct_int_disable(NRFX_NFCT_TX_INT_MASK);
|
||||
|
||||
NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
|
||||
|
||||
NRFX_LOG_DEBUG("Tx fend");
|
||||
}
|
||||
|
||||
if (NRFX_NFCT_EVT_ACTIVE(SELECTED))
|
||||
{
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_SELECTED);
|
||||
/* Clear also RX END and RXERROR events because SW does not take care of
|
||||
commands that were received before selecting the tag. */
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
|
||||
|
||||
/* Begin: Workaround for anomaly 218 */
|
||||
nrfx_nfct_frame_delay_max_set(false);
|
||||
/* End: Workaround for anomaly 218 */
|
||||
|
||||
/* At this point any previous error status can be ignored. */
|
||||
nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
|
||||
nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
|
||||
|
||||
nrfx_nfct_evt_t nfct_evt =
|
||||
{
|
||||
.evt_id = NRFX_NFCT_EVT_SELECTED
|
||||
};
|
||||
NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
|
||||
|
||||
NRFX_LOG_DEBUG("Selected");
|
||||
}
|
||||
|
||||
if (NRFX_NFCT_EVT_ACTIVE(ERROR))
|
||||
{
|
||||
uint32_t err_status = nrf_nfct_error_status_get();
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_ERROR);
|
||||
|
||||
nrfx_nfct_evt_t nfct_evt =
|
||||
{
|
||||
.evt_id = NRFX_NFCT_EVT_ERROR
|
||||
};
|
||||
|
||||
/* Clear FRAMEDELAYTIMEOUT error (expected HW behaviour) when SLP_REQ command was received. */
|
||||
if (err_status & NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
|
||||
{
|
||||
nrf_nfct_error_status_clear(NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK);
|
||||
|
||||
nfct_evt.params.error.reason = NRFX_NFCT_ERROR_FRAMEDELAYTIMEOUT;
|
||||
NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
|
||||
}
|
||||
|
||||
/* Report any other error. */
|
||||
err_status &= ~NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK;
|
||||
if (err_status)
|
||||
{
|
||||
NRFX_LOG_DEBUG("Error (0x%x)", (unsigned int) err_status);
|
||||
}
|
||||
|
||||
/* Clear error status. */
|
||||
nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
|
||||
}
|
||||
|
||||
if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
|
||||
{
|
||||
nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
|
||||
|
||||
if (m_nfct_cb.config.cb != NULL)
|
||||
{
|
||||
nrfx_nfct_evt_t nfct_evt;
|
||||
|
||||
nfct_evt.evt_id = NRFX_NFCT_EVT_TX_FRAMESTART;
|
||||
nfct_evt.params.tx_framestart.tx_data.p_data = nrf_nfct_rxtx_buffer_get();
|
||||
nfct_evt.params.tx_framestart.tx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_tx_bits_get());
|
||||
|
||||
m_nfct_cb.config.cb(&nfct_evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_NFCT_ENABLED)
|
||||
435
modules/nrfx/drivers/src/nrfx_nvmc.c
Normal file
435
modules/nrfx/drivers/src/nrfx_nvmc.c
Normal file
@@ -0,0 +1,435 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_NVMC_ENABLED)
|
||||
|
||||
#include <nrfx_nvmc.h>
|
||||
|
||||
/**
|
||||
* Value representing the number of bytes in a word.
|
||||
*
|
||||
* It is used in loops iterating over bytes contained in a word
|
||||
* or in word-alignment checks.
|
||||
*/
|
||||
#define NVMC_BYTES_IN_WORD 4
|
||||
|
||||
/**
|
||||
* Value representing non-volatile memory (NVM) page count.
|
||||
*
|
||||
* This symbol is needed to determine NVM page count for chips that cannot
|
||||
* always access FICR for this information.
|
||||
*/
|
||||
#if defined(NRF9160_XXAA)
|
||||
#define NVMC_FLASH_PAGE_COUNT 256
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Value representing non-volatile memory (NVM) page size in bytes.
|
||||
*
|
||||
* This symbol is needed to determine NVM page size for chips that cannot
|
||||
* always access FICR for this information.
|
||||
*/
|
||||
#if defined(NRF9160_XXAA)
|
||||
#define NVMC_FLASH_PAGE_SIZE 0x1000 ///< 4 kB
|
||||
#endif
|
||||
|
||||
#if defined(NRF_NVMC_PARTIAL_ERASE_PRESENT)
|
||||
/**
|
||||
* Value representing the page erase time.
|
||||
*
|
||||
* This value is used to determine whether the partial erase is still in progress.
|
||||
*/
|
||||
#if defined(NRF52810_XXAA) || defined(NRF52811_XXAA) || defined(NRF52840_XXAA)
|
||||
#define NVMC_PAGE_ERASE_DURATION_MS 85
|
||||
#elif defined(NRF52820_XXAA) || defined(NRF52833_XXAA) || defined(NRF9160_XXAA)
|
||||
#define NVMC_PAGE_ERASE_DURATION_MS 87
|
||||
#else
|
||||
#error "Page partial erase present but could not determine its total duration for given SoC"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Value representing the invalid page partial erase address.
|
||||
*
|
||||
* This value is used for representing a NULL pointer for
|
||||
* partial erase, as that address 0 can be a valid
|
||||
* memory address in flash.
|
||||
*/
|
||||
#define NVMC_PARTIAL_ERASE_INVALID_ADDR 0xFFFFFFFF
|
||||
|
||||
/** Internal counter for page partial erase. */
|
||||
static uint32_t m_partial_erase_time_elapsed;
|
||||
|
||||
/** Partial erase page address. */
|
||||
static uint32_t m_partial_erase_page_addr = NVMC_PARTIAL_ERASE_INVALID_ADDR;
|
||||
|
||||
#endif // defined(NRF_NVMC_PARTIAL_ERASE_PRESENT)
|
||||
|
||||
static uint32_t flash_page_size_get(void)
|
||||
{
|
||||
uint32_t flash_page_size = 0;
|
||||
|
||||
#if defined(NRF51) || defined(NRF52_SERIES)
|
||||
flash_page_size = nrf_ficr_codepagesize_get(NRF_FICR);
|
||||
#elif defined(NVMC_FLASH_PAGE_SIZE)
|
||||
flash_page_size = NVMC_FLASH_PAGE_SIZE;
|
||||
#else
|
||||
#error "Cannot determine flash page size for a given SoC."
|
||||
#endif
|
||||
|
||||
return flash_page_size;
|
||||
}
|
||||
|
||||
static uint32_t flash_page_count_get(void)
|
||||
{
|
||||
uint32_t page_count = 0;
|
||||
|
||||
#if defined(NRF51) || defined(NRF52_SERIES)
|
||||
page_count = nrf_ficr_codesize_get(NRF_FICR);
|
||||
#elif defined(NVMC_FLASH_PAGE_COUNT)
|
||||
page_count = NVMC_FLASH_PAGE_COUNT;
|
||||
#else
|
||||
#error "Cannot determine flash page count for a given SoC."
|
||||
#endif
|
||||
|
||||
return page_count;
|
||||
}
|
||||
|
||||
static uint32_t flash_total_size_get(void)
|
||||
{
|
||||
return flash_page_size_get() * flash_page_count_get();
|
||||
}
|
||||
|
||||
|
||||
static bool is_page_aligned_check(uint32_t addr)
|
||||
{
|
||||
/* If the modulo operation returns '0', then the address is aligned. */
|
||||
return !(addr % flash_page_size_get());
|
||||
}
|
||||
|
||||
static uint32_t partial_word_create(uint32_t addr, uint8_t const * bytes, uint32_t bytes_count)
|
||||
{
|
||||
uint32_t value32;
|
||||
uint32_t byte_shift;
|
||||
|
||||
byte_shift = addr % NVMC_BYTES_IN_WORD;
|
||||
|
||||
NRFX_ASSERT(bytes_count <= (NVMC_BYTES_IN_WORD - byte_shift));
|
||||
|
||||
value32 = 0xFFFFFFFF;
|
||||
for (uint32_t i = 0; i < bytes_count; i++)
|
||||
{
|
||||
((uint8_t *)&value32)[byte_shift] = bytes[i];
|
||||
byte_shift++;
|
||||
}
|
||||
|
||||
return value32;
|
||||
}
|
||||
|
||||
static void nvmc_readonly_mode_set(void)
|
||||
{
|
||||
#if defined(NRF_TRUSTZONE_NONSECURE)
|
||||
nrf_nvmc_nonsecure_mode_set(NRF_NVMC, NRF_NVMC_NS_MODE_READONLY);
|
||||
#else
|
||||
nrf_nvmc_mode_set(NRF_NVMC, NRF_NVMC_MODE_READONLY);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void nvmc_write_mode_set(void)
|
||||
{
|
||||
#if defined(NRF_TRUSTZONE_NONSECURE)
|
||||
nrf_nvmc_nonsecure_mode_set(NRF_NVMC, NRF_NVMC_NS_MODE_WRITE);
|
||||
#else
|
||||
nrf_nvmc_mode_set(NRF_NVMC, NRF_NVMC_MODE_WRITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void nvmc_erase_mode_set(void)
|
||||
{
|
||||
#if defined(NRF_TRUSTZONE_NONSECURE)
|
||||
nrf_nvmc_nonsecure_mode_set(NRF_NVMC, NRF_NVMC_NS_MODE_ERASE);
|
||||
#else
|
||||
nrf_nvmc_mode_set(NRF_NVMC, NRF_NVMC_MODE_ERASE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void nvmc_word_write(uint32_t addr, uint32_t value)
|
||||
{
|
||||
#if defined(NRF9160_XXAA)
|
||||
while (!nrf_nvmc_write_ready_check(NRF_NVMC))
|
||||
{}
|
||||
#else
|
||||
while (!nrf_nvmc_ready_check(NRF_NVMC))
|
||||
{}
|
||||
#endif
|
||||
|
||||
*(volatile uint32_t *)addr = value;
|
||||
__DMB();
|
||||
}
|
||||
|
||||
static void nvmc_words_write(uint32_t addr, void const * src, uint32_t num_words)
|
||||
{
|
||||
for (uint32_t i = 0; i < num_words; i++)
|
||||
{
|
||||
nvmc_word_write(addr + (NVMC_BYTES_IN_WORD * i), ((uint32_t const *)src)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_nvmc_page_erase(uint32_t addr)
|
||||
{
|
||||
NRFX_ASSERT(addr < flash_total_size_get());
|
||||
|
||||
if (!is_page_aligned_check(addr))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
nvmc_erase_mode_set();
|
||||
nrf_nvmc_page_erase_start(NRF_NVMC, addr);
|
||||
while (!nrf_nvmc_ready_check(NRF_NVMC))
|
||||
{}
|
||||
nvmc_readonly_mode_set();
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_nvmc_uicr_erase(void)
|
||||
{
|
||||
#if defined(NVMC_ERASEUICR_ERASEUICR_Msk)
|
||||
nvmc_erase_mode_set();
|
||||
nrf_nvmc_uicr_erase_start(NRF_NVMC);
|
||||
while (!nrf_nvmc_ready_check(NRF_NVMC))
|
||||
{}
|
||||
nvmc_readonly_mode_set();
|
||||
return NRFX_SUCCESS;
|
||||
#else
|
||||
return NRFX_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
void nrfx_nvmc_all_erase(void)
|
||||
{
|
||||
nvmc_erase_mode_set();
|
||||
nrf_nvmc_erase_all_start(NRF_NVMC);
|
||||
while (!nrf_nvmc_ready_check(NRF_NVMC))
|
||||
{}
|
||||
nvmc_readonly_mode_set();
|
||||
}
|
||||
|
||||
#if defined(NRF_NVMC_PARTIAL_ERASE_PRESENT)
|
||||
nrfx_err_t nrfx_nvmc_page_partial_erase_init(uint32_t addr, uint32_t duration_ms)
|
||||
{
|
||||
NRFX_ASSERT(addr < flash_total_size_get());
|
||||
|
||||
if (!is_page_aligned_check(addr))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
m_partial_erase_time_elapsed = 0;
|
||||
m_partial_erase_page_addr = addr;
|
||||
nrf_nvmc_partial_erase_duration_set(NRF_NVMC, duration_ms);
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
bool nrfx_nvmc_page_partial_erase_continue(void)
|
||||
{
|
||||
NRFX_ASSERT(m_partial_erase_page_addr != NVMC_PARTIAL_ERASE_INVALID_ADDR);
|
||||
|
||||
uint32_t duration_ms = nrf_nvmc_partial_erase_duration_get(NRF_NVMC);
|
||||
|
||||
#if defined(NVMC_CONFIG_WEN_PEen)
|
||||
nrf_nvmc_mode_set(NRF_NVMC, NRF_NVMC_MODE_PARTIAL_ERASE);
|
||||
#else
|
||||
nrf_nvmc_mode_set(NRF_NVMC, NRF_NVMC_MODE_ERASE);
|
||||
#endif
|
||||
|
||||
nrf_nvmc_page_partial_erase_start(NRF_NVMC, m_partial_erase_page_addr);
|
||||
while (!nrf_nvmc_ready_check(NRF_NVMC))
|
||||
{}
|
||||
nvmc_readonly_mode_set();
|
||||
|
||||
m_partial_erase_time_elapsed += duration_ms;
|
||||
if (m_partial_erase_time_elapsed < NVMC_PAGE_ERASE_DURATION_MS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_partial_erase_page_addr = NVMC_PARTIAL_ERASE_INVALID_ADDR;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif // defined(NRF_NVMC_PARTIAL_ERASE_PRESENT)
|
||||
|
||||
bool nrfx_nvmc_byte_writable_check(uint32_t addr, uint8_t val_to_check)
|
||||
{
|
||||
NRFX_ASSERT((addr < flash_total_size_get()) ||
|
||||
((addr - (uint32_t)NRF_UICR) < sizeof(NRF_UICR_Type)));
|
||||
|
||||
uint8_t val_on_addr = *(uint8_t const *)addr;
|
||||
return (val_to_check & val_on_addr) == val_to_check;
|
||||
}
|
||||
|
||||
bool nrfx_nvmc_word_writable_check(uint32_t addr, uint32_t val_to_check)
|
||||
{
|
||||
NRFX_ASSERT((addr < flash_total_size_get()) ||
|
||||
((addr - (uint32_t)NRF_UICR) < sizeof(NRF_UICR_Type)));
|
||||
NRFX_ASSERT(nrfx_is_word_aligned((void const *)addr));
|
||||
|
||||
uint32_t val_on_addr = *(uint32_t const *)addr;
|
||||
return (val_to_check & val_on_addr) == val_to_check;
|
||||
}
|
||||
|
||||
void nrfx_nvmc_byte_write(uint32_t addr, uint8_t value)
|
||||
{
|
||||
uint32_t aligned_addr = addr & ~(0x03UL);
|
||||
|
||||
nrfx_nvmc_word_write(aligned_addr, partial_word_create(addr, &value, 1));
|
||||
}
|
||||
|
||||
void nrfx_nvmc_word_write(uint32_t addr, uint32_t value)
|
||||
{
|
||||
NRFX_ASSERT((addr < flash_total_size_get()) ||
|
||||
((addr - (uint32_t)NRF_UICR) < sizeof(NRF_UICR_Type)));
|
||||
NRFX_ASSERT(nrfx_is_word_aligned((void const *)addr));
|
||||
|
||||
nvmc_write_mode_set();
|
||||
|
||||
nvmc_word_write(addr, value);
|
||||
|
||||
nvmc_readonly_mode_set();
|
||||
}
|
||||
|
||||
void nrfx_nvmc_bytes_write(uint32_t addr, void const * src, uint32_t num_bytes)
|
||||
{
|
||||
NRFX_ASSERT((addr < flash_total_size_get()) ||
|
||||
((addr - (uint32_t)NRF_UICR) < sizeof(NRF_UICR_Type)));
|
||||
|
||||
nvmc_write_mode_set();
|
||||
|
||||
uint8_t const * bytes_src = (uint8_t const *)src;
|
||||
|
||||
uint32_t unaligned_bytes = addr % NVMC_BYTES_IN_WORD;
|
||||
if (unaligned_bytes != 0)
|
||||
{
|
||||
uint32_t leading_bytes = NVMC_BYTES_IN_WORD - unaligned_bytes;
|
||||
if (leading_bytes > num_bytes)
|
||||
{
|
||||
leading_bytes = num_bytes;
|
||||
}
|
||||
|
||||
nvmc_word_write(addr - unaligned_bytes,
|
||||
partial_word_create(addr, bytes_src, leading_bytes));
|
||||
num_bytes -= leading_bytes;
|
||||
addr += leading_bytes;
|
||||
bytes_src += leading_bytes;
|
||||
}
|
||||
|
||||
#if defined(__CORTEX_M) && (__CORTEX_M == 0U)
|
||||
if (!nrfx_is_word_aligned((void const *)bytes_src))
|
||||
{
|
||||
/* Cortex-M0 allows only word-aligned RAM access.
|
||||
If source address is not word-aligned, bytes are combined
|
||||
into words explicitly. */
|
||||
for (uint32_t i = 0; i < num_bytes / NVMC_BYTES_IN_WORD; i++)
|
||||
{
|
||||
uint32_t word = (uint32_t)bytes_src[0]
|
||||
| ((uint32_t)bytes_src[1]) << 8
|
||||
| ((uint32_t)bytes_src[2]) << 16
|
||||
| ((uint32_t)bytes_src[3]) << 24;
|
||||
|
||||
nvmc_word_write(addr, word);
|
||||
bytes_src += NVMC_BYTES_IN_WORD;
|
||||
addr += NVMC_BYTES_IN_WORD;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint32_t word_count = num_bytes / NVMC_BYTES_IN_WORD;
|
||||
|
||||
nvmc_words_write(addr, (uint32_t const *)bytes_src, word_count);
|
||||
|
||||
addr += word_count * NVMC_BYTES_IN_WORD;
|
||||
bytes_src += word_count * NVMC_BYTES_IN_WORD;
|
||||
}
|
||||
|
||||
uint32_t trailing_bytes = num_bytes % NVMC_BYTES_IN_WORD;
|
||||
if (trailing_bytes != 0)
|
||||
{
|
||||
nvmc_word_write(addr, partial_word_create(addr, bytes_src, trailing_bytes));
|
||||
}
|
||||
|
||||
nvmc_readonly_mode_set();
|
||||
}
|
||||
|
||||
void nrfx_nvmc_words_write(uint32_t addr, void const * src, uint32_t num_words)
|
||||
{
|
||||
NRFX_ASSERT((addr < flash_total_size_get()) ||
|
||||
((addr - (uint32_t)NRF_UICR) < sizeof(NRF_UICR_Type)));
|
||||
NRFX_ASSERT(nrfx_is_word_aligned((void const *)addr));
|
||||
NRFX_ASSERT(nrfx_is_word_aligned(src));
|
||||
|
||||
nvmc_write_mode_set();
|
||||
|
||||
nvmc_words_write(addr, src, num_words);
|
||||
|
||||
nvmc_readonly_mode_set();
|
||||
}
|
||||
|
||||
uint32_t nrfx_nvmc_flash_size_get(void)
|
||||
{
|
||||
return flash_total_size_get();
|
||||
}
|
||||
|
||||
uint32_t nrfx_nvmc_flash_page_size_get(void)
|
||||
{
|
||||
return flash_page_size_get();
|
||||
}
|
||||
|
||||
uint32_t nrfx_nvmc_flash_page_count_get(void)
|
||||
{
|
||||
return flash_page_count_get();
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_NVMC_ENABLED)
|
||||
370
modules/nrfx/drivers/src/nrfx_pdm.c
Normal file
370
modules/nrfx/drivers/src/nrfx_pdm.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_PDM_ENABLED)
|
||||
|
||||
#include <nrfx_pdm.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE PDM
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_PDM_EVENT_STARTED ? "NRF_PDM_EVENT_STARTED" : \
|
||||
(event == NRF_PDM_EVENT_STOPPED ? "NRF_PDM_EVENT_STOPPED" : \
|
||||
(event == NRF_PDM_EVENT_END ? "NRF_PDM_EVENT_END" : \
|
||||
"UNKNOWN EVENT")))
|
||||
|
||||
|
||||
/** @brief PDM interface status. */
|
||||
typedef enum
|
||||
{
|
||||
NRFX_PDM_STATE_IDLE,
|
||||
NRFX_PDM_STATE_RUNNING,
|
||||
NRFX_PDM_STATE_STARTING,
|
||||
NRFX_PDM_STATE_STOPPING
|
||||
} nrfx_pdm_state_t;
|
||||
|
||||
/** @brief PDM interface control block.*/
|
||||
typedef struct
|
||||
{
|
||||
nrfx_pdm_event_handler_t event_handler; ///< Event handler function pointer.
|
||||
int16_t * buff_address[2]; ///< Sample buffers.
|
||||
uint16_t buff_length[2]; ///< Length of the sample buffers.
|
||||
nrfx_drv_state_t drv_state; ///< Driver state.
|
||||
volatile nrfx_pdm_state_t op_state; ///< PDM peripheral operation state.
|
||||
uint8_t active_buffer; ///< Number of currently active buffer.
|
||||
uint8_t error; ///< Driver error flag.
|
||||
volatile uint8_t irq_buff_request; ///< Request the next buffer in the ISR.
|
||||
} nrfx_pdm_cb_t;
|
||||
|
||||
static nrfx_pdm_cb_t m_cb;
|
||||
|
||||
|
||||
void nrfx_pdm_irq_handler(void)
|
||||
{
|
||||
if (nrf_pdm_event_check(NRF_PDM_EVENT_STARTED))
|
||||
{
|
||||
nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STARTED));
|
||||
|
||||
uint8_t finished_buffer = m_cb.active_buffer;
|
||||
|
||||
// Check if the next buffer was set before.
|
||||
uint8_t next_buffer = (~m_cb.active_buffer) & 0x01;
|
||||
if (m_cb.buff_address[next_buffer] ||
|
||||
m_cb.op_state == NRFX_PDM_STATE_STARTING)
|
||||
{
|
||||
nrfx_pdm_evt_t evt;
|
||||
evt.error = NRFX_PDM_NO_ERROR;
|
||||
m_cb.error = 0;
|
||||
|
||||
// Release the full buffer if ready and request the next one.
|
||||
if (m_cb.op_state == NRFX_PDM_STATE_STARTING)
|
||||
{
|
||||
evt.buffer_released = 0;
|
||||
m_cb.op_state = NRFX_PDM_STATE_RUNNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.buffer_released = m_cb.buff_address[finished_buffer];
|
||||
m_cb.buff_address[finished_buffer] = 0;
|
||||
m_cb.active_buffer = next_buffer;
|
||||
}
|
||||
evt.buffer_requested = true;
|
||||
m_cb.event_handler(&evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No next buffer available. Report an error.
|
||||
// Do not request the new buffer as it was already done.
|
||||
if (m_cb.error == 0)
|
||||
{
|
||||
nrfx_pdm_evt_t const evt = {
|
||||
.buffer_requested = false,
|
||||
.buffer_released = NULL,
|
||||
.error = NRFX_PDM_ERROR_OVERFLOW
|
||||
};
|
||||
m_cb.error = 1;
|
||||
m_cb.event_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_cb.op_state == NRFX_PDM_STATE_STARTING)
|
||||
{
|
||||
m_cb.op_state = NRFX_PDM_STATE_RUNNING;
|
||||
}
|
||||
}
|
||||
else if (nrf_pdm_event_check(NRF_PDM_EVENT_STOPPED))
|
||||
{
|
||||
nrf_pdm_event_clear(NRF_PDM_EVENT_STOPPED);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STOPPED));
|
||||
nrf_pdm_disable();
|
||||
m_cb.op_state = NRFX_PDM_STATE_IDLE;
|
||||
|
||||
// Release the buffers.
|
||||
nrfx_pdm_evt_t evt;
|
||||
evt.error = NRFX_PDM_NO_ERROR;
|
||||
evt.buffer_requested = false;
|
||||
if (m_cb.buff_address[m_cb.active_buffer])
|
||||
{
|
||||
evt.buffer_released = m_cb.buff_address[m_cb.active_buffer];
|
||||
m_cb.buff_address[m_cb.active_buffer] = 0;
|
||||
m_cb.event_handler(&evt);
|
||||
}
|
||||
|
||||
uint8_t second_buffer = (~m_cb.active_buffer) & 0x01;
|
||||
if (m_cb.buff_address[second_buffer])
|
||||
{
|
||||
evt.buffer_released = m_cb.buff_address[second_buffer];
|
||||
m_cb.buff_address[second_buffer] = 0;
|
||||
m_cb.event_handler(&evt);
|
||||
}
|
||||
m_cb.active_buffer = 0;
|
||||
}
|
||||
|
||||
if (m_cb.irq_buff_request)
|
||||
{
|
||||
nrfx_pdm_evt_t const evt =
|
||||
{
|
||||
.buffer_requested = true,
|
||||
.buffer_released = NULL,
|
||||
.error = NRFX_PDM_NO_ERROR,
|
||||
};
|
||||
m_cb.irq_buff_request = 0;
|
||||
m_cb.event_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_pdm_init(nrfx_pdm_config_t const * p_config,
|
||||
nrfx_pdm_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(event_handler);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_cb.drv_state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (p_config->gain_l > NRF_PDM_GAIN_MAXIMUM ||
|
||||
p_config->gain_r > NRF_PDM_GAIN_MAXIMUM)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_cb.buff_address[0] = 0;
|
||||
m_cb.buff_address[1] = 0;
|
||||
m_cb.active_buffer = 0;
|
||||
m_cb.error = 0;
|
||||
m_cb.event_handler = event_handler;
|
||||
m_cb.op_state = NRFX_PDM_STATE_IDLE;
|
||||
|
||||
nrf_pdm_clock_set(p_config->clock_freq);
|
||||
nrf_pdm_mode_set(p_config->mode, p_config->edge);
|
||||
nrf_pdm_gain_set(p_config->gain_l, p_config->gain_r);
|
||||
|
||||
nrf_gpio_cfg_output(p_config->pin_clk);
|
||||
nrf_gpio_pin_clear(p_config->pin_clk);
|
||||
nrf_gpio_cfg_input(p_config->pin_din, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_pdm_psel_connect(p_config->pin_clk, p_config->pin_din);
|
||||
|
||||
nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED);
|
||||
nrf_pdm_event_clear(NRF_PDM_EVENT_END);
|
||||
nrf_pdm_event_clear(NRF_PDM_EVENT_STOPPED);
|
||||
nrf_pdm_int_enable(NRF_PDM_INT_STARTED | NRF_PDM_INT_STOPPED);
|
||||
NRFX_IRQ_PRIORITY_SET(PDM_IRQn, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(PDM_IRQn);
|
||||
m_cb.drv_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_pdm_uninit(void)
|
||||
{
|
||||
nrf_pdm_disable();
|
||||
nrf_pdm_psel_disconnect();
|
||||
m_cb.drv_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
static void pdm_start()
|
||||
{
|
||||
m_cb.drv_state = NRFX_DRV_STATE_POWERED_ON;
|
||||
nrf_pdm_enable();
|
||||
nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED);
|
||||
nrf_pdm_task_trigger(NRF_PDM_TASK_START);
|
||||
}
|
||||
|
||||
static void pdm_buf_request()
|
||||
{
|
||||
m_cb.irq_buff_request = 1;
|
||||
NRFX_IRQ_PENDING_SET(PDM_IRQn);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_pdm_start(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.drv_state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_cb.op_state != NRFX_PDM_STATE_IDLE)
|
||||
{
|
||||
if (m_cb.op_state == NRFX_PDM_STATE_RUNNING)
|
||||
{
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_cb.op_state = NRFX_PDM_STATE_STARTING;
|
||||
pdm_buf_request();
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_pdm_buffer_set(int16_t * buffer, uint16_t buffer_length)
|
||||
{
|
||||
if (m_cb.drv_state == NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
return NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
if (m_cb.op_state == NRFX_PDM_STATE_STOPPING)
|
||||
{
|
||||
return NRFX_ERROR_BUSY;
|
||||
}
|
||||
if ((buffer == NULL) || (buffer_length > NRFX_PDM_MAX_BUFFER_SIZE))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
// Enter the PDM critical section.
|
||||
NRFX_IRQ_DISABLE(PDM_IRQn);
|
||||
|
||||
uint8_t next_buffer = (~m_cb.active_buffer) & 0x01;
|
||||
if (m_cb.op_state == NRFX_PDM_STATE_STARTING)
|
||||
{
|
||||
next_buffer = 0;
|
||||
}
|
||||
|
||||
if (m_cb.buff_address[next_buffer])
|
||||
{
|
||||
// Buffer already set.
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cb.buff_address[next_buffer] = buffer;
|
||||
m_cb.buff_length[next_buffer] = buffer_length;
|
||||
nrf_pdm_buffer_set((uint32_t *)buffer, buffer_length);
|
||||
|
||||
if (m_cb.drv_state != NRFX_DRV_STATE_POWERED_ON)
|
||||
{
|
||||
pdm_start();
|
||||
}
|
||||
}
|
||||
|
||||
NRFX_IRQ_ENABLE(PDM_IRQn);
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_pdm_stop(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.drv_state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_cb.op_state != NRFX_PDM_STATE_RUNNING)
|
||||
{
|
||||
if (m_cb.op_state == NRFX_PDM_STATE_IDLE ||
|
||||
m_cb.op_state == NRFX_PDM_STATE_STARTING)
|
||||
{
|
||||
nrf_pdm_disable();
|
||||
m_cb.op_state = NRFX_PDM_STATE_IDLE;
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
m_cb.drv_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
m_cb.op_state = NRFX_PDM_STATE_STOPPING;
|
||||
|
||||
nrf_pdm_task_trigger(NRF_PDM_TASK_STOP);
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_PDM_ENABLED)
|
||||
341
modules/nrfx/drivers/src/nrfx_power.c
Normal file
341
modules/nrfx/drivers/src/nrfx_power.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
|
||||
#include <nrfx_power.h>
|
||||
#if defined(REGULATORS_PRESENT)
|
||||
#include <hal/nrf_regulators.h>
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
extern bool nrfx_clock_irq_enabled;
|
||||
extern void nrfx_clock_irq_handler(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @defgroup nrfx_power_internals POWER driver internals
|
||||
* @ingroup nrfx_power
|
||||
*
|
||||
* Internal variables, auxiliary macros and functions of POWER driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This variable is used to check whether common POWER_CLOCK common interrupt
|
||||
* should be disabled or not if @ref nrfx_clock tries to disable the interrupt.
|
||||
*/
|
||||
|
||||
bool nrfx_power_irq_enabled;
|
||||
|
||||
/**
|
||||
* @brief The initialization flag
|
||||
*/
|
||||
|
||||
#define m_initialized nrfx_power_irq_enabled
|
||||
|
||||
/**
|
||||
* @brief The handler of power fail comparator warning event
|
||||
*/
|
||||
static nrfx_power_pofwarn_event_handler_t m_pofwarn_handler;
|
||||
|
||||
#if NRF_POWER_HAS_SLEEPEVT
|
||||
/**
|
||||
* @brief The handler of sleep event handler
|
||||
*/
|
||||
static nrfx_power_sleep_event_handler_t m_sleepevt_handler;
|
||||
#endif
|
||||
|
||||
#if NRF_POWER_HAS_USBREG
|
||||
/**
|
||||
* @brief The handler of USB power events
|
||||
*/
|
||||
static nrfx_power_usb_event_handler_t m_usbevt_handler;
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
nrfx_power_pofwarn_event_handler_t nrfx_power_pof_handler_get(void)
|
||||
{
|
||||
return m_pofwarn_handler;
|
||||
}
|
||||
|
||||
#if NRF_POWER_HAS_USBREG
|
||||
nrfx_power_usb_event_handler_t nrfx_power_usb_handler_get(void)
|
||||
{
|
||||
return m_usbevt_handler;
|
||||
}
|
||||
#endif
|
||||
|
||||
nrfx_err_t nrfx_power_init(nrfx_power_config_t const * p_config)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
if (m_initialized)
|
||||
{
|
||||
return NRFX_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
#if NRF_POWER_HAS_DCDCEN_VDDH
|
||||
nrf_power_dcdcen_vddh_set(p_config->dcdcenhv);
|
||||
#endif
|
||||
#if NRF_POWER_HAS_DCDCEN
|
||||
nrf_power_dcdcen_set(p_config->dcdcen);
|
||||
#else
|
||||
nrf_regulators_dcdcen_set(NRF_REGULATORS, p_config->dcdcen);
|
||||
#endif
|
||||
|
||||
nrfx_power_clock_irq_init();
|
||||
|
||||
m_initialized = true;
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_power_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_initialized);
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
if (!nrfx_clock_irq_enabled)
|
||||
#endif
|
||||
{
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(NRF_POWER));
|
||||
}
|
||||
#if NRF_POWER_HAS_POFCON
|
||||
nrfx_power_pof_uninit();
|
||||
#endif
|
||||
#if NRF_POWER_HAS_SLEEPEVT
|
||||
nrfx_power_sleepevt_uninit();
|
||||
#endif
|
||||
#if NRF_POWER_HAS_USBREG
|
||||
nrfx_power_usbevt_uninit();
|
||||
#endif
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
#if NRF_POWER_HAS_POFCON
|
||||
void nrfx_power_pof_init(nrfx_power_pofwarn_config_t const * p_config)
|
||||
{
|
||||
NRFX_ASSERT(p_config != NULL);
|
||||
|
||||
nrfx_power_pof_uninit();
|
||||
|
||||
if (p_config->handler != NULL)
|
||||
{
|
||||
m_pofwarn_handler = p_config->handler;
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_power_pof_enable(nrfx_power_pofwarn_config_t const * p_config)
|
||||
{
|
||||
nrf_power_pofcon_set(true, p_config->thr);
|
||||
#if NRF_POWER_HAS_VDDH
|
||||
nrf_power_pofcon_vddh_set(p_config->thrvddh);
|
||||
#endif
|
||||
if (m_pofwarn_handler != NULL)
|
||||
{
|
||||
nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_power_pof_disable(void)
|
||||
{
|
||||
nrf_power_pofcon_set(false, NRF_POWER_POFTHR_V27);
|
||||
nrf_power_int_disable(NRF_POWER_INT_POFWARN_MASK);
|
||||
}
|
||||
|
||||
void nrfx_power_pof_uninit(void)
|
||||
{
|
||||
m_pofwarn_handler = NULL;
|
||||
}
|
||||
#endif // NRF_POWER_HAS_POFCON
|
||||
|
||||
#if NRF_POWER_HAS_SLEEPEVT
|
||||
void nrfx_power_sleepevt_init(nrfx_power_sleepevt_config_t const * p_config)
|
||||
{
|
||||
NRFX_ASSERT(p_config != NULL);
|
||||
|
||||
nrfx_power_sleepevt_uninit();
|
||||
if (p_config->handler != NULL)
|
||||
{
|
||||
m_sleepevt_handler = p_config->handler;
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_power_sleepevt_enable(nrfx_power_sleepevt_config_t const * p_config)
|
||||
{
|
||||
uint32_t enmask = 0;
|
||||
if (p_config->en_enter)
|
||||
{
|
||||
enmask |= NRF_POWER_INT_SLEEPENTER_MASK;
|
||||
nrf_power_event_clear(NRF_POWER_EVENT_SLEEPENTER);
|
||||
}
|
||||
if (p_config->en_exit)
|
||||
{
|
||||
enmask |= NRF_POWER_INT_SLEEPEXIT_MASK;
|
||||
nrf_power_event_clear(NRF_POWER_EVENT_SLEEPEXIT);
|
||||
}
|
||||
nrf_power_int_enable(enmask);
|
||||
}
|
||||
|
||||
void nrfx_power_sleepevt_disable(void)
|
||||
{
|
||||
nrf_power_int_disable(
|
||||
NRF_POWER_INT_SLEEPENTER_MASK |
|
||||
NRF_POWER_INT_SLEEPEXIT_MASK);
|
||||
}
|
||||
|
||||
void nrfx_power_sleepevt_uninit(void)
|
||||
{
|
||||
m_sleepevt_handler = NULL;
|
||||
}
|
||||
#endif /* NRF_POWER_HAS_SLEEPEVT */
|
||||
|
||||
#if NRF_POWER_HAS_USBREG
|
||||
void nrfx_power_usbevt_init(nrfx_power_usbevt_config_t const * p_config)
|
||||
{
|
||||
NRFX_ASSERT(p_config != NULL);
|
||||
|
||||
nrfx_power_usbevt_uninit();
|
||||
if (p_config->handler != NULL)
|
||||
{
|
||||
m_usbevt_handler = p_config->handler;
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_power_usbevt_enable(void)
|
||||
{
|
||||
nrf_power_int_enable(
|
||||
NRF_POWER_INT_USBDETECTED_MASK |
|
||||
NRF_POWER_INT_USBREMOVED_MASK |
|
||||
NRF_POWER_INT_USBPWRRDY_MASK);
|
||||
}
|
||||
|
||||
void nrfx_power_usbevt_disable(void)
|
||||
{
|
||||
nrf_power_int_disable(
|
||||
NRF_POWER_INT_USBDETECTED_MASK |
|
||||
NRF_POWER_INT_USBREMOVED_MASK |
|
||||
NRF_POWER_INT_USBPWRRDY_MASK);
|
||||
}
|
||||
|
||||
void nrfx_power_usbevt_uninit(void)
|
||||
{
|
||||
m_usbevt_handler = NULL;
|
||||
}
|
||||
#endif /* NRF_POWER_HAS_USBREG */
|
||||
|
||||
|
||||
void nrfx_power_irq_handler(void)
|
||||
{
|
||||
uint32_t enabled = nrf_power_int_enable_get();
|
||||
|
||||
#if NRF_POWER_HAS_POFCON
|
||||
if ((0 != (enabled & NRF_POWER_INT_POFWARN_MASK)) &&
|
||||
nrf_power_event_get_and_clear(NRF_POWER_EVENT_POFWARN))
|
||||
{
|
||||
/* Cannot be null if event is enabled */
|
||||
NRFX_ASSERT(m_pofwarn_handler != NULL);
|
||||
m_pofwarn_handler();
|
||||
}
|
||||
#endif
|
||||
#if NRF_POWER_HAS_SLEEPEVT
|
||||
if ((0 != (enabled & NRF_POWER_INT_SLEEPENTER_MASK)) &&
|
||||
nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPENTER))
|
||||
{
|
||||
/* Cannot be null if event is enabled */
|
||||
NRFX_ASSERT(m_sleepevt_handler != NULL);
|
||||
m_sleepevt_handler(NRFX_POWER_SLEEP_EVT_ENTER);
|
||||
}
|
||||
if ((0 != (enabled & NRF_POWER_INT_SLEEPEXIT_MASK)) &&
|
||||
nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPEXIT))
|
||||
{
|
||||
/* Cannot be null if event is enabled */
|
||||
NRFX_ASSERT(m_sleepevt_handler != NULL);
|
||||
m_sleepevt_handler(NRFX_POWER_SLEEP_EVT_EXIT);
|
||||
}
|
||||
#endif
|
||||
#if NRF_POWER_HAS_USBREG
|
||||
if ((0 != (enabled & NRF_POWER_INT_USBDETECTED_MASK)) &&
|
||||
nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBDETECTED))
|
||||
{
|
||||
/* Cannot be null if event is enabled */
|
||||
NRFX_ASSERT(m_usbevt_handler != NULL);
|
||||
m_usbevt_handler(NRFX_POWER_USB_EVT_DETECTED);
|
||||
}
|
||||
if ((0 != (enabled & NRF_POWER_INT_USBREMOVED_MASK)) &&
|
||||
nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBREMOVED))
|
||||
{
|
||||
/* Cannot be null if event is enabled */
|
||||
NRFX_ASSERT(m_usbevt_handler != NULL);
|
||||
m_usbevt_handler(NRFX_POWER_USB_EVT_REMOVED);
|
||||
}
|
||||
if ((0 != (enabled & NRF_POWER_INT_USBPWRRDY_MASK)) &&
|
||||
nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBPWRRDY))
|
||||
{
|
||||
/* Cannot be null if event is enabled */
|
||||
NRFX_ASSERT(m_usbevt_handler != NULL);
|
||||
m_usbevt_handler(NRFX_POWER_USB_EVT_READY);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_CLOCK_ENABLED)
|
||||
/*
|
||||
* If both POWER and CLOCK drivers are used, a common IRQ handler function must
|
||||
* be used that calls the handlers in these two drivers. This is because these
|
||||
* two peripherals share one interrupt.
|
||||
* This function is located here, not in a separate nrfx_power_clock.c file,
|
||||
* so that it does not end up as the only symbol in a separate object when
|
||||
* a library with nrfx is created. In such case, forcing a linker to use this
|
||||
* function instead of another one defined as weak will require additional
|
||||
* actions, and might be even impossible.
|
||||
*/
|
||||
void nrfx_power_clock_irq_handler(void)
|
||||
{
|
||||
nrfx_power_irq_handler();
|
||||
nrfx_clock_irq_handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_POWER_ENABLED)
|
||||
530
modules/nrfx/drivers/src/nrfx_ppi.c
Normal file
530
modules/nrfx/drivers/src/nrfx_ppi.c
Normal file
@@ -0,0 +1,530 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_PPI_ENABLED)
|
||||
|
||||
#include <nrfx_ppi.h>
|
||||
|
||||
#define NRFX_LOG_MODULE PPI
|
||||
#include <nrfx_log.h>
|
||||
|
||||
|
||||
static uint32_t m_channels_allocated; /**< Bitmap representing channels availability. 1 when a channel is allocated, 0 otherwise. */
|
||||
static uint8_t m_groups_allocated; /**< Bitmap representing groups availability. 1 when a group is allocated, 0 otherwise.*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compute a group mask (needed for driver internals, not used for NRF_PPI registers).
|
||||
*
|
||||
* @param[in] group Group number to transform to a mask.
|
||||
*
|
||||
* @retval Group mask.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t group_to_mask(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return (1uL << (uint32_t) group);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether a channel is a programmable channel and can be used by an application.
|
||||
*
|
||||
* @param[in] channel Channel to check.
|
||||
*
|
||||
* @retval true The channel is a programmable application channel.
|
||||
* @retval false The channel is used by a stack (for example SoftDevice) or is preprogrammed.
|
||||
*/
|
||||
__STATIC_INLINE bool is_programmable_app_channel(nrf_ppi_channel_t channel)
|
||||
{
|
||||
return ((NRFX_PPI_PROG_APP_CHANNELS_MASK & nrfx_ppi_channel_to_mask(channel)) != 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether channels can be used by an application.
|
||||
*
|
||||
* @param[in] channel_mask Channel mask to check.
|
||||
*
|
||||
* @retval true All specified channels can be used by an application.
|
||||
* @retval false At least one specified channel is used by a stack (for example SoftDevice).
|
||||
*/
|
||||
__STATIC_INLINE bool are_app_channels(uint32_t channel_mask)
|
||||
{
|
||||
//lint -e(587)
|
||||
return ((~(NRFX_PPI_ALL_APP_CHANNELS_MASK) & channel_mask) == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether a channel can be used by an application.
|
||||
*
|
||||
* @param[in] channel Channel to check.
|
||||
*
|
||||
* @retval true The channel can be used by an application.
|
||||
* @retval false The channel is used by a stack (for example SoftDevice).
|
||||
*/
|
||||
__STATIC_INLINE bool is_app_channel(nrf_ppi_channel_t channel)
|
||||
{
|
||||
return are_app_channels(nrfx_ppi_channel_to_mask(channel));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether a channel group can be used by an application.
|
||||
*
|
||||
* @param[in] group Group to check.
|
||||
*
|
||||
* @retval true The group is an application group.
|
||||
* @retval false The group is not an application group (this group either does not exist or
|
||||
* it is used by a stack (for example SoftDevice)).
|
||||
*/
|
||||
__STATIC_INLINE bool is_app_group(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return ((NRFX_PPI_ALL_APP_GROUPS_MASK & group_to_mask(group)) != 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether a channel is allocated.
|
||||
*
|
||||
* @param[in] channel_num Channel number to check.
|
||||
*
|
||||
* @retval true The channel is allocated.
|
||||
* @retval false The channel is not allocated.
|
||||
*/
|
||||
__STATIC_INLINE bool is_allocated_channel(nrf_ppi_channel_t channel)
|
||||
{
|
||||
return ((m_channels_allocated & nrfx_ppi_channel_to_mask(channel)) != 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set channel allocated indication.
|
||||
*
|
||||
* @param[in] channel_num Specifies the channel to set the "allocated" indication.
|
||||
*/
|
||||
__STATIC_INLINE void channel_allocated_set(nrf_ppi_channel_t channel)
|
||||
{
|
||||
m_channels_allocated |= nrfx_ppi_channel_to_mask(channel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear channel allocated indication.
|
||||
*
|
||||
* @param[in] channel_num Specifies the channel to clear the "allocated" indication.
|
||||
*/
|
||||
__STATIC_INLINE void channel_allocated_clr(nrf_ppi_channel_t channel)
|
||||
{
|
||||
m_channels_allocated &= ~nrfx_ppi_channel_to_mask(channel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear all allocated channels.
|
||||
*/
|
||||
__STATIC_INLINE void channel_allocated_clr_all(void)
|
||||
{
|
||||
m_channels_allocated &= ~NRFX_PPI_ALL_APP_CHANNELS_MASK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether a group is allocated.
|
||||
*
|
||||
* @param[in] group_num Group number to check.
|
||||
*
|
||||
* @retval true The group is allocated.
|
||||
* false The group is not allocated.
|
||||
*/
|
||||
__STATIC_INLINE bool is_allocated_group(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
return ((m_groups_allocated & group_to_mask(group)) != 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set group allocated indication.
|
||||
*
|
||||
* @param[in] group_num Specifies the group to set the "allocated" indication.
|
||||
*/
|
||||
__STATIC_INLINE void group_allocated_set(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
m_groups_allocated |= group_to_mask(group);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear group allocated indication.
|
||||
*
|
||||
* @param[in] group_num Specifies the group to clear the "allocated" indication.
|
||||
*/
|
||||
__STATIC_INLINE void group_allocated_clr(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
m_groups_allocated &= ~group_to_mask(group);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear all allocated groups.
|
||||
*/
|
||||
__STATIC_INLINE void group_allocated_clr_all()
|
||||
{
|
||||
m_groups_allocated &= ~NRFX_PPI_ALL_APP_GROUPS_MASK;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_ppi_free_all(void)
|
||||
{
|
||||
uint32_t mask = NRFX_PPI_ALL_APP_GROUPS_MASK;
|
||||
nrf_ppi_channel_group_t group;
|
||||
|
||||
// Disable all channels and groups
|
||||
nrf_ppi_channels_disable(NRFX_PPI_ALL_APP_CHANNELS_MASK);
|
||||
|
||||
for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
|
||||
{
|
||||
if (mask & group_to_mask(group))
|
||||
{
|
||||
nrf_ppi_channel_group_clear(group);
|
||||
}
|
||||
}
|
||||
channel_allocated_clr_all();
|
||||
group_allocated_clr_all();
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_channel_alloc(nrf_ppi_channel_t * p_channel)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
nrf_ppi_channel_t channel;
|
||||
uint32_t mask = 0;
|
||||
err_code = NRFX_ERROR_NO_MEM;
|
||||
|
||||
mask = NRFX_PPI_PROG_APP_CHANNELS_MASK;
|
||||
for (channel = NRF_PPI_CHANNEL0;
|
||||
mask != 0;
|
||||
mask &= ~nrfx_ppi_channel_to_mask(channel), channel++)
|
||||
{
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
if ((mask & nrfx_ppi_channel_to_mask(channel)) && (!is_allocated_channel(channel)))
|
||||
{
|
||||
channel_allocated_set(channel);
|
||||
*p_channel = channel;
|
||||
err_code = NRFX_SUCCESS;
|
||||
}
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
if (err_code == NRFX_SUCCESS)
|
||||
{
|
||||
NRFX_LOG_INFO("Allocated channel: %d.", channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_channel_free(nrf_ppi_channel_t channel)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_programmable_app_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
// First disable this channel
|
||||
nrf_ppi_channel_disable(channel);
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
channel_allocated_clr(channel);
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep)
|
||||
{
|
||||
if ((uint32_t *)eep == NULL || (uint32_t *)tep == NULL)
|
||||
{
|
||||
return NRFX_ERROR_NULL;
|
||||
}
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_programmable_app_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else if (!is_allocated_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_ppi_channel_endpoint_setup(channel, eep, tep);
|
||||
NRFX_LOG_INFO("Assigned channel: %d, event end point: %x, task end point: %x.",
|
||||
channel,
|
||||
eep,
|
||||
tep);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_ppi_channel_fork_assign(nrf_ppi_channel_t channel, uint32_t fork_tep)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
#ifdef PPI_FEATURE_FORKS_PRESENT
|
||||
if (!is_allocated_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_ppi_fork_endpoint_setup(channel, fork_tep);
|
||||
NRFX_LOG_INFO("Fork assigned channel: %d, task end point: %d.", channel, fork_tep);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
#else
|
||||
err_code = NRFX_ERROR_NOT_SUPPORTED;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
#endif
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_ppi_channel_enable(nrf_ppi_channel_t channel)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_app_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_ppi_channel_enable(channel);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_channel_disable(nrf_ppi_channel_t channel)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_app_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_ppi_channel_disable(channel);
|
||||
err_code = NRFX_SUCCESS;
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_group_alloc(nrf_ppi_channel_group_t * p_group)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
uint32_t mask = 0;
|
||||
nrf_ppi_channel_group_t group;
|
||||
|
||||
err_code = NRFX_ERROR_NO_MEM;
|
||||
|
||||
mask = NRFX_PPI_ALL_APP_GROUPS_MASK;
|
||||
for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
|
||||
{
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
if ((mask & group_to_mask(group)) && (!is_allocated_group(group)))
|
||||
{
|
||||
group_allocated_set(group);
|
||||
*p_group = group;
|
||||
err_code = NRFX_SUCCESS;
|
||||
}
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
if (err_code == NRFX_SUCCESS)
|
||||
{
|
||||
NRFX_LOG_INFO("Allocated group: %d.", group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_group_free(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_app_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (!is_allocated_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_ppi_group_disable(group);
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
group_allocated_clr(group);
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_group_enable(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_app_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else if (!is_allocated_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_ppi_group_enable(group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_ppi_group_disable(nrf_ppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_app_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_ppi_group_disable(group);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_ppi_channels_remove_from_group(uint32_t channel_mask,
|
||||
nrf_ppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_app_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else if (!is_allocated_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else if (!are_app_channels(channel_mask))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
nrf_ppi_channels_remove_from_group(channel_mask, group);
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_ppi_channels_include_in_group(uint32_t channel_mask,
|
||||
nrf_ppi_channel_group_t group)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (!is_app_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else if (!is_allocated_group(group))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else if (!are_app_channels(channel_mask))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
nrf_ppi_channels_include_in_group(channel_mask, group);
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PPI_ENABLED)
|
||||
523
modules/nrfx/drivers/src/nrfx_pwm.c
Normal file
523
modules/nrfx/drivers/src/nrfx_pwm.c
Normal file
@@ -0,0 +1,523 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_PWM_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_PWM0_ENABLED) || NRFX_CHECK(NRFX_PWM1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_PWM2_ENABLED) || NRFX_CHECK(NRFX_PWM3_ENABLED))
|
||||
#error "No enabled PWM instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_pwm.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE PWM
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
// The workaround uses interrupts to wake up the CPU and ensure it is active
|
||||
// when PWM is about to start a DMA transfer. For initial transfer, done when
|
||||
// a playback is started via PPI, a specific EGU instance is used to generate
|
||||
// an interrupt. During the playback, the PWM interrupt triggered on SEQEND
|
||||
// event of a preceding sequence is used to protect the transfer done for
|
||||
// the next sequence to be played.
|
||||
#include <hal/nrf_egu.h>
|
||||
#define USE_DMA_ISSUE_WORKAROUND
|
||||
#endif
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
#define EGU_IRQn(i) EGU_IRQn_(i)
|
||||
#define EGU_IRQn_(i) SWI##i##_EGU##i##_IRQn
|
||||
#define EGU_IRQHandler(i) EGU_IRQHandler_(i)
|
||||
#define EGU_IRQHandler_(i) nrfx_swi_##i##_irq_handler
|
||||
#define DMA_ISSUE_EGU_IDX NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE
|
||||
#define DMA_ISSUE_EGU NRFX_CONCAT_2(NRF_EGU, DMA_ISSUE_EGU_IDX)
|
||||
#define DMA_ISSUE_EGU_IRQn EGU_IRQn(DMA_ISSUE_EGU_IDX)
|
||||
#define DMA_ISSUE_EGU_IRQHandler EGU_IRQHandler(DMA_ISSUE_EGU_IDX)
|
||||
#endif
|
||||
|
||||
// Control block - driver instance local data.
|
||||
typedef struct
|
||||
{
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
uint32_t starting_task_address;
|
||||
#endif
|
||||
nrfx_pwm_handler_t handler;
|
||||
nrfx_drv_state_t volatile state;
|
||||
uint8_t flags;
|
||||
} pwm_control_block_t;
|
||||
static pwm_control_block_t m_cb[NRFX_PWM_ENABLED_COUNT];
|
||||
|
||||
static void configure_pins(nrfx_pwm_t const * const p_instance,
|
||||
nrfx_pwm_config_t const * p_config)
|
||||
{
|
||||
uint32_t out_pins[NRF_PWM_CHANNEL_COUNT];
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < NRF_PWM_CHANNEL_COUNT; ++i)
|
||||
{
|
||||
uint8_t output_pin = p_config->output_pins[i];
|
||||
if (output_pin != NRFX_PWM_PIN_NOT_USED)
|
||||
{
|
||||
bool inverted = output_pin & NRFX_PWM_PIN_INVERTED;
|
||||
out_pins[i] = output_pin & ~NRFX_PWM_PIN_INVERTED;
|
||||
|
||||
if (inverted)
|
||||
{
|
||||
nrf_gpio_pin_set(out_pins[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_clear(out_pins[i]);
|
||||
}
|
||||
|
||||
nrf_gpio_cfg_output(out_pins[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_pins[i] = NRF_PWM_PIN_NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
nrf_pwm_pins_set(p_instance->p_registers, out_pins);
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_pwm_init(nrfx_pwm_t const * const p_instance,
|
||||
nrfx_pwm_config_t const * p_config,
|
||||
nrfx_pwm_handler_t handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
p_cb->handler = handler;
|
||||
|
||||
configure_pins(p_instance, p_config);
|
||||
|
||||
nrf_pwm_enable(p_instance->p_registers);
|
||||
nrf_pwm_configure(p_instance->p_registers,
|
||||
p_config->base_clock, p_config->count_mode, p_config->top_value);
|
||||
nrf_pwm_decoder_set(p_instance->p_registers,
|
||||
p_config->load_mode, p_config->step_mode);
|
||||
|
||||
nrf_pwm_shorts_set(p_instance->p_registers, 0);
|
||||
nrf_pwm_int_set(p_instance->p_registers, 0);
|
||||
nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_LOOPSDONE);
|
||||
nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND0);
|
||||
nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND1);
|
||||
nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);
|
||||
|
||||
// The workaround for nRF52 Anomaly 109 "protects" DMA transfers by handling
|
||||
// interrupts generated on SEQEND0 and SEQEND1 events (this ensures that
|
||||
// the 64 MHz clock is ready when data for the next sequence to be played
|
||||
// is read). Therefore, the PWM interrupt must be enabled even if the event
|
||||
// handler is not used.
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
NRFX_IRQ_PRIORITY_SET(DMA_ISSUE_EGU_IRQn, p_config->irq_priority);
|
||||
NRFX_IRQ_ENABLE(DMA_ISSUE_EGU_IRQn);
|
||||
#else
|
||||
if (p_cb->handler)
|
||||
#endif
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_registers),
|
||||
p_config->irq_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_registers));
|
||||
}
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_pwm_uninit(nrfx_pwm_t const * const p_instance)
|
||||
{
|
||||
pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_registers));
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
NRFX_IRQ_DISABLE(DMA_ISSUE_EGU_IRQn);
|
||||
#endif
|
||||
|
||||
nrf_pwm_disable(p_instance->p_registers);
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t start_playback(nrfx_pwm_t const * const p_instance,
|
||||
pwm_control_block_t * p_cb,
|
||||
uint8_t flags,
|
||||
nrf_pwm_task_t starting_task)
|
||||
{
|
||||
p_cb->state = NRFX_DRV_STATE_POWERED_ON;
|
||||
p_cb->flags = flags;
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
// The notification about finished playback is by default enabled,
|
||||
// but this can be suppressed.
|
||||
// The notification that the peripheral has stopped is always enabled.
|
||||
uint32_t int_mask = NRF_PWM_INT_LOOPSDONE_MASK |
|
||||
NRF_PWM_INT_STOPPED_MASK;
|
||||
|
||||
// The workaround for nRF52 Anomaly 109 "protects" DMA transfers by
|
||||
// handling interrupts generated on SEQEND0 and SEQEND1 events (see
|
||||
// 'nrfx_pwm_init'), hence these events must be always enabled
|
||||
// to generate interrupts.
|
||||
// However, the user handler is called for them only when requested
|
||||
// (see 'irq_handler').
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
int_mask |= NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK;
|
||||
#else
|
||||
if (flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ0)
|
||||
{
|
||||
int_mask |= NRF_PWM_INT_SEQEND0_MASK;
|
||||
}
|
||||
if (flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ1)
|
||||
{
|
||||
int_mask |= NRF_PWM_INT_SEQEND1_MASK;
|
||||
}
|
||||
#endif
|
||||
if (flags & NRFX_PWM_FLAG_NO_EVT_FINISHED)
|
||||
{
|
||||
int_mask &= ~NRF_PWM_INT_LOOPSDONE_MASK;
|
||||
}
|
||||
|
||||
nrf_pwm_int_set(p_instance->p_registers, int_mask);
|
||||
}
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
else
|
||||
{
|
||||
nrf_pwm_int_set(p_instance->p_registers,
|
||||
NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);
|
||||
|
||||
if (flags & NRFX_PWM_FLAG_START_VIA_TASK)
|
||||
{
|
||||
uint32_t starting_task_address =
|
||||
nrf_pwm_task_address_get(p_instance->p_registers, starting_task);
|
||||
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
// To "protect" the initial DMA transfer it is required to start
|
||||
// the PWM by triggering the proper task from EGU interrupt handler,
|
||||
// it is not safe to do it directly via PPI.
|
||||
p_cb->starting_task_address = starting_task_address;
|
||||
nrf_egu_int_enable(DMA_ISSUE_EGU,
|
||||
nrf_egu_int_get(DMA_ISSUE_EGU, p_instance->drv_inst_idx));
|
||||
return (uint32_t)nrf_egu_task_trigger_address_get(DMA_ISSUE_EGU,
|
||||
p_instance->drv_inst_idx);
|
||||
#else
|
||||
return starting_task_address;
|
||||
#endif
|
||||
}
|
||||
|
||||
nrf_pwm_task_trigger(p_instance->p_registers, starting_task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrfx_pwm_simple_playback(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_sequence_t const * p_sequence,
|
||||
uint16_t playback_count,
|
||||
uint32_t flags)
|
||||
{
|
||||
pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(playback_count > 0);
|
||||
NRFX_ASSERT(nrfx_is_in_ram(p_sequence->values.p_raw));
|
||||
|
||||
// To take advantage of the looping mechanism, we need to use both sequences
|
||||
// (single sequence can be played back only once).
|
||||
nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence);
|
||||
nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence);
|
||||
bool odd = (playback_count & 1);
|
||||
nrf_pwm_loop_set(p_instance->p_registers,
|
||||
(playback_count / 2) + (odd ? 1 : 0));
|
||||
|
||||
uint32_t shorts_mask;
|
||||
if (flags & NRFX_PWM_FLAG_STOP)
|
||||
{
|
||||
shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;
|
||||
}
|
||||
else if (flags & NRFX_PWM_FLAG_LOOP)
|
||||
{
|
||||
shorts_mask = odd ? NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK
|
||||
: NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
shorts_mask = 0;
|
||||
}
|
||||
nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask);
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, sequence length: %d.",
|
||||
__func__,
|
||||
p_sequence->length);
|
||||
NRFX_LOG_DEBUG("Sequence data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_sequence->values.p_raw,
|
||||
p_sequence->length * sizeof(uint16_t));
|
||||
return start_playback(p_instance, p_cb, flags,
|
||||
odd ? NRF_PWM_TASK_SEQSTART1 : NRF_PWM_TASK_SEQSTART0);
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrfx_pwm_complex_playback(nrfx_pwm_t const * const p_instance,
|
||||
nrf_pwm_sequence_t const * p_sequence_0,
|
||||
nrf_pwm_sequence_t const * p_sequence_1,
|
||||
uint16_t playback_count,
|
||||
uint32_t flags)
|
||||
{
|
||||
pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(playback_count > 0);
|
||||
NRFX_ASSERT(nrfx_is_in_ram(p_sequence_0->values.p_raw));
|
||||
NRFX_ASSERT(nrfx_is_in_ram(p_sequence_1->values.p_raw));
|
||||
|
||||
nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence_0);
|
||||
nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence_1);
|
||||
nrf_pwm_loop_set(p_instance->p_registers, playback_count);
|
||||
|
||||
uint32_t shorts_mask;
|
||||
if (flags & NRFX_PWM_FLAG_STOP)
|
||||
{
|
||||
shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;
|
||||
}
|
||||
else if (flags & NRFX_PWM_FLAG_LOOP)
|
||||
{
|
||||
shorts_mask = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
shorts_mask = 0;
|
||||
}
|
||||
nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask);
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, sequence 0 length: %d.",
|
||||
__func__,
|
||||
p_sequence_0->length);
|
||||
NRFX_LOG_INFO("Function: %s, sequence 1 length: %d.",
|
||||
__func__,
|
||||
p_sequence_1->length);
|
||||
NRFX_LOG_DEBUG("Sequence 0 data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_sequence_0->values.p_raw,
|
||||
p_sequence_0->length * sizeof(uint16_t));
|
||||
NRFX_LOG_DEBUG("Sequence 1 data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_sequence_1->values.p_raw,
|
||||
p_sequence_1->length * sizeof(uint16_t));
|
||||
return start_playback(p_instance, p_cb, flags, NRF_PWM_TASK_SEQSTART0);
|
||||
}
|
||||
|
||||
|
||||
bool nrfx_pwm_stop(nrfx_pwm_t const * const p_instance,
|
||||
bool wait_until_stopped)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
bool ret_val = false;
|
||||
|
||||
// Deactivate shortcuts before triggering the STOP task, otherwise the PWM
|
||||
// could be immediately started again if the LOOPSDONE event occurred in
|
||||
// the same peripheral clock cycle as the STOP task was triggered.
|
||||
nrf_pwm_shorts_set(p_instance->p_registers, 0);
|
||||
|
||||
// Trigger the STOP task even if the PWM appears to be already stopped.
|
||||
// It won't harm, but it could help if for some strange reason the stopped
|
||||
// status was not reported correctly.
|
||||
nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_STOP);
|
||||
|
||||
if (nrfx_pwm_is_stopped(p_instance))
|
||||
{
|
||||
ret_val = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
do {
|
||||
if (nrfx_pwm_is_stopped(p_instance))
|
||||
{
|
||||
ret_val = true;
|
||||
break;
|
||||
}
|
||||
} while (wait_until_stopped);
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("%s returned %d.", __func__, ret_val);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
bool nrfx_pwm_is_stopped(nrfx_pwm_t const * const p_instance)
|
||||
{
|
||||
pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
bool ret_val = false;
|
||||
|
||||
// If the event handler is used (interrupts are enabled), the state will
|
||||
// be changed in interrupt handler when the STOPPED event occurs.
|
||||
if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
|
||||
{
|
||||
ret_val = true;
|
||||
}
|
||||
// If interrupts are disabled, we must check the STOPPED event here.
|
||||
if (nrf_pwm_event_check(p_instance->p_registers, NRF_PWM_EVENT_STOPPED))
|
||||
{
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Disabled.");
|
||||
ret_val = true;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("%s returned %d.", __func__, ret_val);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static void irq_handler(NRF_PWM_Type * p_pwm, pwm_control_block_t * p_cb)
|
||||
{
|
||||
// The user handler is called for SEQEND0 and SEQEND1 events only when the
|
||||
// user asks for it (by setting proper flags when starting the playback).
|
||||
if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND0))
|
||||
{
|
||||
nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND0);
|
||||
if ((p_cb->flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ0) && p_cb->handler)
|
||||
{
|
||||
p_cb->handler(NRFX_PWM_EVT_END_SEQ0);
|
||||
}
|
||||
}
|
||||
if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND1))
|
||||
{
|
||||
nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND1);
|
||||
if ((p_cb->flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ1) && p_cb->handler)
|
||||
{
|
||||
p_cb->handler(NRFX_PWM_EVT_END_SEQ1);
|
||||
}
|
||||
}
|
||||
// For LOOPSDONE the handler is called by default, but the user can disable
|
||||
// this (via flags).
|
||||
if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_LOOPSDONE))
|
||||
{
|
||||
nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_LOOPSDONE);
|
||||
if (!(p_cb->flags & NRFX_PWM_FLAG_NO_EVT_FINISHED) && p_cb->handler)
|
||||
{
|
||||
p_cb->handler(NRFX_PWM_EVT_FINISHED);
|
||||
}
|
||||
}
|
||||
|
||||
// The STOPPED event is always propagated to the user handler.
|
||||
if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_STOPPED))
|
||||
{
|
||||
nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_STOPPED);
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
if (p_cb->handler)
|
||||
{
|
||||
p_cb->handler(NRFX_PWM_EVT_STOPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
// See 'start_playback' why this is needed.
|
||||
void DMA_ISSUE_EGU_IRQHandler(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NRFX_PWM_ENABLED_COUNT; ++i)
|
||||
{
|
||||
volatile uint32_t * p_event_reg =
|
||||
nrf_egu_event_triggered_address_get(DMA_ISSUE_EGU, i);
|
||||
if (*p_event_reg)
|
||||
{
|
||||
*p_event_reg = 0;
|
||||
*(volatile uint32_t *)(m_cb[i].starting_task_address) = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if NRFX_CHECK(NRFX_PWM0_ENABLED)
|
||||
void nrfx_pwm_0_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_PWM0, &m_cb[NRFX_PWM0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_PWM1_ENABLED)
|
||||
void nrfx_pwm_1_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_PWM1, &m_cb[NRFX_PWM1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_PWM2_ENABLED)
|
||||
void nrfx_pwm_2_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_PWM2, &m_cb[NRFX_PWM2_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_PWM3_ENABLED)
|
||||
void nrfx_pwm_3_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_PWM3, &m_cb[NRFX_PWM3_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_PWM_ENABLED)
|
||||
204
modules/nrfx/drivers/src/nrfx_qdec.c
Normal file
204
modules/nrfx/drivers/src/nrfx_qdec.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_QDEC_ENABLED)
|
||||
|
||||
#include <nrfx_qdec.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE QDEC
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_QDEC_EVENT_SAMPLERDY ? "NRF_QDEC_EVENT_SAMPLERDY" : \
|
||||
(event == NRF_QDEC_EVENT_REPORTRDY ? "NRF_QDEC_EVENT_REPORTRDY" : \
|
||||
(event == NRF_QDEC_EVENT_ACCOF ? "NRF_QDEC_EVENT_ACCOF" : \
|
||||
"UNKNOWN EVENT")))
|
||||
|
||||
|
||||
static nrfx_qdec_event_handler_t m_qdec_event_handler = NULL;
|
||||
static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
|
||||
void nrfx_qdec_irq_handler(void)
|
||||
{
|
||||
nrfx_qdec_event_t event;
|
||||
if ( nrf_qdec_event_check(NRF_QDEC_EVENT_SAMPLERDY) &&
|
||||
nrf_qdec_int_enable_check(NRF_QDEC_INT_SAMPLERDY_MASK) )
|
||||
{
|
||||
nrf_qdec_event_clear(NRF_QDEC_EVENT_SAMPLERDY);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_SAMPLERDY));
|
||||
|
||||
event.type = NRF_QDEC_EVENT_SAMPLERDY;
|
||||
event.data.sample.value = (int8_t)nrf_qdec_sample_get();
|
||||
m_qdec_event_handler(event);
|
||||
}
|
||||
|
||||
if ( nrf_qdec_event_check(NRF_QDEC_EVENT_REPORTRDY) &&
|
||||
nrf_qdec_int_enable_check(NRF_QDEC_INT_REPORTRDY_MASK) )
|
||||
{
|
||||
nrf_qdec_event_clear(NRF_QDEC_EVENT_REPORTRDY);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_REPORTRDY));
|
||||
|
||||
event.type = NRF_QDEC_EVENT_REPORTRDY;
|
||||
|
||||
event.data.report.acc = (int16_t)nrf_qdec_accread_get();
|
||||
event.data.report.accdbl = (uint16_t)nrf_qdec_accdblread_get();
|
||||
m_qdec_event_handler(event);
|
||||
}
|
||||
|
||||
if ( nrf_qdec_event_check(NRF_QDEC_EVENT_ACCOF) &&
|
||||
nrf_qdec_int_enable_check(NRF_QDEC_INT_ACCOF_MASK) )
|
||||
{
|
||||
nrf_qdec_event_clear(NRF_QDEC_EVENT_ACCOF);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_ACCOF));
|
||||
|
||||
event.type = NRF_QDEC_EVENT_ACCOF;
|
||||
m_qdec_event_handler(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_qdec_init(nrfx_qdec_config_t const * p_config,
|
||||
nrfx_qdec_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(event_handler);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_qdec_event_handler = event_handler;
|
||||
|
||||
nrf_qdec_sampleper_set(p_config->sampleper);
|
||||
nrf_gpio_cfg_input(p_config->psela, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_cfg_input(p_config->pselb, NRF_GPIO_PIN_NOPULL);
|
||||
if (p_config->pselled != NRF_QDEC_LED_NOT_CONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_input(p_config->pselled, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_qdec_ledpre_set(p_config->ledpre);
|
||||
nrf_qdec_ledpol_set(p_config->ledpol);
|
||||
}
|
||||
nrf_qdec_pio_assign(p_config->psela, p_config->pselb, p_config->pselled);
|
||||
nrf_qdec_shorts_enable(NRF_QDEC_SHORT_REPORTRDY_READCLRACC_MASK);
|
||||
|
||||
if (p_config->dbfen)
|
||||
{
|
||||
nrf_qdec_dbfen_enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_qdec_dbfen_disable();
|
||||
}
|
||||
|
||||
uint32_t int_mask = NRF_QDEC_INT_ACCOF_MASK;
|
||||
|
||||
if (p_config->reportper != NRF_QDEC_REPORTPER_DISABLED)
|
||||
{
|
||||
nrf_qdec_reportper_set(p_config->reportper);
|
||||
int_mask |= NRF_QDEC_INT_REPORTRDY_MASK;
|
||||
}
|
||||
|
||||
if (p_config->sample_inten)
|
||||
{
|
||||
int_mask |= NRF_QDEC_INT_SAMPLERDY_MASK;
|
||||
}
|
||||
|
||||
nrf_qdec_int_enable(int_mask);
|
||||
NRFX_IRQ_PRIORITY_SET(QDEC_IRQn, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(QDEC_IRQn);
|
||||
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_qdec_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
nrfx_qdec_disable();
|
||||
NRFX_IRQ_DISABLE(QDEC_IRQn);
|
||||
m_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
void nrfx_qdec_enable(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
nrf_qdec_enable();
|
||||
nrf_qdec_task_trigger(NRF_QDEC_TASK_START);
|
||||
m_state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Enabled.");
|
||||
}
|
||||
|
||||
void nrfx_qdec_disable(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
|
||||
nrf_qdec_task_trigger(NRF_QDEC_TASK_STOP);
|
||||
nrf_qdec_disable();
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Disabled.");
|
||||
}
|
||||
|
||||
void nrfx_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
|
||||
nrf_qdec_task_trigger(NRF_QDEC_TASK_READCLRACC);
|
||||
|
||||
*p_acc = (int16_t)nrf_qdec_accread_get();
|
||||
*p_accdbl = (int16_t)nrf_qdec_accdblread_get();
|
||||
|
||||
NRFX_LOG_DEBUG("Accumulators data, ACC register:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_acc, sizeof(p_acc[0]));
|
||||
NRFX_LOG_DEBUG("Accumulators data, ACCDBL register:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_accdbl, sizeof(p_accdbl[0]));
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_QDEC_ENABLED)
|
||||
417
modules/nrfx/drivers/src/nrfx_qspi.c
Normal file
417
modules/nrfx/drivers/src/nrfx_qspi.c
Normal file
@@ -0,0 +1,417 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_QSPI_ENABLED)
|
||||
|
||||
#include <nrfx_qspi.h>
|
||||
|
||||
/** @brief Command byte used to read status register. */
|
||||
#define QSPI_STD_CMD_RDSR 0x05
|
||||
|
||||
/** @brief Byte used to mask status register and retrieve the write-in-progess bit. */
|
||||
#define QSPI_MEM_STATUSREG_WIP_Pos 0x01
|
||||
|
||||
/** @brief Default time used in timeout function. */
|
||||
#define QSPI_DEF_WAIT_TIME_US 10
|
||||
|
||||
/** @brief Default number of tries in timeout function. */
|
||||
#define QSPI_DEF_WAIT_ATTEMPTS 100
|
||||
|
||||
/** @brief Control block - driver instance local data. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_qspi_handler_t handler; /**< Handler. */
|
||||
nrfx_drv_state_t state; /**< Driver state. */
|
||||
volatile bool is_busy; /**< Flag indicating that an operation is currently being performed. */
|
||||
void * p_context; /**< Driver context used in interrupt. */
|
||||
} qspi_control_block_t;
|
||||
|
||||
static qspi_control_block_t m_cb;
|
||||
|
||||
static nrfx_err_t qspi_task_perform(nrf_qspi_task_t task)
|
||||
{
|
||||
// Wait for peripheral
|
||||
if (m_cb.is_busy)
|
||||
{
|
||||
return NRFX_ERROR_BUSY;
|
||||
}
|
||||
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
|
||||
if (m_cb.handler)
|
||||
{
|
||||
m_cb.is_busy = true;
|
||||
nrf_qspi_int_enable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
|
||||
}
|
||||
|
||||
nrf_qspi_task_trigger(NRF_QSPI, task);
|
||||
|
||||
if (m_cb.handler == NULL)
|
||||
{
|
||||
while (!nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY))
|
||||
{};
|
||||
}
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
static bool qspi_pins_configure(nrf_qspi_pins_t const * p_config)
|
||||
{
|
||||
// Check if the user set meaningful values to struct fields. If not, return false.
|
||||
if ((p_config->sck_pin == NRF_QSPI_PIN_NOT_CONNECTED) ||
|
||||
(p_config->csn_pin == NRF_QSPI_PIN_NOT_CONNECTED) ||
|
||||
(p_config->io0_pin == NRF_QSPI_PIN_NOT_CONNECTED) ||
|
||||
(p_config->io1_pin == NRF_QSPI_PIN_NOT_CONNECTED))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
nrf_qspi_pins_set(NRF_QSPI, p_config);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static nrfx_err_t qspi_ready_wait(void)
|
||||
{
|
||||
bool result;
|
||||
NRFX_WAIT_FOR(nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY),
|
||||
QSPI_DEF_WAIT_ATTEMPTS,
|
||||
QSPI_DEF_WAIT_TIME_US,
|
||||
result);
|
||||
if (!result)
|
||||
{
|
||||
return NRFX_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_init(nrfx_qspi_config_t const * p_config,
|
||||
nrfx_qspi_handler_t handler,
|
||||
void * p_context)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
return NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!qspi_pins_configure(&p_config->pins))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
nrf_qspi_xip_offset_set(NRF_QSPI, p_config->xip_offset);
|
||||
nrf_qspi_ifconfig0_set(NRF_QSPI, &p_config->prot_if);
|
||||
nrf_qspi_ifconfig1_set(NRF_QSPI, &p_config->phy_if);
|
||||
|
||||
m_cb.is_busy = false;
|
||||
m_cb.handler = handler;
|
||||
m_cb.p_context = p_context;
|
||||
|
||||
/* QSPI interrupt is disabled because the device should be enabled in polling mode (wait for activate
|
||||
task event ready)*/
|
||||
nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
|
||||
|
||||
if (handler)
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(QSPI_IRQn, p_config->irq_priority);
|
||||
NRFX_IRQ_ENABLE(QSPI_IRQn);
|
||||
}
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
nrf_qspi_enable(NRF_QSPI);
|
||||
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE);
|
||||
|
||||
// Waiting for the peripheral to activate
|
||||
|
||||
return qspi_ready_wait();
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_cinstr_xfer(nrf_qspi_cinstr_conf_t const * p_config,
|
||||
void const * p_tx_buffer,
|
||||
void * p_rx_buffer)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
if (m_cb.is_busy)
|
||||
{
|
||||
return NRFX_ERROR_BUSY;
|
||||
}
|
||||
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
/* In some cases, only opcode should be sent. To prevent execution, set function code is
|
||||
* surrounded by an if.
|
||||
*/
|
||||
if (p_tx_buffer)
|
||||
{
|
||||
nrf_qspi_cinstrdata_set(NRF_QSPI, p_config->length, p_tx_buffer);
|
||||
}
|
||||
|
||||
nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
|
||||
|
||||
nrf_qspi_cinstr_transfer_start(NRF_QSPI, p_config);
|
||||
|
||||
if (qspi_ready_wait() == NRFX_ERROR_TIMEOUT)
|
||||
{
|
||||
// This timeout should never occur when WIPWAIT is not active, since in this
|
||||
// case the QSPI peripheral should send the command immediately, without any
|
||||
// waiting for previous write to complete.
|
||||
NRFX_ASSERT(p_config->wipwait);
|
||||
|
||||
return NRFX_ERROR_TIMEOUT;
|
||||
}
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
|
||||
if (p_rx_buffer)
|
||||
{
|
||||
nrf_qspi_cinstrdata_get(NRF_QSPI, p_config->length, p_rx_buffer);
|
||||
}
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_cinstr_quick_send(uint8_t opcode,
|
||||
nrf_qspi_cinstr_len_t length,
|
||||
void const * p_tx_buffer)
|
||||
{
|
||||
nrf_qspi_cinstr_conf_t config = NRFX_QSPI_DEFAULT_CINSTR(opcode, length);
|
||||
return nrfx_qspi_cinstr_xfer(&config, p_tx_buffer, NULL);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_lfm_start(nrf_qspi_cinstr_conf_t const * p_config)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(!(nrf_qspi_cinstr_long_transfer_is_ongoing(NRF_QSPI)));
|
||||
NRFX_ASSERT(p_config->length == NRF_QSPI_CINSTR_LEN_1B);
|
||||
|
||||
if (m_cb.is_busy)
|
||||
{
|
||||
return NRFX_ERROR_BUSY;
|
||||
}
|
||||
|
||||
nrf_qspi_cinstr_long_transfer_start(NRF_QSPI, p_config);
|
||||
|
||||
if (qspi_ready_wait() == NRFX_ERROR_TIMEOUT)
|
||||
{
|
||||
/* In case of error, abort long frame mode */
|
||||
nrf_qspi_cinstr_long_transfer_continue(NRF_QSPI, NRF_QSPI_CINSTR_LEN_1B, true);
|
||||
return NRFX_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
m_cb.is_busy = true;
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_lfm_xfer(void const * p_tx_buffer,
|
||||
void * p_rx_buffer,
|
||||
size_t transfer_length,
|
||||
bool finalize)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(nrf_qspi_cinstr_long_transfer_is_ongoing(NRF_QSPI));
|
||||
|
||||
nrfx_err_t status = NRFX_SUCCESS;
|
||||
|
||||
/* Perform transfers in packets of 8 bytes. Last transfer may be shorter. */
|
||||
nrf_qspi_cinstr_len_t length = NRF_QSPI_CINSTR_LEN_9B;
|
||||
for (uint32_t curr_byte = 0; curr_byte < transfer_length; curr_byte += 8)
|
||||
{
|
||||
uint32_t remaining_bytes = transfer_length - curr_byte;
|
||||
if (remaining_bytes < 8)
|
||||
{
|
||||
length = (nrf_qspi_cinstr_len_t)(remaining_bytes + 1);
|
||||
}
|
||||
|
||||
if (p_tx_buffer)
|
||||
{
|
||||
nrf_qspi_cinstrdata_set(NRF_QSPI,
|
||||
length,
|
||||
&((uint8_t const *)p_tx_buffer)[curr_byte]);
|
||||
}
|
||||
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
|
||||
if (remaining_bytes <= 8)
|
||||
{
|
||||
nrf_qspi_cinstr_long_transfer_continue(NRF_QSPI, length, finalize);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_qspi_cinstr_long_transfer_continue(NRF_QSPI, length, false);
|
||||
}
|
||||
|
||||
if (qspi_ready_wait() == NRFX_ERROR_TIMEOUT)
|
||||
{
|
||||
/* In case of error, abort long frame mode */
|
||||
nrf_qspi_cinstr_long_transfer_continue(NRF_QSPI, NRF_QSPI_CINSTR_LEN_1B, true);
|
||||
status = NRFX_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_rx_buffer)
|
||||
{
|
||||
nrf_qspi_cinstrdata_get(NRF_QSPI,
|
||||
length,
|
||||
&((uint8_t *)p_rx_buffer)[curr_byte]);
|
||||
}
|
||||
}
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
|
||||
if ((finalize) || (status == NRFX_ERROR_TIMEOUT))
|
||||
{
|
||||
m_cb.is_busy = false;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_mem_busy_check(void)
|
||||
{
|
||||
nrfx_err_t ret_code;
|
||||
uint8_t status_value = 0;
|
||||
|
||||
nrf_qspi_cinstr_conf_t const config =
|
||||
NRFX_QSPI_DEFAULT_CINSTR(QSPI_STD_CMD_RDSR,
|
||||
NRF_QSPI_CINSTR_LEN_2B);
|
||||
ret_code = nrfx_qspi_cinstr_xfer(&config, &status_value, &status_value);
|
||||
|
||||
if (ret_code != NRFX_SUCCESS)
|
||||
{
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
if ((status_value & QSPI_MEM_STATUSREG_WIP_Pos) != 0x00)
|
||||
{
|
||||
return NRFX_ERROR_BUSY;
|
||||
}
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
void nrfx_qspi_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
if (nrf_qspi_cinstr_long_transfer_is_ongoing(NRF_QSPI))
|
||||
{
|
||||
nrf_qspi_cinstr_long_transfer_continue(NRF_QSPI, NRF_QSPI_CINSTR_LEN_1B, true);
|
||||
}
|
||||
|
||||
nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
|
||||
|
||||
nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_DEACTIVATE);
|
||||
|
||||
nrf_qspi_disable(NRF_QSPI);
|
||||
|
||||
NRFX_IRQ_DISABLE(QSPI_IRQn);
|
||||
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
|
||||
m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_write(void const * p_tx_buffer,
|
||||
size_t tx_buffer_length,
|
||||
uint32_t dst_address)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(p_tx_buffer != NULL);
|
||||
|
||||
if (!nrfx_is_in_ram(p_tx_buffer) || !nrfx_is_word_aligned(p_tx_buffer))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
nrf_qspi_write_buffer_set(NRF_QSPI, p_tx_buffer, tx_buffer_length, dst_address);
|
||||
return qspi_task_perform(NRF_QSPI_TASK_WRITESTART);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_read(void * p_rx_buffer,
|
||||
size_t rx_buffer_length,
|
||||
uint32_t src_address)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(p_rx_buffer != NULL);
|
||||
|
||||
if (!nrfx_is_in_ram(p_rx_buffer) || !nrfx_is_word_aligned(p_rx_buffer))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
nrf_qspi_read_buffer_set(NRF_QSPI, p_rx_buffer, rx_buffer_length, src_address);
|
||||
return qspi_task_perform(NRF_QSPI_TASK_READSTART);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_erase(nrf_qspi_erase_len_t length,
|
||||
uint32_t start_address)
|
||||
{
|
||||
NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
if (!nrfx_is_word_aligned((void const *)start_address))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
nrf_qspi_erase_ptr_set(NRF_QSPI, start_address, length);
|
||||
return qspi_task_perform(NRF_QSPI_TASK_ERASESTART);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_qspi_chip_erase(void)
|
||||
{
|
||||
return nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_ALL, 0);
|
||||
}
|
||||
|
||||
void nrfx_qspi_irq_handler(void)
|
||||
{
|
||||
// Catch Event ready interrupts
|
||||
if (nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY))
|
||||
{
|
||||
m_cb.is_busy = false;
|
||||
nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
|
||||
m_cb.handler(NRFX_QSPI_EVENT_DONE, m_cb.p_context);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_QSPI_ENABLED)
|
||||
122
modules/nrfx/drivers/src/nrfx_rng.c
Normal file
122
modules/nrfx/drivers/src/nrfx_rng.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_RNG_ENABLED)
|
||||
|
||||
#include <nrfx_rng.h>
|
||||
|
||||
#define NRFX_LOG_MODULE RNG
|
||||
#include <nrfx_log.h>
|
||||
|
||||
/**
|
||||
* @brief Internal state of RNG driver.
|
||||
*/
|
||||
static nrfx_drv_state_t m_rng_state;
|
||||
|
||||
/**
|
||||
* @brief Pointer to handler calling from interrupt routine.
|
||||
*/
|
||||
static nrfx_rng_evt_handler_t m_rng_hndl;
|
||||
|
||||
nrfx_err_t nrfx_rng_init(nrfx_rng_config_t const * p_config, nrfx_rng_evt_handler_t handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(handler);
|
||||
if (m_rng_state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
return NRFX_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
m_rng_hndl = handler;
|
||||
|
||||
if (p_config->error_correction)
|
||||
{
|
||||
nrf_rng_error_correction_enable();
|
||||
}
|
||||
nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
|
||||
NRFX_IRQ_PRIORITY_SET(RNG_IRQn, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(RNG_IRQn);
|
||||
|
||||
m_rng_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
void nrfx_rng_start(void)
|
||||
{
|
||||
NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_START);
|
||||
}
|
||||
|
||||
void nrfx_rng_stop(void)
|
||||
{
|
||||
NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
|
||||
}
|
||||
|
||||
void nrfx_rng_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
|
||||
nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
|
||||
NRFX_IRQ_DISABLE(RNG_IRQn);
|
||||
|
||||
m_rng_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
void nrfx_rng_irq_handler(void)
|
||||
{
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
|
||||
uint8_t rng_value = nrf_rng_random_value_get();
|
||||
|
||||
m_rng_hndl(rng_value);
|
||||
|
||||
NRFX_LOG_DEBUG("Event: NRF_RNG_EVENT_VALRDY.");
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_RNG_ENABLED)
|
||||
348
modules/nrfx/drivers/src/nrfx_rtc.c
Normal file
348
modules/nrfx/drivers/src/nrfx_rtc.c
Normal file
@@ -0,0 +1,348 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_RTC_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_RTC0_ENABLED) || NRFX_CHECK(NRFX_RTC1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_RTC2_ENABLED))
|
||||
#error "No enabled RTC instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_rtc.h>
|
||||
|
||||
#define NRFX_LOG_MODULE RTC
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_RTC_EVENT_TICK ? "NRF_RTC_EVENT_TICK" : \
|
||||
(event == NRF_RTC_EVENT_OVERFLOW ? "NRF_RTC_EVENT_OVERFLOW" : \
|
||||
(event == NRF_RTC_EVENT_COMPARE_0 ? "NRF_RTC_EVENT_COMPARE_0" : \
|
||||
(event == NRF_RTC_EVENT_COMPARE_1 ? "NRF_RTC_EVENT_COMPARE_1" : \
|
||||
(event == NRF_RTC_EVENT_COMPARE_2 ? "NRF_RTC_EVENT_COMPARE_2" : \
|
||||
(event == NRF_RTC_EVENT_COMPARE_3 ? "NRF_RTC_EVENT_COMPARE_3" : \
|
||||
"UNKNOWN EVENT"))))))
|
||||
|
||||
|
||||
/**@brief RTC driver instance control block structure. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_drv_state_t state; /**< Instance state. */
|
||||
bool reliable; /**< Reliable mode flag. */
|
||||
uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */
|
||||
} nrfx_rtc_cb_t;
|
||||
|
||||
// User callbacks local storage.
|
||||
static nrfx_rtc_handler_t m_handlers[NRFX_RTC_ENABLED_COUNT];
|
||||
static nrfx_rtc_cb_t m_cb[NRFX_RTC_ENABLED_COUNT];
|
||||
|
||||
nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const * const p_instance,
|
||||
nrfx_rtc_config_t const * p_config,
|
||||
nrfx_rtc_handler_t handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(handler);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
m_handlers[p_instance->instance_id] = handler;
|
||||
|
||||
if (m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
NRFX_IRQ_PRIORITY_SET(p_instance->irq, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(p_instance->irq);
|
||||
nrf_rtc_prescaler_set(p_instance->p_reg, p_config->prescaler);
|
||||
m_cb[p_instance->instance_id].reliable = p_config->reliable;
|
||||
m_cb[p_instance->instance_id].tick_latency = p_config->tick_latency;
|
||||
m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_rtc_uninit(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
uint32_t mask = NRF_RTC_INT_TICK_MASK |
|
||||
NRF_RTC_INT_OVERFLOW_MASK |
|
||||
NRF_RTC_INT_COMPARE0_MASK |
|
||||
NRF_RTC_INT_COMPARE1_MASK |
|
||||
NRF_RTC_INT_COMPARE2_MASK |
|
||||
NRF_RTC_INT_COMPARE3_MASK;
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
NRFX_IRQ_DISABLE(p_instance->irq);
|
||||
|
||||
nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP);
|
||||
nrf_rtc_event_disable(p_instance->p_reg, mask);
|
||||
nrf_rtc_int_disable(p_instance->p_reg, mask);
|
||||
|
||||
m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
void nrfx_rtc_enable(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_INITIALIZED);
|
||||
|
||||
nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_START);
|
||||
m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Enabled.");
|
||||
}
|
||||
|
||||
void nrfx_rtc_disable(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP);
|
||||
m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Disabled.");
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * const p_instance, uint32_t channel)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(channel<p_instance->cc_channel_count);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel);
|
||||
nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel);
|
||||
|
||||
nrf_rtc_event_disable(p_instance->p_reg,int_mask);
|
||||
if (nrf_rtc_int_is_enabled(p_instance->p_reg,int_mask))
|
||||
{
|
||||
nrf_rtc_int_disable(p_instance->p_reg,int_mask);
|
||||
if (nrf_rtc_event_pending(p_instance->p_reg,event))
|
||||
{
|
||||
nrf_rtc_event_clear(p_instance->p_reg,event);
|
||||
err_code = NRFX_ERROR_TIMEOUT;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
NRFX_LOG_INFO("RTC id: %d, channel disabled: %lu.", p_instance->instance_id, channel);
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance,
|
||||
uint32_t channel,
|
||||
uint32_t val,
|
||||
bool enable_irq)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(channel<p_instance->cc_channel_count);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel);
|
||||
nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel);
|
||||
|
||||
nrf_rtc_event_disable(p_instance->p_reg, int_mask);
|
||||
nrf_rtc_int_disable(p_instance->p_reg, int_mask);
|
||||
|
||||
val = RTC_WRAP(val);
|
||||
if (m_cb[p_instance->instance_id].reliable)
|
||||
{
|
||||
nrf_rtc_cc_set(p_instance->p_reg,channel,val);
|
||||
uint32_t cnt = nrf_rtc_counter_get(p_instance->p_reg);
|
||||
int32_t diff = cnt - val;
|
||||
if (cnt < val)
|
||||
{
|
||||
diff += RTC_COUNTER_COUNTER_Msk;
|
||||
}
|
||||
if (diff < m_cb[p_instance->instance_id].tick_latency)
|
||||
{
|
||||
err_code = NRFX_ERROR_TIMEOUT;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_rtc_cc_set(p_instance->p_reg,channel,val);
|
||||
}
|
||||
|
||||
if (enable_irq)
|
||||
{
|
||||
nrf_rtc_event_clear(p_instance->p_reg,event);
|
||||
nrf_rtc_int_enable(p_instance->p_reg, int_mask);
|
||||
}
|
||||
nrf_rtc_event_enable(p_instance->p_reg,int_mask);
|
||||
|
||||
NRFX_LOG_INFO("RTC id: %d, channel enabled: %lu, compare value: %lu.",
|
||||
p_instance->instance_id,
|
||||
channel,
|
||||
val);
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance, bool enable_irq)
|
||||
{
|
||||
nrf_rtc_event_t event = NRF_RTC_EVENT_TICK;
|
||||
uint32_t mask = NRF_RTC_INT_TICK_MASK;
|
||||
|
||||
nrf_rtc_event_clear(p_instance->p_reg, event);
|
||||
nrf_rtc_event_enable(p_instance->p_reg, mask);
|
||||
if (enable_irq)
|
||||
{
|
||||
nrf_rtc_int_enable(p_instance->p_reg, mask);
|
||||
}
|
||||
NRFX_LOG_INFO("Tick events enabled.");
|
||||
}
|
||||
|
||||
void nrfx_rtc_tick_disable(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
uint32_t mask = NRF_RTC_INT_TICK_MASK;
|
||||
|
||||
nrf_rtc_event_disable(p_instance->p_reg, mask);
|
||||
nrf_rtc_int_disable(p_instance->p_reg, mask);
|
||||
NRFX_LOG_INFO("Tick events disabled.");
|
||||
}
|
||||
|
||||
void nrfx_rtc_overflow_enable(nrfx_rtc_t const * const p_instance, bool enable_irq)
|
||||
{
|
||||
nrf_rtc_event_t event = NRF_RTC_EVENT_OVERFLOW;
|
||||
uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
|
||||
|
||||
nrf_rtc_event_clear(p_instance->p_reg, event);
|
||||
nrf_rtc_event_enable(p_instance->p_reg, mask);
|
||||
if (enable_irq)
|
||||
{
|
||||
nrf_rtc_int_enable(p_instance->p_reg, mask);
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_rtc_overflow_disable(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
|
||||
nrf_rtc_event_disable(p_instance->p_reg, mask);
|
||||
nrf_rtc_int_disable(p_instance->p_reg, mask);
|
||||
}
|
||||
|
||||
uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * const p_instance)
|
||||
{
|
||||
uint32_t ticks;
|
||||
if (m_cb[p_instance->instance_id].reliable)
|
||||
{
|
||||
ticks = RTC_COUNTER_COUNTER_Msk - m_cb[p_instance->instance_id].tick_latency;
|
||||
}
|
||||
else
|
||||
{
|
||||
ticks = RTC_COUNTER_COUNTER_Msk;
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
|
||||
static void irq_handler(NRF_RTC_Type * p_reg,
|
||||
uint32_t instance_id,
|
||||
uint32_t channel_count)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK;
|
||||
nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0;
|
||||
|
||||
for (i = 0; i < channel_count; i++)
|
||||
{
|
||||
if (nrf_rtc_int_is_enabled(p_reg,int_mask) && nrf_rtc_event_pending(p_reg,event))
|
||||
{
|
||||
nrf_rtc_event_disable(p_reg,int_mask);
|
||||
nrf_rtc_int_disable(p_reg,int_mask);
|
||||
nrf_rtc_event_clear(p_reg,event);
|
||||
NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
|
||||
m_handlers[instance_id]((nrfx_rtc_int_type_t)i);
|
||||
}
|
||||
int_mask <<= 1;
|
||||
event = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t));
|
||||
}
|
||||
event = NRF_RTC_EVENT_TICK;
|
||||
if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_TICK_MASK) &&
|
||||
nrf_rtc_event_pending(p_reg, event))
|
||||
{
|
||||
nrf_rtc_event_clear(p_reg, event);
|
||||
NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
|
||||
m_handlers[instance_id](NRFX_RTC_INT_TICK);
|
||||
}
|
||||
|
||||
event = NRF_RTC_EVENT_OVERFLOW;
|
||||
if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_OVERFLOW_MASK) &&
|
||||
nrf_rtc_event_pending(p_reg, event))
|
||||
{
|
||||
nrf_rtc_event_clear(p_reg,event);
|
||||
NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
|
||||
m_handlers[instance_id](NRFX_RTC_INT_OVERFLOW);
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_RTC0_ENABLED)
|
||||
void nrfx_rtc_0_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_RTC0, NRFX_RTC0_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(0));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_RTC1_ENABLED)
|
||||
void nrfx_rtc_1_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_RTC1, NRFX_RTC1_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_RTC2_ENABLED)
|
||||
void nrfx_rtc_2_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_RTC2, NRFX_RTC2_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(2));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_RTC_ENABLED)
|
||||
1470
modules/nrfx/drivers/src/nrfx_saadc.c
Normal file
1470
modules/nrfx/drivers/src/nrfx_saadc.c
Normal file
File diff suppressed because it is too large
Load Diff
436
modules/nrfx/drivers/src/nrfx_spi.c
Normal file
436
modules/nrfx/drivers/src/nrfx_spi.c
Normal file
@@ -0,0 +1,436 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPI_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_SPI0_ENABLED) || NRFX_CHECK(NRFX_SPI1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_SPI2_ENABLED))
|
||||
#error "No enabled SPI instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_spi.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE SPI
|
||||
#include <nrfx_log.h>
|
||||
|
||||
// Control block - driver instance local data.
|
||||
typedef struct
|
||||
{
|
||||
nrfx_spi_evt_handler_t handler;
|
||||
void * p_context;
|
||||
nrfx_spi_evt_t evt; // Keep the struct that is ready for event handler. Less memcpy.
|
||||
nrfx_drv_state_t state;
|
||||
volatile bool transfer_in_progress;
|
||||
|
||||
// [no need for 'volatile' attribute for the following members, as they
|
||||
// are not concurrently used in IRQ handlers and main line code]
|
||||
uint8_t ss_pin;
|
||||
uint8_t miso_pin;
|
||||
uint8_t orc;
|
||||
size_t bytes_transferred;
|
||||
|
||||
bool abort;
|
||||
} spi_control_block_t;
|
||||
static spi_control_block_t m_cb[NRFX_SPI_ENABLED_COUNT];
|
||||
|
||||
|
||||
nrfx_err_t nrfx_spi_init(nrfx_spi_t const * const p_instance,
|
||||
nrfx_spi_config_t const * p_config,
|
||||
nrfx_spi_evt_handler_t handler,
|
||||
void * p_context)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_SPI_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_SPI0_ENABLED)
|
||||
nrfx_spi_0_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPI1_ENABLED)
|
||||
nrfx_spi_1_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPI2_ENABLED)
|
||||
nrfx_spi_2_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_instance->p_reg,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
p_cb->handler = handler;
|
||||
p_cb->p_context = p_context;
|
||||
|
||||
uint32_t mosi_pin;
|
||||
uint32_t miso_pin;
|
||||
// Configure pins used by the peripheral:
|
||||
// - SCK - output with initial value corresponding with the SPI mode used:
|
||||
// 0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1);
|
||||
// according to the reference manual guidelines this pin and its input
|
||||
// buffer must always be connected for the SPI to work.
|
||||
if (p_config->mode <= NRF_SPI_MODE_1)
|
||||
{
|
||||
nrf_gpio_pin_clear(p_config->sck_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->sck_pin);
|
||||
}
|
||||
nrf_gpio_cfg(p_config->sck_pin,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_S0S1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
// - MOSI (optional) - output with initial value 0,
|
||||
if (p_config->mosi_pin != NRFX_SPI_PIN_NOT_USED)
|
||||
{
|
||||
mosi_pin = p_config->mosi_pin;
|
||||
nrf_gpio_pin_clear(mosi_pin);
|
||||
nrf_gpio_cfg_output(mosi_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
mosi_pin = NRF_SPI_PIN_NOT_CONNECTED;
|
||||
}
|
||||
// - MISO (optional) - input,
|
||||
if (p_config->miso_pin != NRFX_SPI_PIN_NOT_USED)
|
||||
{
|
||||
miso_pin = p_config->miso_pin;
|
||||
nrf_gpio_cfg_input(miso_pin, (nrf_gpio_pin_pull_t)NRFX_SPI_MISO_PULL_CFG);
|
||||
}
|
||||
else
|
||||
{
|
||||
miso_pin = NRF_SPI_PIN_NOT_CONNECTED;
|
||||
}
|
||||
m_cb[p_instance->drv_inst_idx].miso_pin = p_config->miso_pin;
|
||||
// - Slave Select (optional) - output with initial value 1 (inactive).
|
||||
if (p_config->ss_pin != NRFX_SPI_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->ss_pin);
|
||||
nrf_gpio_cfg_output(p_config->ss_pin);
|
||||
}
|
||||
m_cb[p_instance->drv_inst_idx].ss_pin = p_config->ss_pin;
|
||||
|
||||
NRF_SPI_Type * p_spi = p_instance->p_reg;
|
||||
nrf_spi_pins_set(p_spi, p_config->sck_pin, mosi_pin, miso_pin);
|
||||
nrf_spi_frequency_set(p_spi, p_config->frequency);
|
||||
nrf_spi_configure(p_spi, p_config->mode, p_config->bit_order);
|
||||
|
||||
m_cb[p_instance->drv_inst_idx].orc = p_config->orc;
|
||||
|
||||
nrf_spi_enable(p_spi);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
|
||||
p_config->irq_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
}
|
||||
|
||||
p_cb->transfer_in_progress = false;
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_spi_uninit(nrfx_spi_t const * const p_instance)
|
||||
{
|
||||
spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
}
|
||||
|
||||
NRF_SPI_Type * p_spi = p_instance->p_reg;
|
||||
if (p_cb->handler)
|
||||
{
|
||||
nrf_spi_int_disable(p_spi, NRF_SPI_ALL_INTS_MASK);
|
||||
}
|
||||
|
||||
if (p_cb->miso_pin != NRFX_SPI_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_cfg_default(p_cb->miso_pin);
|
||||
}
|
||||
nrf_spi_disable(p_spi);
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_instance->p_reg);
|
||||
#endif
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
static void finish_transfer(spi_control_block_t * p_cb)
|
||||
{
|
||||
// If Slave Select signal is used, this is the time to deactivate it.
|
||||
if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_cb->ss_pin);
|
||||
}
|
||||
|
||||
// By clearing this flag before calling the handler we allow subsequent
|
||||
// transfers to be started directly from the handler function.
|
||||
p_cb->transfer_in_progress = false;
|
||||
|
||||
p_cb->evt.type = NRFX_SPI_EVENT_DONE;
|
||||
p_cb->handler(&p_cb->evt, p_cb->p_context);
|
||||
}
|
||||
|
||||
// This function is called from the IRQ handler or, in blocking mode, directly
|
||||
// from the 'spi_xfer' function.
|
||||
// It returns true as long as the transfer should be continued, otherwise (when
|
||||
// there is nothing more to send/receive) it returns false.
|
||||
static bool transfer_byte(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb)
|
||||
{
|
||||
// Read the data byte received in this transfer (always, because no further
|
||||
// READY event can be generated until the current byte is read out from the
|
||||
// RXD register), and store it in the RX buffer (only when needed).
|
||||
volatile uint8_t rx_data = nrf_spi_rxd_get(p_spi);
|
||||
if (p_cb->bytes_transferred < p_cb->evt.xfer_desc.rx_length)
|
||||
{
|
||||
p_cb->evt.xfer_desc.p_rx_buffer[p_cb->bytes_transferred] = rx_data;
|
||||
}
|
||||
|
||||
++p_cb->bytes_transferred;
|
||||
|
||||
// Check if there are more bytes to send or receive and write proper data
|
||||
// byte (next one from TX buffer or over-run character) to the TXD register
|
||||
// when needed.
|
||||
// NOTE - we've already used 'p_cb->bytes_transferred + 1' bytes from our
|
||||
// buffers, because we take advantage of double buffering of TXD
|
||||
// register (so in effect one byte is still being transmitted now);
|
||||
// see how the transfer is started in the 'spi_xfer' function.
|
||||
size_t bytes_used = p_cb->bytes_transferred + 1;
|
||||
|
||||
if (p_cb->abort)
|
||||
{
|
||||
if (bytes_used < p_cb->evt.xfer_desc.tx_length)
|
||||
{
|
||||
p_cb->evt.xfer_desc.tx_length = bytes_used;
|
||||
}
|
||||
if (bytes_used < p_cb->evt.xfer_desc.rx_length)
|
||||
{
|
||||
p_cb->evt.xfer_desc.rx_length = bytes_used;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_used < p_cb->evt.xfer_desc.tx_length)
|
||||
{
|
||||
nrf_spi_txd_set(p_spi, p_cb->evt.xfer_desc.p_tx_buffer[bytes_used]);
|
||||
return true;
|
||||
}
|
||||
else if (bytes_used < p_cb->evt.xfer_desc.rx_length)
|
||||
{
|
||||
nrf_spi_txd_set(p_spi, p_cb->orc);
|
||||
return true;
|
||||
}
|
||||
|
||||
return (p_cb->bytes_transferred < p_cb->evt.xfer_desc.tx_length ||
|
||||
p_cb->bytes_transferred < p_cb->evt.xfer_desc.rx_length);
|
||||
}
|
||||
|
||||
static void spi_xfer(NRF_SPI_Type * p_spi,
|
||||
spi_control_block_t * p_cb,
|
||||
nrfx_spi_xfer_desc_t const * p_xfer_desc)
|
||||
{
|
||||
p_cb->bytes_transferred = 0;
|
||||
nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK);
|
||||
|
||||
nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
|
||||
|
||||
// Start the transfer by writing some byte to the TXD register;
|
||||
// if TX buffer is not empty, take the first byte from this buffer,
|
||||
// otherwise - use over-run character.
|
||||
nrf_spi_txd_set(p_spi,
|
||||
(p_xfer_desc->tx_length > 0 ? p_xfer_desc->p_tx_buffer[0] : p_cb->orc));
|
||||
|
||||
// TXD register is double buffered, so next byte to be transmitted can
|
||||
// be written immediately, if needed, i.e. if TX or RX transfer is to
|
||||
// be more that 1 byte long. Again - if there is something more in TX
|
||||
// buffer send it, otherwise use over-run character.
|
||||
if (p_xfer_desc->tx_length > 1)
|
||||
{
|
||||
nrf_spi_txd_set(p_spi, p_xfer_desc->p_tx_buffer[1]);
|
||||
}
|
||||
else if (p_xfer_desc->rx_length > 1)
|
||||
{
|
||||
nrf_spi_txd_set(p_spi, p_cb->orc);
|
||||
}
|
||||
|
||||
// For blocking mode (user handler not provided) wait here for READY
|
||||
// events (indicating that the byte from TXD register was transmitted
|
||||
// and a new incoming byte was moved to the RXD register) and continue
|
||||
// transaction until all requested bytes are transferred.
|
||||
// In non-blocking mode - IRQ service routine will do this stuff.
|
||||
if (p_cb->handler)
|
||||
{
|
||||
nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
do {
|
||||
while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
|
||||
nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
|
||||
NRFX_LOG_DEBUG("SPI: Event: NRF_SPI_EVENT_READY.");
|
||||
} while (transfer_byte(p_spi, p_cb));
|
||||
if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_cb->ss_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_spi_xfer(nrfx_spi_t const * const p_instance,
|
||||
nrfx_spi_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags)
|
||||
{
|
||||
spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
|
||||
NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (p_cb->transfer_in_progress)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p_cb->handler)
|
||||
{
|
||||
p_cb->transfer_in_progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
p_cb->evt.xfer_desc = *p_xfer_desc;
|
||||
p_cb->abort = false;
|
||||
|
||||
if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_pin_clear(p_cb->ss_pin);
|
||||
}
|
||||
if (flags)
|
||||
{
|
||||
p_cb->transfer_in_progress = false;
|
||||
err_code = NRFX_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_xfer(p_instance->p_reg, p_cb, p_xfer_desc);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_spi_abort(nrfx_spi_t const * p_instance)
|
||||
{
|
||||
spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
p_cb->abort = true;
|
||||
}
|
||||
|
||||
static void irq_handler(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb)
|
||||
{
|
||||
NRFX_ASSERT(p_cb->handler);
|
||||
|
||||
nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
|
||||
NRFX_LOG_DEBUG("Event: NRF_SPI_EVENT_READY.");
|
||||
|
||||
if (!transfer_byte(p_spi, p_cb))
|
||||
{
|
||||
finish_transfer(p_cb);
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPI0_ENABLED)
|
||||
void nrfx_spi_0_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_SPI0, &m_cb[NRFX_SPI0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPI1_ENABLED)
|
||||
void nrfx_spi_1_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_SPI1, &m_cb[NRFX_SPI1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPI2_ENABLED)
|
||||
void nrfx_spi_2_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_SPI2, &m_cb[NRFX_SPI2_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_SPI_ENABLED)
|
||||
697
modules/nrfx/drivers/src/nrfx_spim.c
Normal file
697
modules/nrfx/drivers/src/nrfx_spim.c
Normal file
@@ -0,0 +1,697 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_SPIM0_ENABLED) || NRFX_CHECK(NRFX_SPIM1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_SPIM2_ENABLED) || NRFX_CHECK(NRFX_SPIM3_ENABLED))
|
||||
#error "No enabled SPIM instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) && !NRFX_CHECK(NRFX_SPIM3_ENABLED)
|
||||
#error "Extended options are available only in SPIM3 on the nRF52840 SoC."
|
||||
#endif
|
||||
|
||||
#include <nrfx_spim.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE SPIM
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define SPIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, rx_len, tx_len) \
|
||||
(((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
|
||||
NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, rx_len, tx_len))
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
|
||||
#define SPIM0_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM0, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIM0_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
|
||||
#define SPIM1_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM1, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIM1_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
|
||||
#define SPIM2_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM2, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIM2_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
|
||||
#define SPIM3_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM3, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIM3_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#define SPIM_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) \
|
||||
(SPIM0_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
|
||||
SPIM1_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
|
||||
SPIM2_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
|
||||
SPIM3_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len))
|
||||
|
||||
#if defined(NRF52840_XXAA) && (NRFX_CHECK(NRFX_SPIM3_ENABLED))
|
||||
// Enable workaround for nRF52840 anomaly 195 (SPIM3 continues to draw current after disable).
|
||||
#define USE_WORKAROUND_FOR_ANOMALY_195
|
||||
#endif
|
||||
|
||||
// Control block - driver instance local data.
|
||||
typedef struct
|
||||
{
|
||||
nrfx_spim_evt_handler_t handler;
|
||||
void * p_context;
|
||||
nrfx_spim_evt_t evt; // Keep the struct that is ready for event handler. Less memcpy.
|
||||
nrfx_drv_state_t state;
|
||||
volatile bool transfer_in_progress;
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
bool use_hw_ss;
|
||||
#endif
|
||||
|
||||
// [no need for 'volatile' attribute for the following members, as they
|
||||
// are not concurrently used in IRQ handlers and main line code]
|
||||
bool ss_active_high;
|
||||
uint8_t ss_pin;
|
||||
uint8_t miso_pin;
|
||||
uint8_t orc;
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
size_t tx_length;
|
||||
size_t rx_length;
|
||||
#endif
|
||||
} spim_control_block_t;
|
||||
static spim_control_block_t m_cb[NRFX_SPIM_ENABLED_COUNT];
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
|
||||
|
||||
// Workaround for nRF52840 anomaly 198: SPIM3 transmit data might be corrupted.
|
||||
|
||||
static uint32_t m_anomaly_198_preserved_value;
|
||||
|
||||
static void anomaly_198_enable(uint8_t const * p_buffer, size_t buf_len)
|
||||
{
|
||||
m_anomaly_198_preserved_value = *((volatile uint32_t *)0x40000E00);
|
||||
|
||||
if (buf_len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint32_t buffer_end_addr = ((uint32_t)p_buffer) + buf_len;
|
||||
uint32_t block_addr = ((uint32_t)p_buffer) & ~0x1FFF;
|
||||
uint32_t block_flag = (1UL << ((block_addr >> 13) & 0xFFFF));
|
||||
uint32_t occupied_blocks = 0;
|
||||
|
||||
if (block_addr >= 0x20010000)
|
||||
{
|
||||
occupied_blocks = (1UL << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
do {
|
||||
occupied_blocks |= block_flag;
|
||||
block_flag <<= 1;
|
||||
block_addr += 0x2000;
|
||||
} while ((block_addr < buffer_end_addr) && (block_addr < 0x20012000));
|
||||
}
|
||||
|
||||
*((volatile uint32_t *)0x40000E00) = occupied_blocks;
|
||||
}
|
||||
|
||||
static void anomaly_198_disable(void)
|
||||
{
|
||||
*((volatile uint32_t *)0x40000E00) = m_anomaly_198_preserved_value;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
|
||||
|
||||
nrfx_err_t nrfx_spim_init(nrfx_spim_t const * const p_instance,
|
||||
nrfx_spim_config_t const * p_config,
|
||||
nrfx_spim_evt_handler_t handler,
|
||||
void * p_context)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
// Currently, only SPIM3 in nRF52840 supports the extended features.
|
||||
// Other instances must be checked.
|
||||
if ((p_instance->drv_inst_idx != NRFX_SPIM3_INST_IDX) &&
|
||||
((p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED) ||
|
||||
(p_config->frequency == NRF_SPIM_FREQ_16M) ||
|
||||
(p_config->frequency == NRF_SPIM_FREQ_32M) ||
|
||||
(p_config->use_hw_ss)))
|
||||
{
|
||||
err_code = NRFX_ERROR_NOT_SUPPORTED;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_SPIM_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
|
||||
nrfx_spim_0_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
|
||||
nrfx_spim_1_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
|
||||
nrfx_spim_2_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
|
||||
nrfx_spim_3_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_instance->p_reg,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
p_cb->handler = handler;
|
||||
p_cb->p_context = p_context;
|
||||
|
||||
uint32_t mosi_pin;
|
||||
uint32_t miso_pin;
|
||||
// Configure pins used by the peripheral:
|
||||
// - SCK - output with initial value corresponding with the SPI mode used:
|
||||
// 0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1);
|
||||
// according to the reference manual guidelines this pin and its input
|
||||
// buffer must always be connected for the SPI to work.
|
||||
if (p_config->mode <= NRF_SPIM_MODE_1)
|
||||
{
|
||||
nrf_gpio_pin_clear(p_config->sck_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->sck_pin);
|
||||
}
|
||||
nrf_gpio_cfg(p_config->sck_pin,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_S0S1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
// - MOSI (optional) - output with initial value 0,
|
||||
if (p_config->mosi_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
mosi_pin = p_config->mosi_pin;
|
||||
nrf_gpio_pin_clear(mosi_pin);
|
||||
nrf_gpio_cfg_output(mosi_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
mosi_pin = NRF_SPIM_PIN_NOT_CONNECTED;
|
||||
}
|
||||
// - MISO (optional) - input,
|
||||
if (p_config->miso_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
miso_pin = p_config->miso_pin;
|
||||
nrf_gpio_cfg_input(miso_pin, (nrf_gpio_pin_pull_t)NRFX_SPIM_MISO_PULL_CFG);
|
||||
}
|
||||
else
|
||||
{
|
||||
miso_pin = NRF_SPIM_PIN_NOT_CONNECTED;
|
||||
}
|
||||
p_cb->miso_pin = p_config->miso_pin;
|
||||
// - Slave Select (optional) - output with initial value 1 (inactive).
|
||||
|
||||
// 'p_cb->ss_pin' variable is used during transfers to check if SS pin should be toggled,
|
||||
// so this field needs to be initialized even if the pin is not used.
|
||||
p_cb->ss_pin = p_config->ss_pin;
|
||||
|
||||
if (p_config->ss_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
if (p_config->ss_active_high)
|
||||
{
|
||||
nrf_gpio_pin_clear(p_config->ss_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->ss_pin);
|
||||
}
|
||||
nrf_gpio_cfg_output(p_config->ss_pin);
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
if (p_config->use_hw_ss)
|
||||
{
|
||||
p_cb->use_hw_ss = p_config->use_hw_ss;
|
||||
nrf_spim_csn_configure(p_spim,
|
||||
p_config->ss_pin,
|
||||
(p_config->ss_active_high == true ?
|
||||
NRF_SPIM_CSN_POL_HIGH : NRF_SPIM_CSN_POL_LOW),
|
||||
p_config->ss_duration);
|
||||
}
|
||||
#endif
|
||||
p_cb->ss_active_high = p_config->ss_active_high;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
// - DCX (optional) - output.
|
||||
if (p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->dcx_pin);
|
||||
nrf_gpio_cfg_output(p_config->dcx_pin);
|
||||
nrf_spim_dcx_pin_set(p_spim, p_config->dcx_pin);
|
||||
}
|
||||
|
||||
// Change rx delay
|
||||
nrf_spim_iftiming_set(p_spim, p_config->rx_delay);
|
||||
#endif
|
||||
|
||||
|
||||
nrf_spim_pins_set(p_spim, p_config->sck_pin, mosi_pin, miso_pin);
|
||||
nrf_spim_frequency_set(p_spim, p_config->frequency);
|
||||
nrf_spim_configure(p_spim, p_config->mode, p_config->bit_order);
|
||||
|
||||
nrf_spim_orc_set(p_spim, p_config->orc);
|
||||
|
||||
nrf_spim_enable(p_spim);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
|
||||
p_config->irq_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
}
|
||||
|
||||
p_cb->transfer_in_progress = false;
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_spim_uninit(nrfx_spim_t const * const p_instance)
|
||||
{
|
||||
spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
}
|
||||
|
||||
NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
|
||||
if (p_cb->handler)
|
||||
{
|
||||
nrf_spim_int_disable(p_spim, NRF_SPIM_ALL_INTS_MASK);
|
||||
if (p_cb->transfer_in_progress)
|
||||
{
|
||||
// Ensure that SPI is not performing any transfer.
|
||||
nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_STOP);
|
||||
while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STOPPED))
|
||||
{}
|
||||
p_cb->transfer_in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_cb->miso_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_cfg_default(p_cb->miso_pin);
|
||||
}
|
||||
nrf_spim_disable(p_spim);
|
||||
|
||||
#ifdef USE_WORKAROUND_FOR_ANOMALY_195
|
||||
if (p_spim == NRF_SPIM3)
|
||||
{
|
||||
*(volatile uint32_t *)0x4002F004 = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_instance->p_reg);
|
||||
#endif
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const * const p_instance,
|
||||
nrfx_spim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags,
|
||||
uint8_t cmd_length)
|
||||
{
|
||||
NRFX_ASSERT(cmd_length <= NRF_SPIM_DCX_CNT_ALL_CMD);
|
||||
nrf_spim_dcx_cnt_set((NRF_SPIM_Type *)p_instance->p_reg, cmd_length);
|
||||
return nrfx_spim_xfer(p_instance, p_xfer_desc, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void finish_transfer(spim_control_block_t * p_cb)
|
||||
{
|
||||
// If Slave Select signal is used, this is the time to deactivate it.
|
||||
if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
if (!p_cb->use_hw_ss)
|
||||
#endif
|
||||
{
|
||||
if (p_cb->ss_active_high)
|
||||
{
|
||||
nrf_gpio_pin_clear(p_cb->ss_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_set(p_cb->ss_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// By clearing this flag before calling the handler we allow subsequent
|
||||
// transfers to be started directly from the handler function.
|
||||
p_cb->transfer_in_progress = false;
|
||||
|
||||
p_cb->evt.type = NRFX_SPIM_EVENT_DONE;
|
||||
p_cb->handler(&p_cb->evt, p_cb->p_context);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void spim_int_enable(NRF_SPIM_Type * p_spim, bool enable)
|
||||
{
|
||||
if (!enable)
|
||||
{
|
||||
nrf_spim_int_disable(p_spim, NRF_SPIM_INT_END_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void spim_list_enable_handle(NRF_SPIM_Type * p_spim, uint32_t flags)
|
||||
{
|
||||
if (NRFX_SPIM_FLAG_TX_POSTINC & flags)
|
||||
{
|
||||
nrf_spim_tx_list_enable(p_spim);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_spim_tx_list_disable(p_spim);
|
||||
}
|
||||
|
||||
if (NRFX_SPIM_FLAG_RX_POSTINC & flags)
|
||||
{
|
||||
nrf_spim_rx_list_enable(p_spim);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_spim_rx_list_disable(p_spim);
|
||||
}
|
||||
}
|
||||
|
||||
static nrfx_err_t spim_xfer(NRF_SPIM_Type * p_spim,
|
||||
spim_control_block_t * p_cb,
|
||||
nrfx_spim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
// EasyDMA requires that transfer buffers are placed in Data RAM region;
|
||||
// signal error if they are not.
|
||||
if ((p_xfer_desc->p_tx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_tx_buffer)) ||
|
||||
(p_xfer_desc->p_rx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_rx_buffer)))
|
||||
{
|
||||
p_cb->transfer_in_progress = false;
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
p_cb->tx_length = 0;
|
||||
p_cb->rx_length = 0;
|
||||
#endif
|
||||
|
||||
nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
|
||||
nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, p_xfer_desc->rx_length);
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
|
||||
if (p_spim == NRF_SPIM3)
|
||||
{
|
||||
anomaly_198_enable(p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
|
||||
|
||||
spim_list_enable_handle(p_spim, flags);
|
||||
|
||||
if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
|
||||
{
|
||||
nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
|
||||
}
|
||||
#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
if (flags & NRFX_SPIM_FLAG_HOLD_XFER)
|
||||
{
|
||||
nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
|
||||
p_cb->tx_length = p_xfer_desc->tx_length;
|
||||
p_cb->rx_length = p_xfer_desc->rx_length;
|
||||
nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, 0);
|
||||
nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, 0);
|
||||
nrf_spim_int_enable(p_spim, NRF_SPIM_INT_STARTED_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!p_cb->handler)
|
||||
{
|
||||
while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)){}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
|
||||
if (p_spim == NRF_SPIM3)
|
||||
{
|
||||
anomaly_198_disable();
|
||||
}
|
||||
#endif
|
||||
if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
if (!p_cb->use_hw_ss)
|
||||
#endif
|
||||
{
|
||||
if (p_cb->ss_active_high)
|
||||
{
|
||||
nrf_gpio_pin_clear(p_cb->ss_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_set(p_cb->ss_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spim_int_enable(p_spim, !(flags & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
|
||||
}
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * const p_instance,
|
||||
nrfx_spim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags)
|
||||
{
|
||||
spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
|
||||
NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
|
||||
NRFX_ASSERT(SPIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
|
||||
p_xfer_desc->rx_length,
|
||||
p_xfer_desc->tx_length));
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (p_cb->transfer_in_progress)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p_cb->handler && !(flags & (NRFX_SPIM_FLAG_REPEATED_XFER |
|
||||
NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)))
|
||||
{
|
||||
p_cb->transfer_in_progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
p_cb->evt.xfer_desc = *p_xfer_desc;
|
||||
|
||||
if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
|
||||
if (!p_cb->use_hw_ss)
|
||||
#endif
|
||||
{
|
||||
if (p_cb->ss_active_high)
|
||||
{
|
||||
nrf_gpio_pin_set(p_cb->ss_pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_clear(p_cb->ss_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return spim_xfer(p_instance->p_reg, p_cb, p_xfer_desc, flags);
|
||||
}
|
||||
|
||||
void nrfx_spim_abort(nrfx_spim_t const * p_instance)
|
||||
{
|
||||
spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
nrf_spim_task_trigger(p_instance->p_reg, NRF_SPIM_TASK_STOP);
|
||||
while (!nrf_spim_event_check(p_instance->p_reg, NRF_SPIM_EVENT_STOPPED))
|
||||
{}
|
||||
p_cb->transfer_in_progress = false;
|
||||
}
|
||||
|
||||
uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance)
|
||||
{
|
||||
NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
|
||||
return nrf_spim_task_address_get(p_spim, NRF_SPIM_TASK_START);
|
||||
}
|
||||
|
||||
uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance)
|
||||
{
|
||||
NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
|
||||
return nrf_spim_event_address_get(p_spim, NRF_SPIM_EVENT_END);
|
||||
}
|
||||
|
||||
static void irq_handler(NRF_SPIM_Type * p_spim, spim_control_block_t * p_cb)
|
||||
{
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
if ((nrf_spim_int_enable_check(p_spim, NRF_SPIM_INT_STARTED_MASK)) &&
|
||||
(nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STARTED)) )
|
||||
{
|
||||
/* Handle first, zero-length, auxiliary transmission. */
|
||||
nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
|
||||
nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
|
||||
|
||||
NRFX_ASSERT(p_spim->TXD.MAXCNT == 0);
|
||||
p_spim->TXD.MAXCNT = p_cb->tx_length;
|
||||
|
||||
NRFX_ASSERT(p_spim->RXD.MAXCNT == 0);
|
||||
p_spim->RXD.MAXCNT = p_cb->rx_length;
|
||||
|
||||
/* Disable STARTED interrupt, used only in auxiliary transmission. */
|
||||
nrf_spim_int_disable(p_spim, NRF_SPIM_INT_STARTED_MASK);
|
||||
|
||||
/* Start the actual, glitch-free transmission. */
|
||||
nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
|
||||
{
|
||||
#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
|
||||
if (p_spim == NRF_SPIM3)
|
||||
{
|
||||
anomaly_198_disable();
|
||||
}
|
||||
#endif
|
||||
nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
|
||||
NRFX_ASSERT(p_cb->handler);
|
||||
NRFX_LOG_DEBUG("Event: NRF_SPIM_EVENT_END.");
|
||||
finish_transfer(p_cb);
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
|
||||
void nrfx_spim_0_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_SPIM0, &m_cb[NRFX_SPIM0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
|
||||
void nrfx_spim_1_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_SPIM1, &m_cb[NRFX_SPIM1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
|
||||
void nrfx_spim_2_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_SPIM2, &m_cb[NRFX_SPIM2_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
|
||||
void nrfx_spim_3_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_SPIM3, &m_cb[NRFX_SPIM3_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_SPIM_ENABLED)
|
||||
513
modules/nrfx/drivers/src/nrfx_spis.c
Normal file
513
modules/nrfx/drivers/src/nrfx_spis.c
Normal file
@@ -0,0 +1,513 @@
|
||||
/**
|
||||
* Copyright (c) 2013 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_SPIS0_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_SPIS1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_SPIS2_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_SPIS3_ENABLED))
|
||||
#error "No enabled SPIS instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_spis.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
|
||||
#define NRFX_LOG_MODULE SPIS
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_SPIS_EVENT_ACQUIRED ? "NRF_SPIS_EVENT_ACQUIRED" : \
|
||||
(event == NRF_SPIS_EVENT_END ? "NRF_SPIS_EVENT_END" : \
|
||||
"UNKNOWN ERROR"))
|
||||
|
||||
#define SPISX_LENGTH_VALIDATE(peripheral, drv_inst_idx, rx_len, tx_len) \
|
||||
(((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
|
||||
NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, rx_len, tx_len))
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS0_ENABLED)
|
||||
#define SPIS0_LENGTH_VALIDATE(...) SPISX_LENGTH_VALIDATE(SPIS0, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIS0_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS1_ENABLED)
|
||||
#define SPIS1_LENGTH_VALIDATE(...) SPISX_LENGTH_VALIDATE(SPIS1, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIS1_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS2_ENABLED)
|
||||
#define SPIS2_LENGTH_VALIDATE(...) SPISX_LENGTH_VALIDATE(SPIS2, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIS2_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS3_ENABLED)
|
||||
#define SPIS3_LENGTH_VALIDATE(...) SPISX_LENGTH_VALIDATE(SPIS3, __VA_ARGS__)
|
||||
#else
|
||||
#define SPIS3_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#define SPIS_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) \
|
||||
(SPIS0_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
|
||||
SPIS1_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
|
||||
SPIS2_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
|
||||
SPIS3_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len))
|
||||
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
#include <nrfx_gpiote.h>
|
||||
#define USE_DMA_ISSUE_WORKAROUND
|
||||
// This handler is called by the GPIOTE driver when a falling edge is detected
|
||||
// on the CSN line. There is no need to do anything here. The handling of the
|
||||
// interrupt itself provides a protection for DMA transfers.
|
||||
static void csn_event_handler(nrfx_gpiote_pin_t pin,
|
||||
nrf_gpiote_polarity_t action)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief States of the SPI transaction state machine. */
|
||||
typedef enum
|
||||
{
|
||||
SPIS_STATE_INIT, /**< Initialization state. In this state the module waits for a call to @ref spi_slave_buffers_set. */
|
||||
SPIS_BUFFER_RESOURCE_REQUESTED, /**< State where the configuration of the memory buffers, which are to be used in SPI transaction, has started. */
|
||||
SPIS_BUFFER_RESOURCE_CONFIGURED, /**< State where the configuration of the memory buffers, which are to be used in SPI transaction, has completed. */
|
||||
SPIS_XFER_COMPLETED /**< State where SPI transaction has been completed. */
|
||||
} nrfx_spis_state_t;
|
||||
|
||||
/**@brief SPIS control block - driver instance local data. */
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t tx_buffer_size; //!< SPI slave TX buffer size in bytes.
|
||||
volatile uint32_t rx_buffer_size; //!< SPI slave RX buffer size in bytes.
|
||||
nrfx_spis_event_handler_t handler; //!< SPI event handler.
|
||||
volatile const uint8_t * tx_buffer; //!< SPI slave TX buffer.
|
||||
volatile uint8_t * rx_buffer; //!< SPI slave RX buffer.
|
||||
nrfx_drv_state_t state; //!< driver initialization state.
|
||||
volatile nrfx_spis_state_t spi_state; //!< SPI slave state.
|
||||
void * p_context; //!< Context set on initialization.
|
||||
} spis_cb_t;
|
||||
|
||||
static spis_cb_t m_cb[NRFX_SPIS_ENABLED_COUNT];
|
||||
|
||||
nrfx_err_t nrfx_spis_init(nrfx_spis_t const * const p_instance,
|
||||
nrfx_spis_config_t const * p_config,
|
||||
nrfx_spis_event_handler_t event_handler,
|
||||
void * p_context)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(event_handler);
|
||||
spis_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code;
|
||||
|
||||
NRF_SPIS_Type * p_spis = p_instance->p_reg;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if ((uint32_t)p_config->mode > (uint32_t)NRF_SPIS_MODE_3)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_SPIS_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_SPIS0_ENABLED)
|
||||
nrfx_spis_0_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIS1_ENABLED)
|
||||
nrfx_spis_1_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIS2_ENABLED)
|
||||
nrfx_spis_2_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIS3_ENABLED)
|
||||
nrfx_spis_3_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_spis,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
// Configure the SPI pins for input.
|
||||
uint32_t mosi_pin;
|
||||
uint32_t miso_pin;
|
||||
|
||||
if (p_config->miso_pin != NRFX_SPIS_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_cfg(p_config->miso_pin,
|
||||
NRF_GPIO_PIN_DIR_INPUT,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
p_config->miso_drive,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
miso_pin = p_config->miso_pin;
|
||||
}
|
||||
else
|
||||
{
|
||||
miso_pin = NRF_SPIS_PIN_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
if (p_config->mosi_pin != NRFX_SPIS_PIN_NOT_USED)
|
||||
{
|
||||
nrf_gpio_cfg(p_config->mosi_pin,
|
||||
NRF_GPIO_PIN_DIR_INPUT,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_S0S1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
mosi_pin = p_config->mosi_pin;
|
||||
}
|
||||
else
|
||||
{
|
||||
mosi_pin = NRF_SPIS_PIN_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
nrf_gpio_cfg(p_config->csn_pin,
|
||||
NRF_GPIO_PIN_DIR_INPUT,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT,
|
||||
p_config->csn_pullup,
|
||||
NRF_GPIO_PIN_S0S1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
|
||||
nrf_gpio_cfg(p_config->sck_pin,
|
||||
NRF_GPIO_PIN_DIR_INPUT,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_S0S1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
|
||||
nrf_spis_pins_set(p_spis, p_config->sck_pin, mosi_pin, miso_pin, p_config->csn_pin);
|
||||
|
||||
nrf_spis_rx_buffer_set(p_spis, NULL, 0);
|
||||
nrf_spis_tx_buffer_set(p_spis, NULL, 0);
|
||||
|
||||
// Configure SPI mode.
|
||||
nrf_spis_configure(p_spis, p_config->mode, p_config->bit_order);
|
||||
|
||||
// Configure DEF and ORC characters.
|
||||
nrf_spis_def_set(p_spis, p_config->def);
|
||||
nrf_spis_orc_set(p_spis, p_config->orc);
|
||||
|
||||
// Clear possible pending events.
|
||||
nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END);
|
||||
nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
|
||||
|
||||
// Enable END_ACQUIRE shortcut.
|
||||
nrf_spis_shorts_enable(p_spis, NRF_SPIS_SHORT_END_ACQUIRE);
|
||||
|
||||
p_cb->spi_state = SPIS_STATE_INIT;
|
||||
p_cb->handler = event_handler;
|
||||
p_cb->p_context = p_context;
|
||||
|
||||
#if defined(USE_DMA_ISSUE_WORKAROUND)
|
||||
// Configure a GPIOTE channel to generate interrupts on each falling edge
|
||||
// on the CSN line. Handling of these interrupts will make the CPU active,
|
||||
// and thus will protect the DMA transfers started by SPIS right after it
|
||||
// is selected for communication.
|
||||
// [the GPIOTE driver may be already initialized at this point (by this
|
||||
// driver when another SPIS instance is used, or by an application code),
|
||||
// so just ignore the returned value]
|
||||
(void)nrfx_gpiote_init();
|
||||
static nrfx_gpiote_in_config_t const csn_gpiote_config =
|
||||
NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
|
||||
nrfx_err_t gpiote_err_code = nrfx_gpiote_in_init(p_config->csn_pin,
|
||||
&csn_gpiote_config, csn_event_handler);
|
||||
if (gpiote_err_code != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_INTERNAL;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
nrfx_gpiote_in_event_enable(p_config->csn_pin, true);
|
||||
#endif
|
||||
|
||||
// Enable IRQ.
|
||||
nrf_spis_int_enable(p_spis, NRF_SPIS_INT_ACQUIRED_MASK |
|
||||
NRF_SPIS_INT_END_MASK);
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
|
||||
p_config->irq_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
// Enable SPI slave device.
|
||||
nrf_spis_enable(p_spis);
|
||||
|
||||
NRFX_LOG_INFO("Initialized.");
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_spis_uninit(nrfx_spis_t const * const p_instance)
|
||||
{
|
||||
spis_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
NRF_SPIS_Type * p_spis = p_instance->p_reg;
|
||||
|
||||
#define DISABLE_ALL 0xFFFFFFFF
|
||||
nrf_spis_disable(p_spis);
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
nrf_spis_int_disable(p_spis, DISABLE_ALL);
|
||||
#undef DISABLE_ALL
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_spis);
|
||||
#endif
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized.");
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for executing the state entry action. */
|
||||
static void spis_state_entry_action_execute(NRF_SPIS_Type * p_spis,
|
||||
spis_cb_t * p_cb)
|
||||
{
|
||||
nrfx_spis_evt_t event;
|
||||
|
||||
switch (p_cb->spi_state)
|
||||
{
|
||||
case SPIS_BUFFER_RESOURCE_REQUESTED:
|
||||
nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_ACQUIRE);
|
||||
break;
|
||||
|
||||
case SPIS_BUFFER_RESOURCE_CONFIGURED:
|
||||
event.evt_type = NRFX_SPIS_BUFFERS_SET_DONE;
|
||||
event.rx_amount = 0;
|
||||
event.tx_amount = 0;
|
||||
|
||||
NRFX_ASSERT(p_cb->handler != NULL);
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
break;
|
||||
|
||||
case SPIS_XFER_COMPLETED:
|
||||
event.evt_type = NRFX_SPIS_XFER_DONE;
|
||||
event.rx_amount = nrf_spis_rx_amount_get(p_spis);
|
||||
event.tx_amount = nrf_spis_tx_amount_get(p_spis);
|
||||
NRFX_LOG_INFO("Transfer rx_len:%d.", event.rx_amount);
|
||||
NRFX_LOG_DEBUG("Rx data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG((uint8_t const *)p_cb->rx_buffer,
|
||||
event.rx_amount * sizeof(p_cb->rx_buffer[0]));
|
||||
NRFX_ASSERT(p_cb->handler != NULL);
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No implementation required.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for changing the state of the SPI state machine.
|
||||
*
|
||||
* @param[in] p_spis SPIS instance register.
|
||||
* @param[in] p_cb SPIS instance control block.
|
||||
* @param[in] new_state State where the state machine transits to.
|
||||
*/
|
||||
static void spis_state_change(NRF_SPIS_Type * p_spis,
|
||||
spis_cb_t * p_cb,
|
||||
nrfx_spis_state_t new_state)
|
||||
{
|
||||
p_cb->spi_state = new_state;
|
||||
spis_state_entry_action_execute(p_spis, p_cb);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_spis_buffers_set(nrfx_spis_t const * const p_instance,
|
||||
uint8_t const * p_tx_buffer,
|
||||
size_t tx_buffer_length,
|
||||
uint8_t * p_rx_buffer,
|
||||
size_t rx_buffer_length)
|
||||
{
|
||||
NRFX_ASSERT(p_tx_buffer != NULL || tx_buffer_length == 0);
|
||||
NRFX_ASSERT(p_rx_buffer != NULL || rx_buffer_length == 0);
|
||||
|
||||
spis_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (!SPIS_LENGTH_VALIDATE(p_instance->drv_inst_idx,
|
||||
rx_buffer_length,
|
||||
tx_buffer_length))
|
||||
{
|
||||
return NRFX_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
// EasyDMA requires that transfer buffers are placed in Data RAM region;
|
||||
// signal error if they are not.
|
||||
if ((p_tx_buffer != NULL && !nrfx_is_in_ram(p_tx_buffer)) ||
|
||||
(p_rx_buffer != NULL && !nrfx_is_in_ram(p_rx_buffer)))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
switch (p_cb->spi_state)
|
||||
{
|
||||
case SPIS_STATE_INIT:
|
||||
case SPIS_XFER_COMPLETED:
|
||||
case SPIS_BUFFER_RESOURCE_CONFIGURED:
|
||||
p_cb->tx_buffer = p_tx_buffer;
|
||||
p_cb->rx_buffer = p_rx_buffer;
|
||||
p_cb->tx_buffer_size = tx_buffer_length;
|
||||
p_cb->rx_buffer_size = rx_buffer_length;
|
||||
err_code = NRFX_SUCCESS;
|
||||
|
||||
spis_state_change(p_instance->p_reg, p_cb, SPIS_BUFFER_RESOURCE_REQUESTED);
|
||||
break;
|
||||
|
||||
case SPIS_BUFFER_RESOURCE_REQUESTED:
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
break;
|
||||
|
||||
default:
|
||||
// @note: execution of this code path would imply internal error in the design.
|
||||
err_code = NRFX_ERROR_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
static void spis_irq_handler(NRF_SPIS_Type * p_spis, spis_cb_t * p_cb)
|
||||
{
|
||||
// @note: as multiple events can be pending for processing, the correct event processing order
|
||||
// is as follows:
|
||||
// - SPI semaphore acquired event.
|
||||
// - SPI transaction complete event.
|
||||
|
||||
// Check for SPI semaphore acquired event.
|
||||
if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_ACQUIRED))
|
||||
{
|
||||
nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
|
||||
NRFX_LOG_DEBUG("SPIS: Event: %s.", EVT_TO_STR(NRF_SPIS_EVENT_ACQUIRED));
|
||||
|
||||
switch (p_cb->spi_state)
|
||||
{
|
||||
case SPIS_BUFFER_RESOURCE_REQUESTED:
|
||||
nrf_spis_tx_buffer_set(p_spis, (uint8_t *)p_cb->tx_buffer, p_cb->tx_buffer_size);
|
||||
nrf_spis_rx_buffer_set(p_spis, (uint8_t *)p_cb->rx_buffer, p_cb->rx_buffer_size);
|
||||
|
||||
nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_RELEASE);
|
||||
|
||||
spis_state_change(p_spis, p_cb, SPIS_BUFFER_RESOURCE_CONFIGURED);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No implementation required.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for SPI transaction complete event.
|
||||
if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_END))
|
||||
{
|
||||
nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END);
|
||||
NRFX_LOG_DEBUG("SPIS: Event: %s.", EVT_TO_STR(NRF_SPIS_EVENT_END));
|
||||
|
||||
switch (p_cb->spi_state)
|
||||
{
|
||||
case SPIS_BUFFER_RESOURCE_CONFIGURED:
|
||||
spis_state_change(p_spis, p_cb, SPIS_XFER_COMPLETED);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No implementation required.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS0_ENABLED)
|
||||
void nrfx_spis_0_irq_handler(void)
|
||||
{
|
||||
spis_irq_handler(NRF_SPIS0, &m_cb[NRFX_SPIS0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS1_ENABLED)
|
||||
void nrfx_spis_1_irq_handler(void)
|
||||
{
|
||||
spis_irq_handler(NRF_SPIS1, &m_cb[NRFX_SPIS1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS2_ENABLED)
|
||||
void nrfx_spis_2_irq_handler(void)
|
||||
{
|
||||
spis_irq_handler(NRF_SPIS2, &m_cb[NRFX_SPIS2_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_SPIS3_ENABLED)
|
||||
void nrfx_spis_3_irq_handler(void)
|
||||
{
|
||||
spis_irq_handler(NRF_SPIS3, &m_cb[NRFX_SPIS3_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_SPIS_ENABLED)
|
||||
439
modules/nrfx/drivers/src/nrfx_swi.c
Normal file
439
modules/nrfx/drivers/src/nrfx_swi.c
Normal file
@@ -0,0 +1,439 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_SWI_ENABLED)
|
||||
|
||||
#include <nrfx_swi.h>
|
||||
|
||||
#define NRFX_LOG_MODULE SWI
|
||||
#include <nrfx_log.h>
|
||||
|
||||
|
||||
// NRFX_SWI_RESERVED_MASK - SWIs reserved for use by external modules.
|
||||
#if NRFX_CHECK(NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
#define NRFX_SWI_RESERVED_MASK ((NRFX_SWI_USED) | \
|
||||
(1u << NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE))
|
||||
#else
|
||||
#define NRFX_SWI_RESERVED_MASK (NRFX_SWI_USED)
|
||||
#endif
|
||||
|
||||
// NRFX_SWI_DISABLED_MASK - SWIs excluded from use in <nrfx_config.h>.
|
||||
#if NRFX_CHECK(NRFX_SWI0_DISABLED)
|
||||
#define NRFX_SWI0_DISABLED_MASK (1u << 0)
|
||||
#else
|
||||
#define NRFX_SWI0_DISABLED_MASK 0u
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SWI1_DISABLED)
|
||||
#define NRFX_SWI1_DISABLED_MASK (1u << 1)
|
||||
#else
|
||||
#define NRFX_SWI1_DISABLED_MASK 0u
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SWI2_DISABLED)
|
||||
#define NRFX_SWI2_DISABLED_MASK (1u << 2)
|
||||
#else
|
||||
#define NRFX_SWI2_DISABLED_MASK 0u
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SWI3_DISABLED)
|
||||
#define NRFX_SWI3_DISABLED_MASK (1u << 3)
|
||||
#else
|
||||
#define NRFX_SWI3_DISABLED_MASK 0u
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SWI4_DISABLED)
|
||||
#define NRFX_SWI4_DISABLED_MASK (1u << 4)
|
||||
#else
|
||||
#define NRFX_SWI4_DISABLED_MASK 0u
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SWI5_DISABLED)
|
||||
#define NRFX_SWI5_DISABLED_MASK (1u << 5)
|
||||
#else
|
||||
#define NRFX_SWI5_DISABLED_MASK 0u
|
||||
#endif
|
||||
#define NRFX_SWI_DISABLED_MASK (NRFX_SWI0_DISABLED_MASK | \
|
||||
NRFX_SWI1_DISABLED_MASK | \
|
||||
NRFX_SWI2_DISABLED_MASK | \
|
||||
NRFX_SWI3_DISABLED_MASK | \
|
||||
NRFX_SWI4_DISABLED_MASK | \
|
||||
NRFX_SWI5_DISABLED_MASK)
|
||||
|
||||
#if (NRFX_SWI_RESERVED_MASK & NRFX_SWI_DISABLED_MASK)
|
||||
#error "A reserved SWI configured to be disabled. Check <nrfx_config.h> and NRFX_SWI_USED."
|
||||
#endif
|
||||
|
||||
// NRFX_SWI_AVAILABLE_MASK - SWIs available for this module, i.e. present
|
||||
// in the hardware and neither reserved by external modules nor disabled
|
||||
// in <nrfx_config.h>.
|
||||
#define NRFX_SWI_PRESENT_MASK ((1u << (SWI_COUNT)) - 1u)
|
||||
#define NRFX_SWI_AVAILABLE_MASK (NRFX_SWI_PRESENT_MASK & \
|
||||
~(NRFX_SWI_RESERVED_MASK | \
|
||||
NRFX_SWI_DISABLED_MASK))
|
||||
|
||||
#if (NRFX_SWI_AVAILABLE_MASK == 0)
|
||||
#error "No available SWI instances. Check <nrfx_config.h> and NRFX_SWI_USED."
|
||||
#endif
|
||||
|
||||
#define NRFX_SWI_IS_AVAILABLE(idx) ((NRFX_SWI_AVAILABLE_MASK >> (idx)) & 1u)
|
||||
|
||||
#define NRFX_SWI_FIRST (NRFX_SWI_IS_AVAILABLE(0) ? 0u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(1) ? 1u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(2) ? 2u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(3) ? 3u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(4) ? 4u : \
|
||||
5u)))))
|
||||
#define NRFX_SWI_LAST (NRFX_SWI_IS_AVAILABLE(5) ? 5u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(4) ? 4u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(3) ? 3u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(2) ? 2u : \
|
||||
(NRFX_SWI_IS_AVAILABLE(1) ? 1u : \
|
||||
0u)))))
|
||||
|
||||
// NRFX_SWI_EGU_COUNT - number of EGU instances to be used by this module
|
||||
// (note - if EGU is not present, EGU_COUNT is not defined).
|
||||
#if NRFX_CHECK(NRFX_EGU_ENABLED)
|
||||
#define NRFX_SWI_EGU_COUNT EGU_COUNT
|
||||
#else
|
||||
#define NRFX_SWI_EGU_COUNT 0
|
||||
#endif
|
||||
|
||||
// These flags are needed only for SWIs that have no corresponding EGU unit
|
||||
// (in EGU such flags are available in hardware).
|
||||
#if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
|
||||
static nrfx_swi_flags_t m_swi_flags[SWI_COUNT - NRFX_SWI_EGU_COUNT];
|
||||
#endif
|
||||
static nrfx_swi_handler_t m_swi_handlers[SWI_COUNT];
|
||||
static uint8_t m_swi_allocated_mask;
|
||||
|
||||
|
||||
static void swi_mark_allocated(nrfx_swi_t swi)
|
||||
{
|
||||
m_swi_allocated_mask |= (1u << swi);
|
||||
}
|
||||
|
||||
static void swi_mark_unallocated(nrfx_swi_t swi)
|
||||
{
|
||||
m_swi_allocated_mask &= ~(1u << swi);
|
||||
}
|
||||
|
||||
static bool swi_is_allocated(nrfx_swi_t swi)
|
||||
{
|
||||
return (m_swi_allocated_mask & (1u << swi));
|
||||
}
|
||||
|
||||
static bool swi_is_available(nrfx_swi_t swi)
|
||||
{
|
||||
return NRFX_SWI_IS_AVAILABLE(swi);
|
||||
}
|
||||
|
||||
static IRQn_Type swi_irq_number_get(nrfx_swi_t swi)
|
||||
{
|
||||
#if defined(NRF_SWI)
|
||||
return (IRQn_Type)(nrfx_get_irq_number(NRF_SWI) + swi);
|
||||
#elif defined(NRF_SWI0)
|
||||
return (IRQn_Type)(nrfx_get_irq_number(NRF_SWI0) + swi);
|
||||
#else
|
||||
return (IRQn_Type)(nrfx_get_irq_number(NRF_EGU0) + swi);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void swi_int_enable(nrfx_swi_t swi)
|
||||
{
|
||||
#if NRFX_SWI_EGU_COUNT
|
||||
if (swi < NRFX_SWI_EGU_COUNT)
|
||||
{
|
||||
NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
|
||||
NRFX_ASSERT(p_egu != NULL);
|
||||
nrf_egu_int_enable(p_egu, NRF_EGU_INT_ALL);
|
||||
|
||||
if (m_swi_handlers[swi] == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NRFX_IRQ_ENABLE(swi_irq_number_get(swi));
|
||||
}
|
||||
|
||||
static void swi_int_disable(nrfx_swi_t swi)
|
||||
{
|
||||
NRFX_IRQ_DISABLE(swi_irq_number_get(swi));
|
||||
|
||||
#if NRFX_SWI_EGU_COUNT
|
||||
if (swi < NRFX_SWI_EGU_COUNT)
|
||||
{
|
||||
nrf_egu_int_disable(nrfx_swi_egu_instance_get(swi), NRF_EGU_INT_ALL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void swi_handler_setup(nrfx_swi_t swi,
|
||||
nrfx_swi_handler_t event_handler,
|
||||
uint32_t irq_priority)
|
||||
{
|
||||
m_swi_handlers[swi] = event_handler;
|
||||
NRFX_IRQ_PRIORITY_SET(swi_irq_number_get(swi), irq_priority);
|
||||
swi_int_enable(swi);
|
||||
}
|
||||
|
||||
static void swi_deallocate(nrfx_swi_t swi)
|
||||
{
|
||||
swi_int_disable(swi);
|
||||
m_swi_handlers[swi] = NULL;
|
||||
swi_mark_unallocated(swi);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_swi_alloc(nrfx_swi_t * p_swi,
|
||||
nrfx_swi_handler_t event_handler,
|
||||
uint32_t irq_priority)
|
||||
{
|
||||
NRFX_ASSERT(p_swi != NULL);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
for (nrfx_swi_t swi = NRFX_SWI_FIRST; swi <= NRFX_SWI_LAST; ++swi)
|
||||
{
|
||||
if (swi_is_available(swi))
|
||||
{
|
||||
bool allocated = false;
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
if (!swi_is_allocated(swi))
|
||||
{
|
||||
swi_mark_allocated(swi);
|
||||
allocated = true;
|
||||
}
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
|
||||
if (allocated)
|
||||
{
|
||||
swi_handler_setup(swi, event_handler, irq_priority);
|
||||
|
||||
*p_swi = swi;
|
||||
NRFX_LOG_INFO("SWI channel allocated: %d.", (*p_swi));
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err_code = NRFX_ERROR_NO_MEM;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
bool nrfx_swi_is_allocated(nrfx_swi_t swi)
|
||||
{
|
||||
return swi_is_allocated(swi);
|
||||
}
|
||||
|
||||
void nrfx_swi_int_disable(nrfx_swi_t swi)
|
||||
{
|
||||
NRFX_ASSERT(swi_is_allocated(swi));
|
||||
swi_int_disable(swi);
|
||||
}
|
||||
|
||||
void nrfx_swi_int_enable(nrfx_swi_t swi)
|
||||
{
|
||||
NRFX_ASSERT(swi_is_allocated(swi));
|
||||
swi_int_enable(swi);
|
||||
}
|
||||
|
||||
void nrfx_swi_free(nrfx_swi_t * p_swi)
|
||||
{
|
||||
NRFX_ASSERT(p_swi != NULL);
|
||||
nrfx_swi_t swi = *p_swi;
|
||||
|
||||
NRFX_ASSERT(swi_is_allocated(swi));
|
||||
swi_deallocate(swi);
|
||||
|
||||
*p_swi = NRFX_SWI_UNALLOCATED;
|
||||
}
|
||||
|
||||
void nrfx_swi_all_free(void)
|
||||
{
|
||||
for (nrfx_swi_t swi = NRFX_SWI_FIRST; swi <= NRFX_SWI_LAST; ++swi)
|
||||
{
|
||||
if (swi_is_allocated(swi))
|
||||
{
|
||||
swi_deallocate(swi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_swi_trigger(nrfx_swi_t swi, uint8_t flag_number)
|
||||
{
|
||||
NRFX_ASSERT(swi_is_allocated(swi));
|
||||
|
||||
#if NRFX_SWI_EGU_COUNT
|
||||
|
||||
NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
|
||||
#if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
|
||||
if (p_egu == NULL)
|
||||
{
|
||||
m_swi_flags[swi - NRFX_SWI_EGU_COUNT] |= (1 << flag_number);
|
||||
NRFX_IRQ_PENDING_SET(swi_irq_number_get(swi));
|
||||
}
|
||||
else
|
||||
#endif // (NRFX_SWI_EGU_COUNT < SWI_COUNT)
|
||||
{
|
||||
nrf_egu_task_trigger(p_egu,
|
||||
nrf_egu_task_trigger_get(p_egu, flag_number));
|
||||
}
|
||||
|
||||
#else // -> #if !NRFX_SWI_EGU_COUNT
|
||||
|
||||
m_swi_flags[swi - NRFX_SWI_EGU_COUNT] |= (1 << flag_number);
|
||||
NRFX_IRQ_PENDING_SET(swi_irq_number_get(swi));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NRFX_SWI_EGU_COUNT
|
||||
static void egu_irq_handler(nrfx_swi_t swi, uint8_t egu_channel_count)
|
||||
{
|
||||
#if (NRFX_SWI_FIRST > 0)
|
||||
NRFX_ASSERT(swi >= NRFX_SWI_FIRST);
|
||||
#endif
|
||||
NRFX_ASSERT(swi <= NRFX_SWI_LAST);
|
||||
nrfx_swi_handler_t handler = m_swi_handlers[swi];
|
||||
NRFX_ASSERT(handler != NULL);
|
||||
|
||||
NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
|
||||
NRFX_ASSERT(p_egu != NULL);
|
||||
|
||||
nrfx_swi_flags_t flags = 0;
|
||||
for (uint8_t i = 0; i < egu_channel_count; ++i)
|
||||
{
|
||||
nrf_egu_event_t egu_event = nrf_egu_event_triggered_get(p_egu, i);
|
||||
if (nrf_egu_event_check(p_egu, egu_event))
|
||||
{
|
||||
flags |= (1u << i);
|
||||
nrf_egu_event_clear(p_egu, egu_event);
|
||||
}
|
||||
}
|
||||
|
||||
handler(swi, flags);
|
||||
}
|
||||
#endif // NRFX_SWI_EGU_COUNT
|
||||
|
||||
#if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
|
||||
static void swi_irq_handler(nrfx_swi_t swi)
|
||||
{
|
||||
#if (NRFX_SWI_FIRST > 0)
|
||||
NRFX_ASSERT(swi >= NRFX_SWI_FIRST);
|
||||
#endif
|
||||
NRFX_ASSERT(swi <= NRFX_SWI_LAST);
|
||||
nrfx_swi_handler_t handler = m_swi_handlers[swi];
|
||||
NRFX_ASSERT(handler != NULL);
|
||||
|
||||
nrfx_swi_flags_t flags = m_swi_flags[swi - NRFX_SWI_EGU_COUNT];
|
||||
m_swi_flags[swi - NRFX_SWI_EGU_COUNT] &= ~flags;
|
||||
|
||||
handler(swi, flags);
|
||||
}
|
||||
#endif // (NRFX_SWI_EGU_COUNT < SWI_COUNT)
|
||||
|
||||
|
||||
#if NRFX_SWI_IS_AVAILABLE(0)
|
||||
void nrfx_swi_0_irq_handler(void)
|
||||
{
|
||||
#if (NRFX_SWI_EGU_COUNT > 0)
|
||||
egu_irq_handler(0, EGU0_CH_NUM);
|
||||
#else
|
||||
swi_irq_handler(0);
|
||||
#endif
|
||||
}
|
||||
#endif // NRFX_SWI_IS_AVAILABLE(0)
|
||||
|
||||
#if NRFX_SWI_IS_AVAILABLE(1)
|
||||
void nrfx_swi_1_irq_handler(void)
|
||||
{
|
||||
#if (NRFX_SWI_EGU_COUNT > 1)
|
||||
egu_irq_handler(1, EGU1_CH_NUM);
|
||||
#else
|
||||
swi_irq_handler(1);
|
||||
#endif
|
||||
}
|
||||
#endif // NRFX_SWI_IS_AVAILABLE(1)
|
||||
|
||||
#if NRFX_SWI_IS_AVAILABLE(2)
|
||||
void nrfx_swi_2_irq_handler(void)
|
||||
{
|
||||
#if (NRFX_SWI_EGU_COUNT > 2)
|
||||
egu_irq_handler(2, EGU2_CH_NUM);
|
||||
#else
|
||||
swi_irq_handler(2);
|
||||
#endif
|
||||
}
|
||||
#endif // NRFX_SWI_IS_AVAILABLE(2)
|
||||
|
||||
#if NRFX_SWI_IS_AVAILABLE(3)
|
||||
void nrfx_swi_3_irq_handler(void)
|
||||
{
|
||||
#if (NRFX_SWI_EGU_COUNT > 3)
|
||||
egu_irq_handler(3, EGU3_CH_NUM);
|
||||
#else
|
||||
swi_irq_handler(3);
|
||||
#endif
|
||||
}
|
||||
#endif // NRFX_SWI_IS_AVAILABLE(3)
|
||||
|
||||
#if NRFX_SWI_IS_AVAILABLE(4)
|
||||
void nrfx_swi_4_irq_handler(void)
|
||||
{
|
||||
#if (NRFX_SWI_EGU_COUNT > 4)
|
||||
egu_irq_handler(4, EGU4_CH_NUM);
|
||||
#else
|
||||
swi_irq_handler(4);
|
||||
#endif
|
||||
}
|
||||
#endif // NRFX_SWI_IS_AVAILABLE(4)
|
||||
|
||||
#if NRFX_SWI_IS_AVAILABLE(5)
|
||||
void nrfx_swi_5_irq_handler(void)
|
||||
{
|
||||
#if (NRFX_SWI_EGU_COUNT > 5)
|
||||
egu_irq_handler(5, EGU5_CH_NUM);
|
||||
#else
|
||||
swi_irq_handler(5);
|
||||
#endif
|
||||
}
|
||||
#endif // NRFX_SWI_IS_AVAILABLE(5)
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_SWI_ENABLED)
|
||||
170
modules/nrfx/drivers/src/nrfx_systick.c
Normal file
170
modules/nrfx/drivers/src/nrfx_systick.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_SYSTICK_ENABLED)
|
||||
#include <nrfx_systick.h>
|
||||
|
||||
/**
|
||||
* @brief Maximum number of ticks to delay
|
||||
*
|
||||
* The maximum number of ticks should be much lower than
|
||||
* Physical maximum count of the SysTick timer.
|
||||
* It is dictated by the fact that it would be impossible to detect delay
|
||||
* properly when the timer value warps around the starting point.
|
||||
*/
|
||||
#define NRFX_SYSTICK_TICKS_MAX (NRF_SYSTICK_VAL_MASK / 2UL)
|
||||
|
||||
/**
|
||||
* @brief Number of milliseconds in a second
|
||||
*/
|
||||
#define NRFX_SYSTICK_MS (1000UL)
|
||||
|
||||
/**
|
||||
* @brief Number of microseconds in a second
|
||||
*/
|
||||
#define NRFX_SYSTICK_US (1000UL * NRFX_SYSTICK_MS)
|
||||
|
||||
/**
|
||||
* @brief Number of milliseconds to wait in single loop
|
||||
*
|
||||
* Constant used by @ref nrd_drv_systick_delay_ms function
|
||||
* to split waiting into loops and rest.
|
||||
*
|
||||
* It describes the number of milliseconds to wait in single loop.
|
||||
*
|
||||
* See @ref nrfx_systick_delay_ms source code for details.
|
||||
*/
|
||||
#define NRFX_SYSTICK_MS_STEP (64U)
|
||||
|
||||
/**
|
||||
* @brief Checks if the given time is in correct range
|
||||
*
|
||||
* Function tests given time is not to big for this library.
|
||||
* Assertion is used for testing.
|
||||
*
|
||||
* @param us Time in microseconds to check
|
||||
*/
|
||||
#define NRFX_SYSTICK_ASSERT_TIMEOUT(us) \
|
||||
NRFX_ASSERT(us <= (NRFX_SYSTICK_TICKS_MAX / ((SystemCoreClock) / NRFX_SYSTICK_US)));
|
||||
|
||||
/**
|
||||
* @brief Function that converts microseconds to ticks
|
||||
*
|
||||
* Function converts from microseconds to CPU ticks.
|
||||
*
|
||||
* @param us Number of microseconds
|
||||
*
|
||||
* @return Number of ticks
|
||||
*
|
||||
* @sa nrfx_systick_ms_tick
|
||||
*/
|
||||
static inline uint32_t nrfx_systick_us_tick(uint32_t us)
|
||||
{
|
||||
return us * ((SystemCoreClock) / NRFX_SYSTICK_US);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function that converts milliseconds to ticks
|
||||
*
|
||||
* Function converts from milliseconds to CPU ticks.
|
||||
*
|
||||
* @param us Number of milliseconds
|
||||
*
|
||||
* @return Number of ticks
|
||||
*
|
||||
* @sa nrfx_systick_us_tick
|
||||
*/
|
||||
static inline uint32_t nrfx_systick_ms_tick(uint32_t ms)
|
||||
{
|
||||
return ms * ((SystemCoreClock) / NRFX_SYSTICK_MS);
|
||||
}
|
||||
|
||||
void nrfx_systick_init(void)
|
||||
{
|
||||
nrf_systick_load_set(NRF_SYSTICK_VAL_MASK);
|
||||
nrf_systick_csr_set(
|
||||
NRF_SYSTICK_CSR_CLKSOURCE_CPU |
|
||||
NRF_SYSTICK_CSR_TICKINT_DISABLE |
|
||||
NRF_SYSTICK_CSR_ENABLE);
|
||||
}
|
||||
|
||||
void nrfx_systick_get(nrfx_systick_state_t * p_state)
|
||||
{
|
||||
p_state->time = nrf_systick_val_get();
|
||||
}
|
||||
|
||||
bool nrfx_systick_test(nrfx_systick_state_t const * p_state, uint32_t us)
|
||||
{
|
||||
NRFX_SYSTICK_ASSERT_TIMEOUT(us);
|
||||
|
||||
const uint32_t diff = NRF_SYSTICK_VAL_MASK & ((p_state->time) - nrf_systick_val_get());
|
||||
return (diff >= nrfx_systick_us_tick(us));
|
||||
}
|
||||
|
||||
void nrfx_systick_delay_ticks(uint32_t ticks)
|
||||
{
|
||||
NRFX_ASSERT(ticks <= NRFX_SYSTICK_TICKS_MAX);
|
||||
|
||||
const uint32_t start = nrf_systick_val_get();
|
||||
while ((NRF_SYSTICK_VAL_MASK & (start - nrf_systick_val_get())) < ticks)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_systick_delay_us(uint32_t us)
|
||||
{
|
||||
NRFX_SYSTICK_ASSERT_TIMEOUT(us);
|
||||
nrfx_systick_delay_ticks(nrfx_systick_us_tick(us));
|
||||
}
|
||||
|
||||
void nrfx_systick_delay_ms(uint32_t ms)
|
||||
{
|
||||
uint32_t n = ms / NRFX_SYSTICK_MS_STEP;
|
||||
uint32_t r = ms % NRFX_SYSTICK_MS_STEP;
|
||||
while (0 != (n--))
|
||||
{
|
||||
nrfx_systick_delay_ticks(nrfx_systick_ms_tick(NRFX_SYSTICK_MS_STEP));
|
||||
}
|
||||
nrfx_systick_delay_ticks(nrfx_systick_ms_tick(r));
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_SYSTICK_ENABLED)
|
||||
155
modules/nrfx/drivers/src/nrfx_temp.c
Normal file
155
modules/nrfx/drivers/src/nrfx_temp.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_TEMP_ENABLED)
|
||||
|
||||
#include <nrfx_temp.h>
|
||||
|
||||
#if !defined(USE_WORKAROUND_FOR_TEMP_OFFSET_ANOMALY) && defined(NRF51)
|
||||
// Enable workaround for nRF51 series anomaly 28
|
||||
// (TEMP: Temperature offset value has to be manually loaded to the TEMP module).
|
||||
#define USE_WORKAROUND_FOR_TEMP_OFFSET_ANOMALY 1
|
||||
#endif
|
||||
|
||||
/** @brief Time of one check attempt.*/
|
||||
#define NRFX_TEMP_TIME_US 4
|
||||
|
||||
/** @brief Maximum attempts to check whether conversion passed.*/
|
||||
#define NRFX_TEMP_ATTEMPTS 10
|
||||
|
||||
/** @brief Internal state of TEMP driver. */
|
||||
static nrfx_drv_state_t m_temp_state;
|
||||
|
||||
/** @brief Pointer to handler to be called from interrupt routine. */
|
||||
static nrfx_temp_data_handler_t m_data_handler;
|
||||
|
||||
nrfx_err_t nrfx_temp_init(nrfx_temp_config_t const * p_config, nrfx_temp_data_handler_t handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
|
||||
if (m_temp_state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
return NRFX_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(USE_WORKAROUND_FOR_TEMP_OFFSET_ANOMALY)
|
||||
*(uint32_t volatile *)0x4000C504 = 0;
|
||||
#endif
|
||||
|
||||
m_data_handler = handler;
|
||||
|
||||
if (m_data_handler)
|
||||
{
|
||||
nrf_temp_int_enable(NRF_TEMP, NRF_TEMP_INT_DATARDY_MASK);
|
||||
NRFX_IRQ_PRIORITY_SET(TEMP_IRQn, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(TEMP_IRQn);
|
||||
}
|
||||
|
||||
m_temp_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
|
||||
void nrfx_temp_uninit(void)
|
||||
{
|
||||
NRFX_ASSERT(m_temp_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_STOP);
|
||||
|
||||
if (m_data_handler)
|
||||
{
|
||||
nrf_temp_int_disable(NRF_TEMP, NRF_TEMP_INT_DATARDY_MASK);
|
||||
NRFX_IRQ_DISABLE(TEMP_IRQn);
|
||||
}
|
||||
|
||||
m_temp_state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
int32_t nrfx_temp_calculate(int32_t raw_measurement)
|
||||
{
|
||||
/* Raw temperature is a 2's complement signed value. Moreover, it is represented
|
||||
* by 0.25[C] intervals, so division by 4 is needed. To preserve
|
||||
* fractional part, raw value is multiplied by 100 before division.*/
|
||||
|
||||
return (raw_measurement * 100) / 4;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_temp_measure(void)
|
||||
{
|
||||
NRFX_ASSERT(m_temp_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
|
||||
nrfx_err_t result = NRFX_SUCCESS;
|
||||
nrf_temp_event_clear(NRF_TEMP, NRF_TEMP_EVENT_DATARDY);
|
||||
nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_START);
|
||||
|
||||
if (!m_data_handler)
|
||||
{
|
||||
bool ev_result;
|
||||
NRFX_WAIT_FOR(nrf_temp_event_check(NRF_TEMP, NRF_TEMP_EVENT_DATARDY),
|
||||
NRFX_TEMP_ATTEMPTS,
|
||||
NRFX_TEMP_TIME_US,
|
||||
ev_result);
|
||||
if (!ev_result)
|
||||
{
|
||||
result = NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_temp_event_clear(NRF_TEMP, NRF_TEMP_EVENT_DATARDY);
|
||||
}
|
||||
nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_STOP);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void nrfx_temp_irq_handler(void)
|
||||
{
|
||||
NRFX_ASSERT(m_data_handler);
|
||||
|
||||
nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_STOP);
|
||||
nrf_temp_event_clear(NRF_TEMP, NRF_TEMP_EVENT_DATARDY);
|
||||
|
||||
uint32_t raw_temp = nrfx_temp_result_get();
|
||||
|
||||
m_data_handler(raw_temp);
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_TEMP_ENABLED)
|
||||
330
modules/nrfx/drivers/src/nrfx_timer.c
Normal file
330
modules/nrfx/drivers/src/nrfx_timer.c
Normal file
@@ -0,0 +1,330 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_TIMER_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_TIMER0_ENABLED) || NRFX_CHECK(NRFX_TIMER1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TIMER2_ENABLED) || NRFX_CHECK(NRFX_TIMER3_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TIMER4_ENABLED))
|
||||
#error "No enabled TIMER instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_timer.h>
|
||||
|
||||
#define NRFX_LOG_MODULE TIMER
|
||||
#include <nrfx_log.h>
|
||||
|
||||
/**@brief Timer control block. */
|
||||
typedef struct
|
||||
{
|
||||
nrfx_timer_event_handler_t handler;
|
||||
void * context;
|
||||
nrfx_drv_state_t state;
|
||||
} timer_control_block_t;
|
||||
|
||||
static timer_control_block_t m_cb[NRFX_TIMER_ENABLED_COUNT];
|
||||
|
||||
nrfx_err_t nrfx_timer_init(nrfx_timer_t const * const p_instance,
|
||||
nrfx_timer_config_t const * p_config,
|
||||
nrfx_timer_event_handler_t timer_event_handler)
|
||||
{
|
||||
timer_control_block_t * p_cb = &m_cb[p_instance->instance_id];
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
NRFX_ASSERT(p_instance->p_reg != NRF_TIMER0);
|
||||
#endif
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(timer_event_handler);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
/* Warning 685: Relational operator '<=' always evaluates to 'true'"
|
||||
* Warning in NRF_TIMER_IS_BIT_WIDTH_VALID macro. Macro validate timers resolution.
|
||||
* Not necessary in nRF52 based systems. Obligatory in nRF51 based systems.
|
||||
*/
|
||||
|
||||
/*lint -save -e685 */
|
||||
|
||||
NRFX_ASSERT(NRF_TIMER_IS_BIT_WIDTH_VALID(p_instance->p_reg, p_config->bit_width));
|
||||
|
||||
//lint -restore
|
||||
|
||||
p_cb->handler = timer_event_handler;
|
||||
p_cb->context = p_config->p_context;
|
||||
|
||||
uint8_t i;
|
||||
for (i = 0; i < p_instance->cc_channel_count; ++i)
|
||||
{
|
||||
nrf_timer_event_clear(p_instance->p_reg,
|
||||
nrf_timer_compare_event_get(i));
|
||||
}
|
||||
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
|
||||
p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
|
||||
nrf_timer_mode_set(p_instance->p_reg, p_config->mode);
|
||||
nrf_timer_bit_width_set(p_instance->p_reg, p_config->bit_width);
|
||||
nrf_timer_frequency_set(p_instance->p_reg, p_config->frequency);
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_timer_uninit(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
|
||||
|
||||
#define DISABLE_ALL UINT32_MAX
|
||||
nrf_timer_shorts_disable(p_instance->p_reg, DISABLE_ALL);
|
||||
nrf_timer_int_disable(p_instance->p_reg, DISABLE_ALL);
|
||||
#undef DISABLE_ALL
|
||||
|
||||
nrfx_timer_disable(p_instance);
|
||||
|
||||
m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Uninitialized instance: %d.", p_instance->instance_id);
|
||||
}
|
||||
|
||||
void nrfx_timer_enable(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_INITIALIZED);
|
||||
nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START);
|
||||
m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Enabled instance: %d.", p_instance->instance_id);
|
||||
}
|
||||
|
||||
void nrfx_timer_disable(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_SHUTDOWN);
|
||||
m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Disabled instance: %d.", p_instance->instance_id);
|
||||
}
|
||||
|
||||
bool nrfx_timer_is_enabled(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
return (m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_POWERED_ON);
|
||||
}
|
||||
|
||||
void nrfx_timer_resume(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START);
|
||||
NRFX_LOG_INFO("Resumed instance: %d.", p_instance->instance_id);
|
||||
}
|
||||
|
||||
void nrfx_timer_pause(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_STOP);
|
||||
NRFX_LOG_INFO("Paused instance: %d.", p_instance->instance_id);
|
||||
}
|
||||
|
||||
void nrfx_timer_clear(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_CLEAR);
|
||||
}
|
||||
|
||||
void nrfx_timer_increment(nrfx_timer_t const * const p_instance)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(nrf_timer_mode_get(p_instance->p_reg) != NRF_TIMER_MODE_TIMER);
|
||||
|
||||
nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_COUNT);
|
||||
}
|
||||
|
||||
uint32_t nrfx_timer_capture(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(cc_channel < p_instance->cc_channel_count);
|
||||
|
||||
nrf_timer_task_trigger(p_instance->p_reg,
|
||||
nrf_timer_capture_task_get(cc_channel));
|
||||
return nrf_timer_cc_read(p_instance->p_reg, cc_channel);
|
||||
}
|
||||
|
||||
void nrfx_timer_compare(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel,
|
||||
uint32_t cc_value,
|
||||
bool enable_int)
|
||||
{
|
||||
nrf_timer_int_mask_t timer_int = nrf_timer_compare_int_get(cc_channel);
|
||||
|
||||
if (enable_int)
|
||||
{
|
||||
nrf_timer_event_clear(p_instance->p_reg, nrf_timer_compare_event_get(cc_channel));
|
||||
nrf_timer_int_enable(p_instance->p_reg, timer_int);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_timer_int_disable(p_instance->p_reg, timer_int);
|
||||
}
|
||||
|
||||
nrf_timer_cc_write(p_instance->p_reg, cc_channel, cc_value);
|
||||
NRFX_LOG_INFO("Timer id: %d, capture value set: %lu, channel: %d.",
|
||||
p_instance->instance_id,
|
||||
cc_value,
|
||||
cc_channel);
|
||||
}
|
||||
|
||||
void nrfx_timer_extended_compare(nrfx_timer_t const * const p_instance,
|
||||
nrf_timer_cc_channel_t cc_channel,
|
||||
uint32_t cc_value,
|
||||
nrf_timer_short_mask_t timer_short_mask,
|
||||
bool enable_int)
|
||||
{
|
||||
nrf_timer_shorts_disable(p_instance->p_reg,
|
||||
(TIMER_SHORTS_COMPARE0_STOP_Msk << cc_channel) |
|
||||
(TIMER_SHORTS_COMPARE0_CLEAR_Msk << cc_channel));
|
||||
|
||||
nrf_timer_shorts_enable(p_instance->p_reg, timer_short_mask);
|
||||
|
||||
nrfx_timer_compare(p_instance,
|
||||
cc_channel,
|
||||
cc_value,
|
||||
enable_int);
|
||||
NRFX_LOG_INFO("Timer id: %d, capture value set: %lu, channel: %d.",
|
||||
p_instance->instance_id,
|
||||
cc_value,
|
||||
cc_channel);
|
||||
}
|
||||
|
||||
void nrfx_timer_compare_int_enable(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(channel < p_instance->cc_channel_count);
|
||||
|
||||
nrf_timer_event_clear(p_instance->p_reg,
|
||||
nrf_timer_compare_event_get(channel));
|
||||
nrf_timer_int_enable(p_instance->p_reg,
|
||||
nrf_timer_compare_int_get(channel));
|
||||
}
|
||||
|
||||
void nrfx_timer_compare_int_disable(nrfx_timer_t const * const p_instance,
|
||||
uint32_t channel)
|
||||
{
|
||||
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
NRFX_ASSERT(channel < p_instance->cc_channel_count);
|
||||
|
||||
nrf_timer_int_disable(p_instance->p_reg,
|
||||
nrf_timer_compare_int_get(channel));
|
||||
}
|
||||
|
||||
static void irq_handler(NRF_TIMER_Type * p_reg,
|
||||
timer_control_block_t * p_cb,
|
||||
uint8_t channel_count)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < channel_count; ++i)
|
||||
{
|
||||
nrf_timer_event_t event = nrf_timer_compare_event_get(i);
|
||||
nrf_timer_int_mask_t int_mask = nrf_timer_compare_int_get(i);
|
||||
|
||||
if (nrf_timer_event_check(p_reg, event) &&
|
||||
nrf_timer_int_enable_check(p_reg, int_mask))
|
||||
{
|
||||
nrf_timer_event_clear(p_reg, event);
|
||||
NRFX_LOG_DEBUG("Compare event, channel: %d.", i);
|
||||
p_cb->handler(event, p_cb->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_TIMER0_ENABLED)
|
||||
void nrfx_timer_0_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_TIMER0, &m_cb[NRFX_TIMER0_INST_IDX],
|
||||
NRF_TIMER_CC_CHANNEL_COUNT(0));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TIMER1_ENABLED)
|
||||
void nrfx_timer_1_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_TIMER1, &m_cb[NRFX_TIMER1_INST_IDX],
|
||||
NRF_TIMER_CC_CHANNEL_COUNT(1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TIMER2_ENABLED)
|
||||
void nrfx_timer_2_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_TIMER2, &m_cb[NRFX_TIMER2_INST_IDX],
|
||||
NRF_TIMER_CC_CHANNEL_COUNT(2));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TIMER3_ENABLED)
|
||||
void nrfx_timer_3_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_TIMER3, &m_cb[NRFX_TIMER3_INST_IDX],
|
||||
NRF_TIMER_CC_CHANNEL_COUNT(3));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TIMER4_ENABLED)
|
||||
void nrfx_timer_4_irq_handler(void)
|
||||
{
|
||||
irq_handler(NRF_TIMER4, &m_cb[NRFX_TIMER4_INST_IDX],
|
||||
NRF_TIMER_CC_CHANNEL_COUNT(4));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_TIMER_ENABLED)
|
||||
783
modules/nrfx/drivers/src/nrfx_twi.c
Normal file
783
modules/nrfx/drivers/src/nrfx_twi.c
Normal file
@@ -0,0 +1,783 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWI_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_TWI0_ENABLED) || NRFX_CHECK(NRFX_TWI1_ENABLED))
|
||||
#error "No enabled TWI instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_twi.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
|
||||
#define NRFX_LOG_MODULE TWI
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRFX_TWI_EVT_DONE ? "EVT_DONE" : \
|
||||
(event == NRFX_TWI_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \
|
||||
(event == NRFX_TWI_EVT_DATA_NACK ? "EVT_DATA_NACK" : \
|
||||
(event == NRFX_TWI_EVT_OVERRUN ? "EVT_OVERRUN" : \
|
||||
(event == NRFX_TWI_EVT_BUS_ERROR ? "EVT_BUS_ERROR" : \
|
||||
"UNKNOWN ERROR")))))
|
||||
|
||||
#define EVT_TO_STR_TWI(event) \
|
||||
(event == NRF_TWI_EVENT_STOPPED ? "NRF_TWI_EVENT_STOPPED" : \
|
||||
(event == NRF_TWI_EVENT_RXDREADY ? "NRF_TWI_EVENT_RXDREADY" : \
|
||||
(event == NRF_TWI_EVENT_TXDSENT ? "NRF_TWI_EVENT_TXDSENT" : \
|
||||
(event == NRF_TWI_EVENT_ERROR ? "NRF_TWI_EVENT_ERROR" : \
|
||||
(event == NRF_TWI_EVENT_BB ? "NRF_TWI_EVENT_BB" : \
|
||||
(event == NRF_TWI_EVENT_SUSPENDED ? "NRF_TWI_EVENT_SUSPENDED" : \
|
||||
"UNKNOWN ERROR"))))))
|
||||
|
||||
#define TRANSFER_TO_STR(type) \
|
||||
(type == NRFX_TWI_XFER_TX ? "XFER_TX" : \
|
||||
(type == NRFX_TWI_XFER_RX ? "XFER_RX" : \
|
||||
(type == NRFX_TWI_XFER_TXRX ? "XFER_TXRX" : \
|
||||
(type == NRFX_TWI_XFER_TXTX ? "XFER_TXTX" : \
|
||||
"UNKNOWN TRANSFER TYPE"))))
|
||||
|
||||
#define TWI_PIN_INIT(_pin) nrf_gpio_cfg((_pin), \
|
||||
NRF_GPIO_PIN_DIR_INPUT, \
|
||||
NRF_GPIO_PIN_INPUT_CONNECT, \
|
||||
NRF_GPIO_PIN_PULLUP, \
|
||||
NRF_GPIO_PIN_S0D1, \
|
||||
NRF_GPIO_PIN_NOSENSE)
|
||||
|
||||
#define TWI_FLAG_NO_STOP(flags) (flags & NRFX_TWI_FLAG_TX_NO_STOP)
|
||||
#define TWI_FLAG_SUSPEND(flags) (flags & NRFX_TWI_FLAG_SUSPEND)
|
||||
#define TWI_FLAG_NO_HANDLER_IN_USE(flags) (flags & NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER)
|
||||
|
||||
#define HW_TIMEOUT 100000
|
||||
|
||||
/* TWI master driver suspend types. */
|
||||
typedef enum
|
||||
{
|
||||
TWI_NO_SUSPEND, //< Last transfer was not suspended.
|
||||
TWI_SUSPEND_TX, //< Last transfer was TX and was suspended.
|
||||
TWI_SUSPEND_RX //< Last transfer was RX and was suspended.
|
||||
} twi_suspend_t;
|
||||
|
||||
// Control block - driver instance local data.
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twi_evt_handler_t handler;
|
||||
void * p_context;
|
||||
volatile uint32_t int_mask;
|
||||
nrfx_twi_xfer_desc_t xfer_desc;
|
||||
uint32_t flags;
|
||||
uint8_t * p_curr_buf;
|
||||
size_t curr_length;
|
||||
bool curr_tx_no_stop;
|
||||
twi_suspend_t prev_suspend;
|
||||
nrfx_drv_state_t state;
|
||||
bool error;
|
||||
volatile bool busy;
|
||||
bool repeated;
|
||||
size_t bytes_transferred;
|
||||
bool hold_bus_uninit;
|
||||
} twi_control_block_t;
|
||||
|
||||
static twi_control_block_t m_cb[NRFX_TWI_ENABLED_COUNT];
|
||||
|
||||
static nrfx_err_t twi_process_error(uint32_t errorsrc)
|
||||
{
|
||||
nrfx_err_t ret = NRFX_ERROR_INTERNAL;
|
||||
|
||||
if (errorsrc & NRF_TWI_ERROR_OVERRUN)
|
||||
{
|
||||
ret = NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
|
||||
}
|
||||
|
||||
if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
|
||||
{
|
||||
ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
|
||||
}
|
||||
|
||||
if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
|
||||
{
|
||||
ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool xfer_completeness_check(NRF_TWI_Type * p_twi, twi_control_block_t const * p_cb)
|
||||
{
|
||||
// If the actual number of transferred bytes is not equal to what was requested,
|
||||
// but there was no error signaled by the peripheral, this means that something
|
||||
// unexpected, like a premature STOP condition, was received on the bus.
|
||||
// In such case the peripheral has to be disabled and re-enabled, so that its
|
||||
// internal state machine is reinitialized.
|
||||
|
||||
if (p_cb->bytes_transferred != p_cb->curr_length)
|
||||
{
|
||||
nrf_twi_disable(p_twi);
|
||||
nrf_twi_enable(p_twi);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_twi_init(nrfx_twi_t const * p_instance,
|
||||
nrfx_twi_config_t const * p_config,
|
||||
nrfx_twi_evt_handler_t event_handler,
|
||||
void * p_context)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(p_config->scl != p_config->sda);
|
||||
twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_TWI_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_TWI0_ENABLED)
|
||||
nrfx_twi_0_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWI1_ENABLED)
|
||||
nrfx_twi_1_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_instance->p_twi,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
p_cb->handler = event_handler;
|
||||
p_cb->p_context = p_context;
|
||||
p_cb->int_mask = 0;
|
||||
p_cb->prev_suspend = TWI_NO_SUSPEND;
|
||||
p_cb->repeated = false;
|
||||
p_cb->busy = false;
|
||||
p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
|
||||
|
||||
/* To secure correct signal levels on the pins used by the TWI
|
||||
master when the system is in OFF mode, and when the TWI master is
|
||||
disabled, these pins must be configured in the GPIO peripheral.
|
||||
*/
|
||||
TWI_PIN_INIT(p_config->scl);
|
||||
TWI_PIN_INIT(p_config->sda);
|
||||
|
||||
NRF_TWI_Type * p_twi = p_instance->p_twi;
|
||||
nrf_twi_pins_set(p_twi, p_config->scl, p_config->sda);
|
||||
nrf_twi_frequency_set(p_twi,
|
||||
(nrf_twi_frequency_t)p_config->frequency);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twi),
|
||||
p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twi));
|
||||
}
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_twi_uninit(nrfx_twi_t const * p_instance)
|
||||
{
|
||||
twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twi));
|
||||
}
|
||||
nrfx_twi_disable(p_instance);
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_instance->p_twi);
|
||||
#endif
|
||||
|
||||
if (!p_cb->hold_bus_uninit)
|
||||
{
|
||||
nrf_gpio_cfg_default(nrf_twi_scl_pin_get(p_instance->p_twi));
|
||||
nrf_gpio_cfg_default(nrf_twi_sda_pin_get(p_instance->p_twi));
|
||||
}
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
void nrfx_twi_enable(nrfx_twi_t const * p_instance)
|
||||
{
|
||||
twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
|
||||
|
||||
NRF_TWI_Type * p_twi = p_instance->p_twi;
|
||||
nrf_twi_enable(p_twi);
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
void nrfx_twi_disable(nrfx_twi_t const * p_instance)
|
||||
{
|
||||
twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
NRF_TWI_Type * p_twi = p_instance->p_twi;
|
||||
nrf_twi_int_disable(p_twi, NRF_TWI_ALL_INTS_MASK);
|
||||
nrf_twi_shorts_disable(p_twi, NRF_TWI_ALL_SHORTS_MASK);
|
||||
nrf_twi_disable(p_twi);
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
static bool twi_send_byte(NRF_TWI_Type * p_twi,
|
||||
twi_control_block_t * p_cb)
|
||||
{
|
||||
if (p_cb->bytes_transferred < p_cb->curr_length)
|
||||
{
|
||||
nrf_twi_txd_set(p_twi, p_cb->p_curr_buf[p_cb->bytes_transferred]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p_cb->curr_tx_no_stop)
|
||||
{
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_SUSPEND);
|
||||
return false;
|
||||
}
|
||||
else if(TWI_FLAG_SUSPEND(p_cb->flags))
|
||||
{
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_SUSPEND);
|
||||
p_cb->prev_suspend = TWI_SUSPEND_TX;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool twi_receive_byte(NRF_TWI_Type * p_twi,
|
||||
twi_control_block_t * p_cb)
|
||||
{
|
||||
if (p_cb->bytes_transferred < p_cb->curr_length)
|
||||
{
|
||||
p_cb->p_curr_buf[p_cb->bytes_transferred] = nrf_twi_rxd_get(p_twi);
|
||||
|
||||
++(p_cb->bytes_transferred);
|
||||
|
||||
if ((p_cb->bytes_transferred == p_cb->curr_length - 1) && (!TWI_FLAG_SUSPEND(p_cb->flags)))
|
||||
{
|
||||
nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
||||
}
|
||||
else if (p_cb->bytes_transferred == p_cb->curr_length && (!TWI_FLAG_SUSPEND(p_cb->flags)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (p_cb->bytes_transferred == p_cb->curr_length && TWI_FLAG_SUSPEND(p_cb->flags))
|
||||
{
|
||||
p_cb->prev_suspend = TWI_SUSPEND_RX;
|
||||
return false;
|
||||
}
|
||||
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool twi_transfer(NRF_TWI_Type * p_twi,
|
||||
twi_control_block_t * p_cb)
|
||||
{
|
||||
bool stopped = false;
|
||||
if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_STOPPED))
|
||||
{
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
|
||||
NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_STOPPED));
|
||||
|
||||
// Delay handling of STOPPED event till the end of events processing procedure.
|
||||
// If penultimate byte is received and function gets interrupted for long enough
|
||||
// after enabling BB_STOP shortcut, RXDREADY for last byte as well as STOPPED
|
||||
// may be active at the same time. Therefore RXREADY has to be processed before STOPPED to
|
||||
// acquire last byte before finishing transmission by returning 'false'.
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
if (p_cb->error)
|
||||
{
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
|
||||
}
|
||||
else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
|
||||
{
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
|
||||
NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
|
||||
p_cb->error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_TXDSENT))
|
||||
{
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
|
||||
++(p_cb->bytes_transferred);
|
||||
NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_TXDSENT));
|
||||
if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
|
||||
{
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
|
||||
NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
|
||||
p_cb->error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!twi_send_byte(p_twi, p_cb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_RXDREADY))
|
||||
{
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
|
||||
NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_RXDREADY));
|
||||
if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
|
||||
{
|
||||
NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
|
||||
p_cb->error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!twi_receive_byte(p_twi, p_cb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stopped)
|
||||
{
|
||||
p_cb->prev_suspend = TWI_NO_SUSPEND;
|
||||
if (!p_cb->error)
|
||||
{
|
||||
p_cb->error = !xfer_completeness_check(p_twi, p_cb);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static nrfx_err_t twi_tx_start_transfer(NRF_TWI_Type * p_twi,
|
||||
twi_control_block_t * p_cb)
|
||||
{
|
||||
nrfx_err_t ret_code = NRFX_SUCCESS;
|
||||
volatile int32_t hw_timeout;
|
||||
|
||||
hw_timeout = HW_TIMEOUT;
|
||||
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
|
||||
nrf_twi_shorts_set(p_twi, 0);
|
||||
|
||||
p_cb->bytes_transferred = 0;
|
||||
p_cb->error = false;
|
||||
|
||||
// In case TWI is suspended resume its operation.
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
|
||||
|
||||
if (p_cb->prev_suspend != TWI_SUSPEND_TX)
|
||||
{
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTTX);
|
||||
}
|
||||
|
||||
(void)twi_send_byte(p_twi, p_cb);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK |
|
||||
NRF_TWI_INT_ERROR_MASK |
|
||||
NRF_TWI_INT_TXDSENT_MASK |
|
||||
NRF_TWI_INT_RXDREADY_MASK;
|
||||
|
||||
nrf_twi_int_enable(p_twi, p_cb->int_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((hw_timeout > 0) &&
|
||||
twi_transfer(p_twi, p_cb))
|
||||
{
|
||||
hw_timeout--;
|
||||
}
|
||||
|
||||
if (p_cb->error)
|
||||
{
|
||||
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
|
||||
|
||||
if (errorsrc)
|
||||
{
|
||||
ret_code = twi_process_error(errorsrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_code = NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (hw_timeout <= 0)
|
||||
{
|
||||
nrf_twi_disable(p_twi);
|
||||
nrf_twi_enable(p_twi);
|
||||
ret_code = NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
}
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
static nrfx_err_t twi_rx_start_transfer(NRF_TWI_Type * p_twi,
|
||||
twi_control_block_t * p_cb)
|
||||
{
|
||||
nrfx_err_t ret_code = NRFX_SUCCESS;
|
||||
volatile int32_t hw_timeout;
|
||||
|
||||
hw_timeout = HW_TIMEOUT;
|
||||
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
|
||||
nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
|
||||
|
||||
p_cb->bytes_transferred = 0;
|
||||
p_cb->error = false;
|
||||
|
||||
if ((p_cb->curr_length == 1) && (!TWI_FLAG_SUSPEND(p_cb->flags)))
|
||||
{
|
||||
nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
|
||||
}
|
||||
// In case TWI is suspended resume its operation.
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
|
||||
|
||||
if (p_cb->prev_suspend != TWI_SUSPEND_RX)
|
||||
{
|
||||
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTRX);
|
||||
}
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK |
|
||||
NRF_TWI_INT_ERROR_MASK |
|
||||
NRF_TWI_INT_TXDSENT_MASK |
|
||||
NRF_TWI_INT_RXDREADY_MASK;
|
||||
nrf_twi_int_enable(p_twi, p_cb->int_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((hw_timeout > 0) &&
|
||||
twi_transfer(p_twi, p_cb))
|
||||
{
|
||||
hw_timeout--;
|
||||
}
|
||||
|
||||
if (p_cb->error)
|
||||
{
|
||||
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
|
||||
|
||||
if (errorsrc)
|
||||
{
|
||||
ret_code = twi_process_error(errorsrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_code = NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
if (hw_timeout <= 0)
|
||||
{
|
||||
nrf_twi_disable(p_twi);
|
||||
nrf_twi_enable(p_twi);
|
||||
ret_code = NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
__STATIC_INLINE nrfx_err_t twi_xfer(NRF_TWI_Type * p_twi,
|
||||
twi_control_block_t * p_cb,
|
||||
nrfx_twi_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags)
|
||||
{
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if ((p_cb->prev_suspend == TWI_SUSPEND_TX) && (p_xfer_desc->type == NRFX_TWI_XFER_RX))
|
||||
{
|
||||
/* RX is invalid after TX suspend */
|
||||
return NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
else if ((p_cb->prev_suspend == TWI_SUSPEND_RX) && (p_xfer_desc->type != NRFX_TWI_XFER_RX))
|
||||
{
|
||||
/* TX, TXRX and TXTX are invalid after RX suspend */
|
||||
return NRFX_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
|
||||
nrf_twi_int_disable(p_twi, NRF_TWI_ALL_INTS_MASK);
|
||||
|
||||
if (p_cb->busy)
|
||||
{
|
||||
nrf_twi_int_enable(p_twi, p_cb->int_mask);
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_cb->busy = (TWI_FLAG_NO_HANDLER_IN_USE(flags)) ? false : true;
|
||||
}
|
||||
|
||||
p_cb->flags = flags;
|
||||
p_cb->xfer_desc = *p_xfer_desc;
|
||||
p_cb->curr_length = p_xfer_desc->primary_length;
|
||||
p_cb->p_curr_buf = p_xfer_desc->p_primary_buf;
|
||||
nrf_twi_address_set(p_twi, p_xfer_desc->address);
|
||||
|
||||
if (p_xfer_desc->type != NRFX_TWI_XFER_RX)
|
||||
{
|
||||
p_cb->curr_tx_no_stop = ((p_xfer_desc->type == NRFX_TWI_XFER_TX) &&
|
||||
!(flags & NRFX_TWI_FLAG_TX_NO_STOP)) ? false : true;
|
||||
|
||||
err_code = twi_tx_start_transfer(p_twi, p_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
err_code = twi_rx_start_transfer(p_twi, p_cb);
|
||||
}
|
||||
if (p_cb->handler == NULL)
|
||||
{
|
||||
p_cb->busy = false;
|
||||
}
|
||||
return err_code;
|
||||
}
|
||||
|
||||
bool nrfx_twi_is_busy(nrfx_twi_t const * p_instance)
|
||||
{
|
||||
twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return p_cb->busy;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_twi_xfer(nrfx_twi_t const * p_instance,
|
||||
nrfx_twi_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags)
|
||||
{
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
// TXRX and TXTX transfers are supported only in non-blocking mode.
|
||||
NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWI_XFER_TXRX)));
|
||||
NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWI_XFER_TXTX)));
|
||||
|
||||
NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
|
||||
NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
|
||||
p_xfer_desc->primary_length,
|
||||
p_xfer_desc->secondary_length);
|
||||
NRFX_LOG_DEBUG("Primary buffer data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
|
||||
p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
|
||||
NRFX_LOG_DEBUG("Secondary buffer data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
|
||||
p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
|
||||
|
||||
err_code = twi_xfer((NRF_TWI_Type *)p_instance->p_twi, p_cb, p_xfer_desc, flags);
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_twi_tx(nrfx_twi_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t const * p_data,
|
||||
size_t length,
|
||||
bool no_stop)
|
||||
{
|
||||
nrfx_twi_xfer_desc_t xfer = NRFX_TWI_XFER_DESC_TX(address, (uint8_t*)p_data, length);
|
||||
return nrfx_twi_xfer(p_instance, &xfer, no_stop ? NRFX_TWI_FLAG_TX_NO_STOP : 0);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_twi_rx(nrfx_twi_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t * p_data,
|
||||
size_t length)
|
||||
{
|
||||
nrfx_twi_xfer_desc_t xfer = NRFX_TWI_XFER_DESC_RX(address, p_data, length);
|
||||
return nrfx_twi_xfer(p_instance, &xfer, 0);
|
||||
}
|
||||
|
||||
size_t nrfx_twi_data_count_get(nrfx_twi_t const * const p_instance)
|
||||
{
|
||||
return m_cb[p_instance->drv_inst_idx].bytes_transferred;
|
||||
}
|
||||
|
||||
uint32_t nrfx_twi_stopped_event_get(nrfx_twi_t const * p_instance)
|
||||
{
|
||||
return (uint32_t)nrf_twi_event_address_get(p_instance->p_twi, NRF_TWI_EVENT_STOPPED);
|
||||
}
|
||||
|
||||
static void twi_irq_handler(NRF_TWI_Type * p_twi, twi_control_block_t * p_cb)
|
||||
{
|
||||
NRFX_ASSERT(p_cb->handler);
|
||||
|
||||
if (twi_transfer(p_twi, p_cb))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!p_cb->error &&
|
||||
((p_cb->xfer_desc.type == NRFX_TWI_XFER_TXRX) ||
|
||||
(p_cb->xfer_desc.type == NRFX_TWI_XFER_TXTX)) &&
|
||||
p_cb->p_curr_buf == p_cb->xfer_desc.p_primary_buf)
|
||||
{
|
||||
p_cb->p_curr_buf = p_cb->xfer_desc.p_secondary_buf;
|
||||
p_cb->curr_length = p_cb->xfer_desc.secondary_length;
|
||||
p_cb->curr_tx_no_stop = (p_cb->flags & NRFX_TWI_FLAG_TX_NO_STOP);
|
||||
p_cb->prev_suspend = TWI_NO_SUSPEND;
|
||||
|
||||
if (p_cb->xfer_desc.type == NRFX_TWI_XFER_TXTX)
|
||||
{
|
||||
(void)twi_tx_start_transfer(p_twi, p_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)twi_rx_start_transfer(p_twi, p_cb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nrfx_twi_evt_t event;
|
||||
event.xfer_desc = p_cb->xfer_desc;
|
||||
|
||||
if (p_cb->error)
|
||||
{
|
||||
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
|
||||
if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
|
||||
{
|
||||
event.type = NRFX_TWI_EVT_ADDRESS_NACK;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_ADDRESS_NACK));
|
||||
}
|
||||
else if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
|
||||
{
|
||||
event.type = NRFX_TWI_EVT_DATA_NACK;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_DATA_NACK));
|
||||
}
|
||||
else if (errorsrc & NRF_TWI_ERROR_OVERRUN)
|
||||
{
|
||||
event.type = NRFX_TWI_EVT_OVERRUN;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_OVERRUN));
|
||||
}
|
||||
else
|
||||
{
|
||||
event.type = NRFX_TWI_EVT_BUS_ERROR;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_BUS_ERROR));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
event.type = NRFX_TWI_EVT_DONE;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_DONE));
|
||||
}
|
||||
|
||||
p_cb->busy = false;
|
||||
|
||||
if (!(TWI_FLAG_NO_HANDLER_IN_USE(p_cb->flags)) || p_cb->error)
|
||||
{
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWI0_ENABLED)
|
||||
void nrfx_twi_0_irq_handler(void)
|
||||
{
|
||||
twi_irq_handler(NRF_TWI0, &m_cb[NRFX_TWI0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWI1_ENABLED)
|
||||
void nrfx_twi_1_irq_handler(void)
|
||||
{
|
||||
twi_irq_handler(NRF_TWI1, &m_cb[NRFX_TWI1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_TWI_ENABLED)
|
||||
90
modules/nrfx/drivers/src/nrfx_twi_twim.c
Normal file
90
modules/nrfx/drivers/src/nrfx_twi_twim.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 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 <nrfx.h>
|
||||
#include <nrf_gpio.h>
|
||||
|
||||
#define TWI_TWIM_PIN_CONFIGURE(_pin) nrf_gpio_cfg((_pin), \
|
||||
NRF_GPIO_PIN_DIR_OUTPUT, \
|
||||
NRF_GPIO_PIN_INPUT_CONNECT, \
|
||||
NRF_GPIO_PIN_PULLUP, \
|
||||
NRF_GPIO_PIN_S0D1, \
|
||||
NRF_GPIO_PIN_NOSENSE)
|
||||
|
||||
nrfx_err_t nrfx_twi_twim_bus_recover(uint32_t scl_pin, uint32_t sda_pin)
|
||||
{
|
||||
nrf_gpio_pin_set(scl_pin);
|
||||
nrf_gpio_pin_set(sda_pin);
|
||||
|
||||
TWI_TWIM_PIN_CONFIGURE(scl_pin);
|
||||
TWI_TWIM_PIN_CONFIGURE(sda_pin);
|
||||
NRFX_DELAY_US(4);
|
||||
|
||||
for (uint8_t i = 0; i < 9; i++)
|
||||
{
|
||||
if (nrf_gpio_pin_read(sda_pin))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pulse CLOCK signal
|
||||
nrf_gpio_pin_clear(scl_pin);
|
||||
NRFX_DELAY_US(4);
|
||||
nrf_gpio_pin_set(scl_pin);
|
||||
NRFX_DELAY_US(4);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a STOP condition on the bus
|
||||
nrf_gpio_pin_clear(sda_pin);
|
||||
NRFX_DELAY_US(4);
|
||||
nrf_gpio_pin_set(sda_pin);
|
||||
NRFX_DELAY_US(4);
|
||||
|
||||
if (nrf_gpio_pin_read(sda_pin))
|
||||
{
|
||||
return NRFX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
872
modules/nrfx/drivers/src/nrfx_twim.c
Normal file
872
modules/nrfx/drivers/src/nrfx_twim.c
Normal file
@@ -0,0 +1,872 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_TWIM0_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TWIM1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TWIM2_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TWIM3_ENABLED))
|
||||
#error "No enabled TWIM instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_twim.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
|
||||
#define NRFX_LOG_MODULE TWIM
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRFX_TWIM_EVT_DONE ? "EVT_DONE" : \
|
||||
(event == NRFX_TWIM_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \
|
||||
(event == NRFX_TWIM_EVT_DATA_NACK ? "EVT_DATA_NACK" : \
|
||||
(event == NRFX_TWIM_EVT_OVERRUN ? "EVT_OVERRUN" : \
|
||||
(event == NRFX_TWIM_EVT_BUS_ERROR ? "EVT_BUS_ERROR" : \
|
||||
"UNKNOWN ERROR")))))
|
||||
|
||||
#define EVT_TO_STR_TWIM(event) \
|
||||
(event == NRF_TWIM_EVENT_STOPPED ? "NRF_TWIM_EVENT_STOPPED" : \
|
||||
(event == NRF_TWIM_EVENT_ERROR ? "NRF_TWIM_EVENT_ERROR" : \
|
||||
(event == NRF_TWIM_EVENT_SUSPENDED ? "NRF_TWIM_EVENT_SUSPENDED" : \
|
||||
(event == NRF_TWIM_EVENT_RXSTARTED ? "NRF_TWIM_EVENT_RXSTARTED" : \
|
||||
(event == NRF_TWIM_EVENT_TXSTARTED ? "NRF_TWIM_EVENT_TXSTARTED" : \
|
||||
(event == NRF_TWIM_EVENT_LASTRX ? "NRF_TWIM_EVENT_LASTRX" : \
|
||||
(event == NRF_TWIM_EVENT_LASTTX ? "NRF_TWIM_EVENT_LASTTX" : \
|
||||
"UNKNOWN ERROR")))))))
|
||||
|
||||
#define TRANSFER_TO_STR(type) \
|
||||
(type == NRFX_TWIM_XFER_TX ? "XFER_TX" : \
|
||||
(type == NRFX_TWIM_XFER_RX ? "XFER_RX" : \
|
||||
(type == NRFX_TWIM_XFER_TXRX ? "XFER_TXRX" : \
|
||||
(type == NRFX_TWIM_XFER_TXTX ? "XFER_TXTX" : \
|
||||
"UNKNOWN TRANSFER TYPE"))))
|
||||
|
||||
#define TWIM_PIN_INIT(_pin) nrf_gpio_cfg((_pin), \
|
||||
NRF_GPIO_PIN_DIR_INPUT, \
|
||||
NRF_GPIO_PIN_INPUT_CONNECT, \
|
||||
NRF_GPIO_PIN_PULLUP, \
|
||||
NRF_GPIO_PIN_S0D1, \
|
||||
NRF_GPIO_PIN_NOSENSE)
|
||||
|
||||
#define TWIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, len1, len2) \
|
||||
(((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
|
||||
NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, len1, len2))
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
|
||||
#define TWIM0_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM0, __VA_ARGS__)
|
||||
#else
|
||||
#define TWIM0_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
|
||||
#define TWIM1_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM1, __VA_ARGS__)
|
||||
#else
|
||||
#define TWIM1_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM2_ENABLED)
|
||||
#define TWIM2_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM2, __VA_ARGS__)
|
||||
#else
|
||||
#define TWIM2_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM3_ENABLED)
|
||||
#define TWIM3_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM3, __VA_ARGS__)
|
||||
#else
|
||||
#define TWIM3_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#define TWIM_LENGTH_VALIDATE(drv_inst_idx, len1, len2) \
|
||||
(TWIM0_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
|
||||
TWIM1_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
|
||||
TWIM2_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
|
||||
TWIM3_LENGTH_VALIDATE(drv_inst_idx, len1, len2))
|
||||
|
||||
// Control block - driver instance local data.
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twim_evt_handler_t handler;
|
||||
void * p_context;
|
||||
volatile uint32_t int_mask;
|
||||
nrfx_twim_xfer_desc_t xfer_desc;
|
||||
uint32_t flags;
|
||||
uint8_t * p_curr_buf;
|
||||
size_t curr_length;
|
||||
bool curr_no_stop;
|
||||
nrfx_drv_state_t state;
|
||||
bool error;
|
||||
volatile bool busy;
|
||||
bool repeated;
|
||||
uint8_t bytes_transferred;
|
||||
bool hold_bus_uninit;
|
||||
#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
nrf_twim_frequency_t bus_frequency;
|
||||
#endif
|
||||
} twim_control_block_t;
|
||||
|
||||
static twim_control_block_t m_cb[NRFX_TWIM_ENABLED_COUNT];
|
||||
|
||||
static nrfx_err_t twi_process_error(uint32_t errorsrc)
|
||||
{
|
||||
nrfx_err_t ret = NRFX_ERROR_INTERNAL;
|
||||
|
||||
if (errorsrc & NRF_TWIM_ERROR_OVERRUN)
|
||||
{
|
||||
ret = NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
|
||||
}
|
||||
|
||||
if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
|
||||
{
|
||||
ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
|
||||
}
|
||||
|
||||
if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
|
||||
{
|
||||
ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool xfer_completeness_check(NRF_TWIM_Type * p_twim, twim_control_block_t const * p_cb)
|
||||
{
|
||||
// If the actual number of transferred bytes is not equal to what was requested,
|
||||
// but there was no error signaled by the peripheral, this means that something
|
||||
// unexpected, like a premature STOP condition, was received on the bus.
|
||||
// In such case the peripheral has to be disabled and re-enabled, so that its
|
||||
// internal state machine is reinitialized.
|
||||
|
||||
bool transfer_complete = true;
|
||||
switch (p_cb->xfer_desc.type)
|
||||
{
|
||||
case NRFX_TWIM_XFER_TXTX:
|
||||
// int_mask variable is used to determine which length should be checked
|
||||
// against number of bytes latched in EasyDMA.
|
||||
// NRF_TWIM_INT_SUSPENDED_MASK is configured only in first TX of TXTX transfer.
|
||||
if (((p_cb->int_mask & NRF_TWIM_INT_SUSPENDED_MASK) &&
|
||||
(nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)) ||
|
||||
(!(p_cb->int_mask & NRF_TWIM_INT_SUSPENDED_MASK) &&
|
||||
(nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.secondary_length)))
|
||||
{
|
||||
transfer_complete = false;
|
||||
}
|
||||
break;
|
||||
case NRFX_TWIM_XFER_TXRX:
|
||||
if ((nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length) ||
|
||||
(nrf_twim_rxd_amount_get(p_twim) != p_cb->xfer_desc.secondary_length))
|
||||
{
|
||||
transfer_complete = false;
|
||||
}
|
||||
break;
|
||||
case NRFX_TWIM_XFER_TX:
|
||||
if (nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)
|
||||
{
|
||||
transfer_complete = false;
|
||||
}
|
||||
break;
|
||||
case NRFX_TWIM_XFER_RX:
|
||||
if (nrf_twim_rxd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)
|
||||
{
|
||||
transfer_complete = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!transfer_complete)
|
||||
{
|
||||
nrf_twim_disable(p_twim);
|
||||
nrf_twim_enable(p_twim);
|
||||
}
|
||||
|
||||
return transfer_complete;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance,
|
||||
nrfx_twim_config_t const * p_config,
|
||||
nrfx_twim_evt_handler_t event_handler,
|
||||
void * p_context)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(p_config->scl != p_config->sda);
|
||||
twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_TWIM_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
|
||||
nrfx_twim_0_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
|
||||
nrfx_twim_1_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIM2_ENABLED)
|
||||
nrfx_twim_2_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIM3_ENABLED)
|
||||
nrfx_twim_3_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_instance->p_twim,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
p_cb->handler = event_handler;
|
||||
p_cb->p_context = p_context;
|
||||
p_cb->int_mask = 0;
|
||||
p_cb->repeated = false;
|
||||
p_cb->busy = false;
|
||||
p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
|
||||
#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
p_cb->bus_frequency = (nrf_twim_frequency_t)p_config->frequency;
|
||||
#endif
|
||||
|
||||
/* To secure correct signal levels on the pins used by the TWI
|
||||
master when the system is in OFF mode, and when the TWI master is
|
||||
disabled, these pins must be configured in the GPIO peripheral.
|
||||
*/
|
||||
TWIM_PIN_INIT(p_config->scl);
|
||||
TWIM_PIN_INIT(p_config->sda);
|
||||
|
||||
NRF_TWIM_Type * p_twim = p_instance->p_twim;
|
||||
nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda);
|
||||
nrf_twim_frequency_set(p_twim,
|
||||
(nrf_twim_frequency_t)p_config->frequency);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twim),
|
||||
p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twim));
|
||||
}
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_twim_uninit(nrfx_twim_t const * p_instance)
|
||||
{
|
||||
twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twim));
|
||||
}
|
||||
nrfx_twim_disable(p_instance);
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_instance->p_twim);
|
||||
#endif
|
||||
|
||||
if (!p_cb->hold_bus_uninit)
|
||||
{
|
||||
nrf_gpio_cfg_default(p_instance->p_twim->PSEL.SCL);
|
||||
nrf_gpio_cfg_default(p_instance->p_twim->PSEL.SDA);
|
||||
}
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
void nrfx_twim_enable(nrfx_twim_t const * p_instance)
|
||||
{
|
||||
twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
|
||||
|
||||
nrf_twim_enable(p_instance->p_twim);
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
void nrfx_twim_disable(nrfx_twim_t const * p_instance)
|
||||
{
|
||||
twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
NRF_TWIM_Type * p_twim = p_instance->p_twim;
|
||||
p_cb->int_mask = 0;
|
||||
nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
|
||||
nrf_twim_shorts_disable(p_twim, NRF_TWIM_ALL_SHORTS_MASK);
|
||||
nrf_twim_disable(p_twim);
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
|
||||
bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance)
|
||||
{
|
||||
twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return p_cb->busy;
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE void twim_list_enable_handle(NRF_TWIM_Type * p_twim, uint32_t flags)
|
||||
{
|
||||
if (NRFX_TWIM_FLAG_TX_POSTINC & flags)
|
||||
{
|
||||
nrf_twim_tx_list_enable(p_twim);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twim_tx_list_disable(p_twim);
|
||||
}
|
||||
|
||||
if (NRFX_TWIM_FLAG_RX_POSTINC & flags)
|
||||
{
|
||||
nrf_twim_rx_list_enable(p_twim);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twim_rx_list_disable(p_twim);
|
||||
}
|
||||
}
|
||||
__STATIC_INLINE nrfx_err_t twim_xfer(twim_control_block_t * p_cb,
|
||||
NRF_TWIM_Type * p_twim,
|
||||
nrfx_twim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags)
|
||||
{
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
nrf_twim_task_t start_task = NRF_TWIM_TASK_STARTTX;
|
||||
p_cb->error = false;
|
||||
|
||||
if (!nrfx_is_in_ram(p_xfer_desc->p_primary_buf))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
/* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
|
||||
nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
|
||||
if (p_cb->busy)
|
||||
{
|
||||
nrf_twim_int_enable(p_twim, p_cb->int_mask);
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_cb->busy = ((NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER & flags) ||
|
||||
(NRFX_TWIM_FLAG_REPEATED_XFER & flags)) ? false: true;
|
||||
}
|
||||
|
||||
p_cb->xfer_desc = *p_xfer_desc;
|
||||
p_cb->repeated = (flags & NRFX_TWIM_FLAG_REPEATED_XFER) ? true : false;
|
||||
p_cb->flags = flags;
|
||||
nrf_twim_address_set(p_twim, p_xfer_desc->address);
|
||||
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
|
||||
|
||||
twim_list_enable_handle(p_twim, flags);
|
||||
switch (p_xfer_desc->type)
|
||||
{
|
||||
case NRFX_TWIM_XFER_TXTX:
|
||||
NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_REPEATED_XFER));
|
||||
NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_HOLD_XFER));
|
||||
NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER));
|
||||
if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
|
||||
nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
|
||||
while (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
|
||||
{}
|
||||
NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_TXSTARTED));
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
|
||||
nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
|
||||
p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK;
|
||||
break;
|
||||
case NRFX_TWIM_XFER_TXRX:
|
||||
nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
|
||||
if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
|
||||
nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK |
|
||||
NRF_TWIM_SHORT_LASTRX_STOP_MASK);
|
||||
p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
|
||||
break;
|
||||
case NRFX_TWIM_XFER_TX:
|
||||
nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
|
||||
if (NRFX_TWIM_FLAG_TX_NO_STOP & flags)
|
||||
{
|
||||
nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
|
||||
p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
|
||||
p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
|
||||
}
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
|
||||
break;
|
||||
case NRFX_TWIM_XFER_RX:
|
||||
nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
|
||||
nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK);
|
||||
p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
|
||||
start_task = NRF_TWIM_TASK_STARTRX;
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
|
||||
break;
|
||||
default:
|
||||
err_code = NRFX_ERROR_INVALID_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_TXTX))
|
||||
{
|
||||
nrf_twim_task_trigger(p_twim, start_task);
|
||||
}
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
if (flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER)
|
||||
{
|
||||
p_cb->int_mask = 0;
|
||||
}
|
||||
|
||||
if (!(flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK))
|
||||
{
|
||||
p_cb->int_mask |= NRF_TWIM_INT_STOPPED_MASK;
|
||||
}
|
||||
|
||||
// Interrupts for ERROR are implicitly enabled, regardless of driver configuration.
|
||||
p_cb->int_mask |= NRF_TWIM_INT_ERROR_MASK;
|
||||
nrf_twim_int_enable(p_twim, p_cb->int_mask);
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
if ((flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_RX))
|
||||
{
|
||||
twim_list_enable_handle(p_twim, 0);
|
||||
p_twim->FREQUENCY = 0;
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
|
||||
nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
bool transmission_finished = false;
|
||||
do {
|
||||
if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_SUSPENDED))
|
||||
{
|
||||
NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
|
||||
transmission_finished = true;
|
||||
}
|
||||
|
||||
if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
|
||||
{
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
|
||||
NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
|
||||
transmission_finished = true;
|
||||
}
|
||||
|
||||
if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
|
||||
{
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
|
||||
NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
|
||||
|
||||
bool lasttx_triggered = nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX);
|
||||
uint32_t shorts_mask = nrf_twim_shorts_get(p_twim);
|
||||
|
||||
if (!(lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
|
||||
{
|
||||
// Unless LASTTX event arrived and LASTTX_STOP shortcut is active,
|
||||
// triggering of STOP task in case of error has to be done manually.
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
|
||||
|
||||
// Mark transmission as not finished yet,
|
||||
// as STOPPED event is expected to arrive.
|
||||
// If LASTTX_SUSPENDED shortcut is active,
|
||||
// NACK has been received on last byte sent
|
||||
// and SUSPENDED event happened to be checked before ERROR,
|
||||
// transmission will be marked as finished.
|
||||
// In such case this flag has to be overwritten.
|
||||
transmission_finished = false;
|
||||
}
|
||||
|
||||
if (lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK))
|
||||
{
|
||||
// When STOP task was triggered just before SUSPEND task has taken effect,
|
||||
// SUSPENDED event may not arrive.
|
||||
// However if SUSPENDED arrives it always arrives after ERROR.
|
||||
// Therefore SUSPENDED has to be cleared
|
||||
// so it does not cause premature termination of busy loop
|
||||
// waiting for STOPPED event to arrive.
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
|
||||
|
||||
// Mark transmission as not finished yet,
|
||||
// for same reasons as above.
|
||||
transmission_finished = false;
|
||||
}
|
||||
}
|
||||
} while (!transmission_finished);
|
||||
|
||||
uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
|
||||
|
||||
p_cb->busy = false;
|
||||
|
||||
if (errorsrc)
|
||||
{
|
||||
err_code = twi_process_error(errorsrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK) &&
|
||||
!xfer_completeness_check(p_twim, p_cb))
|
||||
{
|
||||
err_code = NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance,
|
||||
nrfx_twim_xfer_desc_t const * p_xfer_desc,
|
||||
uint32_t flags)
|
||||
{
|
||||
NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
|
||||
p_xfer_desc->primary_length,
|
||||
p_xfer_desc->secondary_length));
|
||||
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
// TXRX and TXTX transfers are supported only in non-blocking mode.
|
||||
NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)));
|
||||
NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXTX)));
|
||||
|
||||
NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
|
||||
NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
|
||||
p_xfer_desc->primary_length,
|
||||
p_xfer_desc->secondary_length);
|
||||
NRFX_LOG_DEBUG("Primary buffer data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
|
||||
p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
|
||||
NRFX_LOG_DEBUG("Secondary buffer data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
|
||||
p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
|
||||
|
||||
err_code = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->p_twim, p_xfer_desc, flags);
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_twim_tx(nrfx_twim_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t const * p_data,
|
||||
size_t length,
|
||||
bool no_stop)
|
||||
{
|
||||
nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_TX(address, (uint8_t*)p_data, length);
|
||||
|
||||
return nrfx_twim_xfer(p_instance, &xfer, no_stop ? NRFX_TWIM_FLAG_TX_NO_STOP : 0);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_twim_rx(nrfx_twim_t const * p_instance,
|
||||
uint8_t address,
|
||||
uint8_t * p_data,
|
||||
size_t length)
|
||||
{
|
||||
nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_RX(address, p_data, length);
|
||||
return nrfx_twim_xfer(p_instance, &xfer, 0);
|
||||
}
|
||||
|
||||
uint32_t nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,
|
||||
nrfx_twim_xfer_type_t xfer_type)
|
||||
{
|
||||
return (uint32_t)nrf_twim_task_address_get(p_instance->p_twim,
|
||||
(xfer_type != NRFX_TWIM_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX);
|
||||
}
|
||||
|
||||
uint32_t nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)
|
||||
{
|
||||
return (uint32_t)nrf_twim_event_address_get(p_instance->p_twim, NRF_TWIM_EVENT_STOPPED);
|
||||
}
|
||||
|
||||
static void twim_irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb)
|
||||
{
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
/* Handle only workaround case. Can be used without TWIM handler in IRQs. */
|
||||
if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
|
||||
{
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
|
||||
nrf_twim_int_disable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
|
||||
if (p_twim->FREQUENCY == 0)
|
||||
{
|
||||
// Set enable to zero to reset TWIM internal state.
|
||||
nrf_twim_disable(p_twim);
|
||||
nrf_twim_enable(p_twim);
|
||||
|
||||
// Set proper frequency.
|
||||
nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
|
||||
twim_list_enable_handle(p_twim, p_cb->flags);
|
||||
|
||||
// Start proper transmission.
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NRFX_ASSERT(p_cb->handler);
|
||||
|
||||
if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
|
||||
{
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
|
||||
NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
|
||||
if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
|
||||
{
|
||||
nrf_twim_int_disable(p_twim, p_cb->int_mask);
|
||||
p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
|
||||
nrf_twim_int_enable(p_twim, p_cb->int_mask);
|
||||
|
||||
if (!(nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX) &&
|
||||
(nrf_twim_shorts_get(p_twim) & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
|
||||
{
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
|
||||
}
|
||||
|
||||
p_cb->error = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_twim_evt_t event;
|
||||
|
||||
if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
|
||||
{
|
||||
NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
|
||||
|
||||
if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK) && !p_cb->error)
|
||||
{
|
||||
p_cb->error = !xfer_completeness_check(p_twim, p_cb);
|
||||
}
|
||||
|
||||
// Further processing of STOPPED event is valid only if NO_XFER_EVT_HANDLER
|
||||
// setting is not used.
|
||||
if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER))
|
||||
{
|
||||
event.xfer_desc = p_cb->xfer_desc;
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX);
|
||||
if (!p_cb->repeated || p_cb->error)
|
||||
{
|
||||
nrf_twim_shorts_set(p_twim, 0);
|
||||
p_cb->int_mask = 0;
|
||||
nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
|
||||
|
||||
// At this point interrupt handler should not be invoked again for current transfer.
|
||||
// If STOPPED arrived during ERROR processing,
|
||||
// its pending interrupt should be ignored.
|
||||
// Otherwise spurious NRFX_TWIM_EVT_DONE or NRFX_TWIM_EVT_BUS_ERROR
|
||||
// would be passed to user's handler.
|
||||
NRFX_IRQ_PENDING_CLEAR(nrfx_get_irq_number(p_twim));
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
|
||||
else if (p_cb->xfer_desc.type != NRFX_TWIM_XFER_RX)
|
||||
{
|
||||
/* Add Anomaly 109 workaround for each potential repeated transfer starting from TX. */
|
||||
twim_list_enable_handle(p_twim, 0);
|
||||
p_twim->FREQUENCY = 0;
|
||||
nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
|
||||
NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
|
||||
if (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TX)
|
||||
{
|
||||
event.xfer_desc = p_cb->xfer_desc;
|
||||
if (!p_cb->repeated)
|
||||
{
|
||||
nrf_twim_shorts_set(p_twim, 0);
|
||||
p_cb->int_mask = 0;
|
||||
nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
|
||||
|
||||
// At this point interrupt handler should not be invoked again for current transfer.
|
||||
// If STOPPED arrived during SUSPENDED processing,
|
||||
// its pending interrupt should be ignored.
|
||||
// Otherwise spurious NRFX_TWIM_EVT_DONE or NRFX_TWIM_EVT_BUS_ERROR
|
||||
// would be passed to user's handler.
|
||||
NRFX_IRQ_PENDING_CLEAR(nrfx_get_irq_number(p_twim));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
|
||||
p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
|
||||
nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
|
||||
nrf_twim_int_enable(p_twim, p_cb->int_mask);
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
|
||||
nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
|
||||
if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
|
||||
{
|
||||
event.type = NRFX_TWIM_EVT_ADDRESS_NACK;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_ADDRESS_NACK));
|
||||
}
|
||||
else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
|
||||
{
|
||||
event.type = NRFX_TWIM_EVT_DATA_NACK;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DATA_NACK));
|
||||
}
|
||||
else if (errorsrc & NRF_TWIM_ERROR_OVERRUN)
|
||||
{
|
||||
event.type = NRFX_TWIM_EVT_OVERRUN;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_OVERRUN));
|
||||
}
|
||||
else if (p_cb->error)
|
||||
{
|
||||
event.type = NRFX_TWIM_EVT_BUS_ERROR;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_BUS_ERROR));
|
||||
}
|
||||
else
|
||||
{
|
||||
event.type = NRFX_TWIM_EVT_DONE;
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DONE));
|
||||
}
|
||||
|
||||
if (!p_cb->repeated)
|
||||
{
|
||||
p_cb->busy = false;
|
||||
}
|
||||
|
||||
if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER) || p_cb->error)
|
||||
{
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
|
||||
void nrfx_twim_0_irq_handler(void)
|
||||
{
|
||||
twim_irq_handler(NRF_TWIM0, &m_cb[NRFX_TWIM0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
|
||||
void nrfx_twim_1_irq_handler(void)
|
||||
{
|
||||
twim_irq_handler(NRF_TWIM1, &m_cb[NRFX_TWIM1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM2_ENABLED)
|
||||
void nrfx_twim_2_irq_handler(void)
|
||||
{
|
||||
twim_irq_handler(NRF_TWIM2, &m_cb[NRFX_TWIM2_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIM3_ENABLED)
|
||||
void nrfx_twim_3_irq_handler(void)
|
||||
{
|
||||
twim_irq_handler(NRF_TWIM3, &m_cb[NRFX_TWIM3_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_TWIM_ENABLED)
|
||||
857
modules/nrfx/drivers/src/nrfx_twis.c
Normal file
857
modules/nrfx/drivers/src/nrfx_twis.c
Normal file
@@ -0,0 +1,857 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIS_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_TWIS0_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TWIS1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TWIS2_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_TWIS3_ENABLED))
|
||||
#error "No enabled TWIS instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_twis.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
|
||||
#define NRFX_LOG_MODULE TWIS
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_TWIS_EVENT_STOPPED ? "NRF_TWIS_EVENT_STOPPED" : \
|
||||
(event == NRF_TWIS_EVENT_ERROR ? "NRF_TWIS_EVENT_ERROR" : \
|
||||
(event == NRF_TWIS_EVENT_RXSTARTED ? "NRF_TWIS_EVENT_RXSTARTED" : \
|
||||
(event == NRF_TWIS_EVENT_TXSTARTED ? "NRF_TWIS_EVENT_TXSTARTED" : \
|
||||
(event == NRF_TWIS_EVENT_WRITE ? "NRF_TWIS_EVENT_WRITE" : \
|
||||
(event == NRF_TWIS_EVENT_READ ? "NRF_TWIS_EVENT_READ" : \
|
||||
"UNKNOWN EVENT"))))))
|
||||
|
||||
|
||||
/**
|
||||
* @brief Actual state of internal state machine
|
||||
*
|
||||
* Current substate of powered on state.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRFX_TWIS_SUBSTATE_IDLE, ///< No ongoing transmission
|
||||
NRFX_TWIS_SUBSTATE_READ_WAITING, ///< Read request received, waiting for data
|
||||
NRFX_TWIS_SUBSTATE_READ_PENDING, ///< Reading is actually pending (data sending)
|
||||
NRFX_TWIS_SUBSTATE_WRITE_WAITING, ///< Write request received, waiting for data buffer
|
||||
NRFX_TWIS_SUBSTATE_WRITE_PENDING, ///< Writing is actually pending (data receiving)
|
||||
} nrfx_twis_substate_t;
|
||||
|
||||
// Control block - driver instance local data.
|
||||
typedef struct
|
||||
{
|
||||
nrfx_twis_event_handler_t ev_handler;
|
||||
// Internal copy of hardware errors flags merged with specific internal
|
||||
// driver errors flags.
|
||||
// This value can be changed in the interrupt and cleared in the main program.
|
||||
// Always use Atomic load-store when updating this value in main loop.
|
||||
volatile uint32_t error;
|
||||
nrfx_drv_state_t state;
|
||||
volatile nrfx_twis_substate_t substate;
|
||||
|
||||
volatile bool semaphore;
|
||||
} twis_control_block_t;
|
||||
static twis_control_block_t m_cb[NRFX_TWIS_ENABLED_COUNT];
|
||||
|
||||
/**
|
||||
* @brief Used interrupts mask
|
||||
*
|
||||
* Mask for all interrupts used by this library
|
||||
*/
|
||||
static const uint32_t m_used_ints_mask = NRF_TWIS_INT_STOPPED_MASK |
|
||||
NRF_TWIS_INT_ERROR_MASK |
|
||||
NRF_TWIS_INT_RXSTARTED_MASK |
|
||||
NRF_TWIS_INT_TXSTARTED_MASK |
|
||||
NRF_TWIS_INT_WRITE_MASK |
|
||||
NRF_TWIS_INT_READ_MASK;
|
||||
|
||||
/**
|
||||
* @brief Clear all events
|
||||
*
|
||||
* Function clears all actually pending events
|
||||
*/
|
||||
static void nrfx_twis_clear_all_events(NRF_TWIS_Type * const p_reg)
|
||||
{
|
||||
/* Clear all events */
|
||||
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_STOPPED);
|
||||
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_ERROR);
|
||||
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_RXSTARTED);
|
||||
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_TXSTARTED);
|
||||
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_WRITE);
|
||||
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_READ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all the registers to known state
|
||||
*
|
||||
* This function clears all registers that requires it to known state.
|
||||
* TWIS is left disabled after this function.
|
||||
* All events are cleared.
|
||||
* @param[out] p_reg TWIS to reset register address
|
||||
*/
|
||||
static inline void nrfx_twis_swreset(NRF_TWIS_Type * p_reg)
|
||||
{
|
||||
/* Disable TWIS */
|
||||
nrf_twis_disable(p_reg);
|
||||
|
||||
/* Disconnect pins */
|
||||
nrf_twis_pins_set(p_reg, ~0U, ~0U);
|
||||
|
||||
/* Disable interrupt global for the instance */
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
|
||||
|
||||
/* Disable interrupts */
|
||||
nrf_twis_int_disable(p_reg, ~0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure pin
|
||||
*
|
||||
* Function configures selected for work as SDA or SCL.
|
||||
* @param pin Pin number to configure
|
||||
*/
|
||||
static inline void nrfx_twis_config_pin(uint32_t pin, nrf_gpio_pin_pull_t pull)
|
||||
{
|
||||
nrf_gpio_cfg(pin,
|
||||
NRF_GPIO_PIN_DIR_INPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
pull,
|
||||
NRF_GPIO_PIN_S0D1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Auxiliary function for getting event state on right bit possition
|
||||
*
|
||||
* This function calls @ref nrf_twis_event_get function but the the result
|
||||
* is shifted to match INTEN register scheme.
|
||||
*
|
||||
* @param[in,out] p_reg TWIS to read event from
|
||||
* @param ev Event code
|
||||
*
|
||||
* @return Selected event state shifted by @ref nrfx_event_to_bitpos
|
||||
*
|
||||
* @sa nrf_twis_event_get
|
||||
* @sa nrfx_event_to_bitpos
|
||||
*/
|
||||
static inline uint32_t nrfx_twis_event_bit_get(NRF_TWIS_Type * p_reg,
|
||||
nrf_twis_event_t ev)
|
||||
{
|
||||
return (uint32_t)nrf_twis_event_get_and_clear(p_reg, ev) << nrfx_event_to_bitpos(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Auxiliary function for checking event bit inside given flags value
|
||||
*
|
||||
* Function used here to check presence of the event inside given flags value.
|
||||
* It transforms given event to bit possition and then checks if in given variable it is cleared.
|
||||
*
|
||||
* @param flags Flags to test
|
||||
* @param ev Event code
|
||||
*
|
||||
* @retval true Flag for selected event is set
|
||||
* @retval false Flag for selected event is cleared
|
||||
*/
|
||||
static inline bool nrfx_twis_check_bit(uint32_t flags,
|
||||
nrf_twis_event_t ev)
|
||||
{
|
||||
return 0 != (flags & (1U << nrfx_event_to_bitpos(ev)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Auxiliary function for clearing event bit in given flags value
|
||||
*
|
||||
* Function used to clear selected event bit.
|
||||
*
|
||||
* @param flags Flags to process
|
||||
* @param ev Event code to clear
|
||||
*
|
||||
* @return Value @em flags with cleared event bit that matches given @em ev
|
||||
*/
|
||||
static inline uint32_t nrfx_twis_clear_bit(uint32_t flags,
|
||||
nrf_twis_event_t ev)
|
||||
{
|
||||
return flags & ~(1U << nrfx_event_to_bitpos(ev));
|
||||
}
|
||||
|
||||
static void call_event_handler(twis_control_block_t const * p_cb,
|
||||
nrfx_twis_evt_t const * p_evt)
|
||||
{
|
||||
nrfx_twis_event_handler_t handler = p_cb->ev_handler;
|
||||
if (handler != NULL)
|
||||
{
|
||||
handler(p_evt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Auxiliary function for error processing
|
||||
*
|
||||
* Function called when in current substate the event apears and it cannot be processed.
|
||||
* It should be called also on ERROR event.
|
||||
* If given @em error parameter has zero value the @ref NRFX_TWIS_ERROR_UNEXPECTED_EVENT
|
||||
* would be set.
|
||||
*
|
||||
* @param p_cb Pointer to the driver instance control block.
|
||||
* @param evt What error event raport to event handler
|
||||
* @param error Error flags
|
||||
*/
|
||||
static inline void nrfx_twis_process_error(twis_control_block_t * p_cb,
|
||||
nrfx_twis_evt_type_t evt,
|
||||
uint32_t error)
|
||||
{
|
||||
if (0 == error)
|
||||
{
|
||||
error = NRFX_TWIS_ERROR_UNEXPECTED_EVENT;
|
||||
}
|
||||
nrfx_twis_evt_t evdata;
|
||||
evdata.type = evt;
|
||||
evdata.data.error = error;
|
||||
|
||||
p_cb->error |= error;
|
||||
|
||||
call_event_handler(p_cb, &evdata);
|
||||
}
|
||||
|
||||
static void nrfx_twis_state_machine(NRF_TWIS_Type * p_reg,
|
||||
twis_control_block_t * p_cb)
|
||||
{
|
||||
if (!NRFX_TWIS_NO_SYNC_MODE)
|
||||
{
|
||||
/* Exclude parallel processing of this function */
|
||||
if (p_cb->semaphore)
|
||||
{
|
||||
return;
|
||||
}
|
||||
p_cb->semaphore = 1;
|
||||
}
|
||||
|
||||
/* Event data structure to be passed into event handler */
|
||||
nrfx_twis_evt_t evdata;
|
||||
/* Current substate copy */
|
||||
nrfx_twis_substate_t substate = p_cb->substate;
|
||||
/* Event flags */
|
||||
uint32_t ev = 0;
|
||||
|
||||
/* Get all events */
|
||||
ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_STOPPED);
|
||||
ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_ERROR);
|
||||
ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_RXSTARTED);
|
||||
ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_TXSTARTED);
|
||||
ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_WRITE);
|
||||
ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_READ);
|
||||
|
||||
/* State machine */
|
||||
while (0 != ev)
|
||||
{
|
||||
switch (substate)
|
||||
{
|
||||
case NRFX_TWIS_SUBSTATE_IDLE:
|
||||
if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
|
||||
{
|
||||
/* Stopped event is always allowed in IDLE state - just ignore */
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
|
||||
}
|
||||
else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ))
|
||||
{
|
||||
evdata.type = NRFX_TWIS_EVT_READ_REQ;
|
||||
if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED))
|
||||
{
|
||||
substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
|
||||
evdata.data.buf_req = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
substate = NRFX_TWIS_SUBSTATE_READ_WAITING;
|
||||
evdata.data.buf_req = true;
|
||||
}
|
||||
call_event_handler(p_cb, &evdata);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
|
||||
}
|
||||
else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE))
|
||||
{
|
||||
evdata.type = NRFX_TWIS_EVT_WRITE_REQ;
|
||||
if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED))
|
||||
{
|
||||
substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
|
||||
evdata.data.buf_req = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
substate = NRFX_TWIS_SUBSTATE_WRITE_WAITING;
|
||||
evdata.data.buf_req = true;
|
||||
}
|
||||
call_event_handler(p_cb, &evdata);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrfx_twis_process_error(p_cb,
|
||||
NRFX_TWIS_EVT_GENERAL_ERROR,
|
||||
nrf_twis_error_source_get_and_clear(p_reg));
|
||||
ev = 0;
|
||||
}
|
||||
break;
|
||||
case NRFX_TWIS_SUBSTATE_READ_WAITING:
|
||||
if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
|
||||
{
|
||||
substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
|
||||
/* Any other bits requires further processing in PENDING substate */
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrfx_twis_process_error(p_cb,
|
||||
NRFX_TWIS_EVT_READ_ERROR,
|
||||
nrf_twis_error_source_get_and_clear(p_reg));
|
||||
substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
ev = 0;
|
||||
}
|
||||
break;
|
||||
case NRFX_TWIS_SUBSTATE_READ_PENDING:
|
||||
if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
|
||||
{
|
||||
evdata.type = NRFX_TWIS_EVT_READ_DONE;
|
||||
evdata.data.tx_amount = nrf_twis_tx_amount_get(p_reg);
|
||||
NRFX_LOG_INFO("Transfer tx_len:%d", evdata.data.tx_amount);
|
||||
NRFX_LOG_DEBUG("Tx data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG((uint8_t const *)p_reg->TXD.PTR,
|
||||
evdata.data.tx_amount * sizeof(uint8_t));
|
||||
call_event_handler(p_cb, &evdata);
|
||||
/* Go to idle and repeat the state machine if READ or WRITE events detected.
|
||||
* This time READ or WRITE would be started */
|
||||
substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrfx_twis_process_error(p_cb,
|
||||
NRFX_TWIS_EVT_READ_ERROR,
|
||||
nrf_twis_error_source_get_and_clear(p_reg));
|
||||
substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
ev = 0;
|
||||
}
|
||||
break;
|
||||
case NRFX_TWIS_SUBSTATE_WRITE_WAITING:
|
||||
if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
|
||||
{
|
||||
substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
|
||||
/* Any other bits requires further processing in PENDING substate */
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrfx_twis_process_error(p_cb,
|
||||
NRFX_TWIS_EVT_WRITE_ERROR,
|
||||
nrf_twis_error_source_get_and_clear(p_reg));
|
||||
substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
ev = 0;
|
||||
}
|
||||
break;
|
||||
case NRFX_TWIS_SUBSTATE_WRITE_PENDING:
|
||||
if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
|
||||
nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
|
||||
{
|
||||
evdata.type = NRFX_TWIS_EVT_WRITE_DONE;
|
||||
evdata.data.rx_amount = nrf_twis_rx_amount_get(p_reg);
|
||||
call_event_handler(p_cb, &evdata);
|
||||
/* Go to idle and repeat the state machine if READ or WRITE events detected.
|
||||
* This time READ or WRITE would be started */
|
||||
substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrfx_twis_process_error(p_cb,
|
||||
NRFX_TWIS_EVT_WRITE_ERROR,
|
||||
nrf_twis_error_source_get_and_clear(p_reg));
|
||||
substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
ev = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
/* Do not clear any events and repeat the machine */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p_cb->substate = substate;
|
||||
if (!NRFX_TWIS_NO_SYNC_MODE)
|
||||
{
|
||||
p_cb->semaphore = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void nrfx_twis_preprocess_status(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
if (!NRFX_TWIS_NO_SYNC_MODE)
|
||||
{
|
||||
NRF_TWIS_Type * p_reg = p_instance->p_reg;
|
||||
twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
if (NULL == p_cb->ev_handler)
|
||||
{
|
||||
nrfx_twis_state_machine(p_reg, p_cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Implementation of interface functions
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
nrfx_err_t nrfx_twis_init(nrfx_twis_t const * p_instance,
|
||||
nrfx_twis_config_t const * p_config,
|
||||
nrfx_twis_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
NRFX_ASSERT(p_config->scl != p_config->sda);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
NRF_TWIS_Type * p_reg = p_instance->p_reg;
|
||||
twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_TWIS_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_TWIS0_ENABLED)
|
||||
nrfx_twis_0_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIS1_ENABLED)
|
||||
nrfx_twis_1_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIS2_ENABLED)
|
||||
nrfx_twis_2_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIS3_ENABLED)
|
||||
nrfx_twis_3_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_reg,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
if (!NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY)
|
||||
{
|
||||
nrfx_twis_swreset(p_reg);
|
||||
}
|
||||
|
||||
nrfx_twis_config_pin(p_config->scl, p_config->scl_pull);
|
||||
nrfx_twis_config_pin(p_config->sda, p_config->sda_pull);
|
||||
|
||||
nrf_twis_config_addr_mask_t addr_mask = (nrf_twis_config_addr_mask_t)0;
|
||||
if (0 == (p_config->addr[0] | p_config->addr[1]))
|
||||
{
|
||||
addr_mask = NRF_TWIS_CONFIG_ADDRESS0_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != p_config->addr[0])
|
||||
{
|
||||
addr_mask |= NRF_TWIS_CONFIG_ADDRESS0_MASK;
|
||||
}
|
||||
if (0 != p_config->addr[1])
|
||||
{
|
||||
addr_mask |= NRF_TWIS_CONFIG_ADDRESS1_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Peripheral interrupt configure
|
||||
* (note - interrupts still needs to be configured in INTEN register.
|
||||
* This is done in enable function) */
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_reg),
|
||||
p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_reg));
|
||||
|
||||
/* Configure */
|
||||
nrf_twis_pins_set (p_reg, p_config->scl, p_config->sda);
|
||||
nrf_twis_address_set (p_reg, 0, p_config->addr[0]);
|
||||
nrf_twis_address_set (p_reg, 1, p_config->addr[1]);
|
||||
nrf_twis_config_address_set(p_reg, addr_mask);
|
||||
|
||||
/* Clear semaphore */
|
||||
if (!NRFX_TWIS_NO_SYNC_MODE)
|
||||
{
|
||||
p_cb->semaphore = 0;
|
||||
}
|
||||
/* Set internal instance variables */
|
||||
p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
p_cb->ev_handler = event_handler;
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_twis_uninit(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
NRF_TWIS_Type * p_reg = p_instance->p_reg;
|
||||
twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
TWIS_PSEL_Type psel = p_reg->PSEL;
|
||||
|
||||
nrfx_twis_swreset(p_reg);
|
||||
|
||||
/* Clear pins state if */
|
||||
if (!(TWIS_PSEL_SCL_CONNECT_Msk & psel.SCL))
|
||||
{
|
||||
nrf_gpio_cfg_default(psel.SCL);
|
||||
}
|
||||
if (!(TWIS_PSEL_SDA_CONNECT_Msk & psel.SDA))
|
||||
{
|
||||
nrf_gpio_cfg_default(psel.SDA);
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_reg);
|
||||
#endif
|
||||
|
||||
/* Clear variables */
|
||||
p_cb->ev_handler = NULL;
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_twis_enable(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
NRF_TWIS_Type * p_reg = p_instance->p_reg;
|
||||
twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
|
||||
|
||||
nrfx_twis_clear_all_events(p_reg);
|
||||
|
||||
/* Enable interrupts */
|
||||
if (NULL != p_cb->ev_handler)
|
||||
{
|
||||
nrf_twis_int_enable(p_reg, m_used_ints_mask);
|
||||
}
|
||||
|
||||
nrf_twis_enable(p_reg);
|
||||
p_cb->error = 0;
|
||||
p_cb->state = NRFX_DRV_STATE_POWERED_ON;
|
||||
p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_twis_disable(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
NRF_TWIS_Type * p_reg = p_instance->p_reg;
|
||||
twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
|
||||
|
||||
nrf_twis_int_disable(p_reg, m_used_ints_mask);
|
||||
|
||||
nrf_twis_disable(p_reg);
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
}
|
||||
|
||||
/* ARM recommends not using the LDREX and STREX instructions in C code.
|
||||
* This is because the compiler might generate loads and stores between
|
||||
* LDREX and STREX, potentially clearing the exclusive monitor set by LDREX.
|
||||
* This recommendation also applies to the byte, halfword, and doubleword
|
||||
* variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD.
|
||||
*
|
||||
* This is the reason for the function below to be implemented in assembly.
|
||||
*/
|
||||
//lint -save -e578
|
||||
#if defined (__CC_ARM )
|
||||
static __ASM uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
|
||||
{
|
||||
mov r3, r0
|
||||
mov r1, #0
|
||||
nrfx_twis_error_get_and_clear_internal_try
|
||||
ldrex r0, [r3]
|
||||
strex r2, r1, [r3]
|
||||
cmp r2, r1 /* did this succeed? */
|
||||
bne nrfx_twis_error_get_and_clear_internal_try /* no - try again */
|
||||
bx lr
|
||||
}
|
||||
#elif defined ( __GNUC__ )
|
||||
static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint32_t temp;
|
||||
__ASM volatile(
|
||||
" .syntax unified \n"
|
||||
"nrfx_twis_error_get_and_clear_internal_try: \n"
|
||||
" ldrex %[ret], [%[perror]] \n"
|
||||
" strex %[temp], %[zero], [%[perror]] \n"
|
||||
" cmp %[temp], %[zero] \n"
|
||||
" bne nrfx_twis_error_get_and_clear_internal_try \n"
|
||||
: /* Output */
|
||||
[ret]"=&l"(ret),
|
||||
[temp]"=&l"(temp)
|
||||
: /* Input */
|
||||
[zero]"l"(0),
|
||||
[perror]"l"(perror)
|
||||
);
|
||||
(void)temp;
|
||||
return ret;
|
||||
}
|
||||
#elif defined ( __ICCARM__ )
|
||||
static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint32_t temp;
|
||||
__ASM volatile(
|
||||
"1: \n"
|
||||
" ldrex %[ret], [%[perror]] \n"
|
||||
" strex %[temp], %[zero], [%[perror]] \n"
|
||||
" cmp %[temp], %[zero] \n"
|
||||
" bne.n 1b \n"
|
||||
: /* Output */
|
||||
[ret]"=&l"(ret),
|
||||
[temp]"=&l"(temp)
|
||||
: /* Input */
|
||||
[zero]"l"(0),
|
||||
[perror]"l"(perror)
|
||||
);
|
||||
(void)temp;
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#error Unknown compiler
|
||||
#endif
|
||||
//lint -restore
|
||||
|
||||
uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
nrfx_twis_preprocess_status(p_instance);
|
||||
/* Make sure that access to error member is atomic
|
||||
* so there is no bit that is cleared if it is not copied to local variable already. */
|
||||
twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return nrfx_twis_error_get_and_clear_internal(&p_cb->error);
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
|
||||
void const * p_buf,
|
||||
size_t size)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
/* Check power state*/
|
||||
if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
/* Check data address */
|
||||
if (!nrfx_is_in_ram(p_buf))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
/* Check data size */
|
||||
if ((size & TWIS_TXD_MAXCNT_MAXCNT_Msk) != size)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_LENGTH;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrf_twis_tx_prepare(p_instance->p_reg,
|
||||
(uint8_t const *)p_buf,
|
||||
size);
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
|
||||
void * p_buf,
|
||||
size_t size)
|
||||
{
|
||||
nrfx_err_t err_code;
|
||||
twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
/* Check power state*/
|
||||
if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
/* Check data address */
|
||||
if (!nrfx_is_in_ram(p_buf))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
/* Check data size */
|
||||
if ((size & TWIS_RXD_MAXCNT_MAXCNT_Msk) != size)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_LENGTH;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrf_twis_rx_prepare(p_instance->p_reg,
|
||||
(uint8_t *)p_buf,
|
||||
size);
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
nrfx_twis_preprocess_status(p_instance);
|
||||
twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return NRFX_TWIS_SUBSTATE_IDLE != p_cb->substate;
|
||||
}
|
||||
|
||||
bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
nrfx_twis_preprocess_status(p_instance);
|
||||
twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return NRFX_TWIS_SUBSTATE_READ_WAITING == p_cb->substate;
|
||||
}
|
||||
|
||||
bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
nrfx_twis_preprocess_status(p_instance);
|
||||
twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return NRFX_TWIS_SUBSTATE_WRITE_WAITING == p_cb->substate;
|
||||
}
|
||||
|
||||
bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
nrfx_twis_preprocess_status(p_instance);
|
||||
twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return NRFX_TWIS_SUBSTATE_READ_PENDING == p_cb->substate;
|
||||
}
|
||||
|
||||
bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)
|
||||
{
|
||||
nrfx_twis_preprocess_status(p_instance);
|
||||
twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
return NRFX_TWIS_SUBSTATE_WRITE_PENDING == p_cb->substate;
|
||||
}
|
||||
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIS0_ENABLED)
|
||||
void nrfx_twis_0_irq_handler(void)
|
||||
{
|
||||
nrfx_twis_state_machine(NRF_TWIS0, &m_cb[NRFX_TWIS0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIS1_ENABLED)
|
||||
void nrfx_twis_1_irq_handler(void)
|
||||
{
|
||||
nrfx_twis_state_machine(NRF_TWIS1, &m_cb[NRFX_TWIS1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIS2_ENABLED)
|
||||
void nrfx_twis_2_irq_handler(void)
|
||||
{
|
||||
nrfx_twis_state_machine(NRF_TWIS2, &m_cb[NRFX_TWIS2_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_TWIS3_ENABLED)
|
||||
void nrfx_twis_3_irq_handler(void)
|
||||
{
|
||||
nrfx_twis_state_machine(NRF_TWIS3, &m_cb[NRFX_TWIS3_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_TWIS_ENABLED)
|
||||
654
modules/nrfx/drivers/src/nrfx_uart.c
Normal file
654
modules/nrfx/drivers/src/nrfx_uart.c
Normal file
@@ -0,0 +1,654 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_UART_ENABLED)
|
||||
|
||||
#if !NRFX_CHECK(NRFX_UART0_ENABLED)
|
||||
#error "No enabled UART instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_uart.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE UART
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_UART_EVENT_ERROR ? "NRF_UART_EVENT_ERROR" : \
|
||||
"UNKNOWN EVENT")
|
||||
|
||||
|
||||
#define TX_COUNTER_ABORT_REQ_VALUE UINT32_MAX
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void * p_context;
|
||||
nrfx_uart_event_handler_t handler;
|
||||
uint8_t const * p_tx_buffer;
|
||||
uint8_t * p_rx_buffer;
|
||||
uint8_t * p_rx_secondary_buffer;
|
||||
volatile size_t tx_buffer_length;
|
||||
size_t rx_buffer_length;
|
||||
size_t rx_secondary_buffer_length;
|
||||
volatile size_t tx_counter;
|
||||
volatile size_t rx_counter;
|
||||
volatile bool tx_abort;
|
||||
bool rx_enabled;
|
||||
nrfx_drv_state_t state;
|
||||
} uart_control_block_t;
|
||||
static uart_control_block_t m_cb[NRFX_UART_ENABLED_COUNT];
|
||||
|
||||
static void apply_config(nrfx_uart_t const * p_instance,
|
||||
nrfx_uart_config_t const * p_config)
|
||||
{
|
||||
if (p_config->pseltxd != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->pseltxd);
|
||||
nrf_gpio_cfg_output(p_config->pseltxd);
|
||||
}
|
||||
if (p_config->pselrxd != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL);
|
||||
}
|
||||
|
||||
nrf_uart_baudrate_set(p_instance->p_reg, p_config->baudrate);
|
||||
nrf_uart_configure(p_instance->p_reg, p_config->parity, p_config->hwfc);
|
||||
nrf_uart_txrx_pins_set(p_instance->p_reg, p_config->pseltxd, p_config->pselrxd);
|
||||
if (p_config->hwfc == NRF_UART_HWFC_ENABLED)
|
||||
{
|
||||
if (p_config->pselcts != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL);
|
||||
}
|
||||
if (p_config->pselrts != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->pselrts);
|
||||
nrf_gpio_cfg_output(p_config->pselrts);
|
||||
}
|
||||
nrf_uart_hwfc_pins_set(p_instance->p_reg, p_config->pselrts, p_config->pselcts);
|
||||
}
|
||||
}
|
||||
|
||||
static void interrupts_enable(nrfx_uart_t const * p_instance,
|
||||
uint8_t interrupt_priority)
|
||||
{
|
||||
nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY);
|
||||
nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO);
|
||||
nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_TXDRDY |
|
||||
NRF_UART_INT_MASK_RXTO);
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number((void *)p_instance->p_reg),
|
||||
interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
|
||||
}
|
||||
|
||||
static void interrupts_disable(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
|
||||
NRF_UART_INT_MASK_TXDRDY |
|
||||
NRF_UART_INT_MASK_ERROR |
|
||||
NRF_UART_INT_MASK_RXTO);
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
|
||||
}
|
||||
|
||||
static void pins_to_default(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
/* Reset pins to default states */
|
||||
uint32_t txd;
|
||||
uint32_t rxd;
|
||||
uint32_t rts;
|
||||
uint32_t cts;
|
||||
|
||||
txd = nrf_uart_tx_pin_get(p_instance->p_reg);
|
||||
rxd = nrf_uart_rx_pin_get(p_instance->p_reg);
|
||||
rts = nrf_uart_rts_pin_get(p_instance->p_reg);
|
||||
cts = nrf_uart_cts_pin_get(p_instance->p_reg);
|
||||
nrf_uart_txrx_pins_disconnect(p_instance->p_reg);
|
||||
nrf_uart_hwfc_pins_disconnect(p_instance->p_reg);
|
||||
|
||||
if (txd != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(txd);
|
||||
}
|
||||
if (rxd != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(rxd);
|
||||
}
|
||||
if (cts != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(cts);
|
||||
}
|
||||
if (rts != NRF_UART_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(rts);
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_uart_init(nrfx_uart_t const * p_instance,
|
||||
nrfx_uart_config_t const * p_config,
|
||||
nrfx_uart_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_UART_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_UART0_ENABLED)
|
||||
nrfx_uart_0_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_instance->p_reg,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
apply_config(p_instance, p_config);
|
||||
|
||||
p_cb->handler = event_handler;
|
||||
p_cb->p_context = p_config->p_context;
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
interrupts_enable(p_instance, p_config->interrupt_priority);
|
||||
}
|
||||
|
||||
nrf_uart_enable(p_instance->p_reg);
|
||||
p_cb->rx_buffer_length = 0;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
p_cb->rx_enabled = false;
|
||||
p_cb->tx_buffer_length = 0;
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_uart_uninit(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
nrf_uart_disable(p_instance->p_reg);
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
interrupts_disable(p_instance);
|
||||
}
|
||||
|
||||
pins_to_default(p_instance);
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_instance->p_reg);
|
||||
#endif
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
p_cb->handler = NULL;
|
||||
NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
static void tx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
|
||||
{
|
||||
nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
|
||||
uint8_t txd = p_cb->p_tx_buffer[p_cb->tx_counter];
|
||||
p_cb->tx_counter++;
|
||||
nrf_uart_txd_set(p_uart, txd);
|
||||
}
|
||||
|
||||
static bool tx_blocking(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
|
||||
{
|
||||
// Use a local variable to avoid undefined order of accessing two volatile variables
|
||||
// in one statement.
|
||||
size_t const tx_buffer_length = p_cb->tx_buffer_length;
|
||||
while (p_cb->tx_counter < tx_buffer_length)
|
||||
{
|
||||
// Wait until the transmitter is ready to accept a new byte.
|
||||
// Exit immediately if the transfer has been aborted.
|
||||
while (!nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY))
|
||||
{
|
||||
if (p_cb->tx_abort)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
tx_byte(p_uart, p_cb);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_uart_tx(nrfx_uart_t const * p_instance,
|
||||
uint8_t const * p_data,
|
||||
size_t length)
|
||||
{
|
||||
uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
|
||||
NRFX_ASSERT(p_data);
|
||||
NRFX_ASSERT(length > 0);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
if (nrfx_uart_tx_in_progress(p_instance))
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
p_cb->tx_buffer_length = length;
|
||||
p_cb->p_tx_buffer = p_data;
|
||||
p_cb->tx_counter = 0;
|
||||
p_cb->tx_abort = false;
|
||||
|
||||
NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length);
|
||||
NRFX_LOG_DEBUG("Tx data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer,
|
||||
p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0]));
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
|
||||
nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY);
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTTX);
|
||||
|
||||
tx_byte(p_instance->p_reg, p_cb);
|
||||
|
||||
if (p_cb->handler == NULL)
|
||||
{
|
||||
if (!tx_blocking(p_instance->p_reg, p_cb))
|
||||
{
|
||||
// The transfer has been aborted.
|
||||
err_code = NRFX_ERROR_FORBIDDEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wait until the last byte is completely transmitted.
|
||||
while (!nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_TXDRDY))
|
||||
{}
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPTX);
|
||||
}
|
||||
p_cb->tx_buffer_length = 0;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
bool nrfx_uart_tx_in_progress(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
return (m_cb[p_instance->drv_inst_idx].tx_buffer_length != 0);
|
||||
}
|
||||
|
||||
static void rx_enable(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
|
||||
nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX);
|
||||
}
|
||||
|
||||
static void rx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
|
||||
{
|
||||
if (!p_cb->rx_buffer_length)
|
||||
{
|
||||
nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
|
||||
// Byte received when buffer is not set - data lost.
|
||||
(void) nrf_uart_rxd_get(p_uart);
|
||||
return;
|
||||
}
|
||||
nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
|
||||
p_cb->p_rx_buffer[p_cb->rx_counter] = nrf_uart_rxd_get(p_uart);
|
||||
p_cb->rx_counter++;
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance,
|
||||
uint8_t * p_data,
|
||||
size_t length)
|
||||
{
|
||||
uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
|
||||
NRFX_ASSERT(p_data);
|
||||
NRFX_ASSERT(length > 0);
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
bool second_buffer = false;
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
|
||||
NRF_UART_INT_MASK_ERROR);
|
||||
}
|
||||
if (p_cb->rx_buffer_length != 0)
|
||||
{
|
||||
if (p_cb->rx_secondary_buffer_length != 0)
|
||||
{
|
||||
if (p_cb->handler)
|
||||
{
|
||||
nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
|
||||
NRF_UART_INT_MASK_ERROR);
|
||||
}
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
second_buffer = true;
|
||||
}
|
||||
|
||||
if (!second_buffer)
|
||||
{
|
||||
p_cb->rx_buffer_length = length;
|
||||
p_cb->p_rx_buffer = p_data;
|
||||
p_cb->rx_counter = 0;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_cb->p_rx_secondary_buffer = p_data;
|
||||
p_cb->rx_secondary_buffer_length = length;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Transfer rx_len: %d.", length);
|
||||
|
||||
if ((!p_cb->rx_enabled) && (!second_buffer))
|
||||
{
|
||||
rx_enable(p_instance);
|
||||
}
|
||||
|
||||
if (p_cb->handler == NULL)
|
||||
{
|
||||
nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO);
|
||||
|
||||
bool rxrdy;
|
||||
bool rxto;
|
||||
bool error;
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
error = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_ERROR);
|
||||
rxrdy = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
|
||||
rxto = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXTO);
|
||||
} while ((!rxrdy) && (!rxto) && (!error));
|
||||
|
||||
if (error || rxto)
|
||||
{
|
||||
break;
|
||||
}
|
||||
rx_byte(p_instance->p_reg, p_cb);
|
||||
} while (p_cb->rx_buffer_length > p_cb->rx_counter);
|
||||
|
||||
p_cb->rx_buffer_length = 0;
|
||||
if (error)
|
||||
{
|
||||
err_code = NRFX_ERROR_INTERNAL;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (rxto)
|
||||
{
|
||||
err_code = NRFX_ERROR_FORBIDDEN;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (p_cb->rx_enabled)
|
||||
{
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip stopping RX if driver is forced to be enabled.
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
|
||||
NRF_UART_INT_MASK_ERROR);
|
||||
}
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
bool nrfx_uart_rx_ready(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
return nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
|
||||
}
|
||||
|
||||
void nrfx_uart_rx_enable(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
if (!m_cb[p_instance->drv_inst_idx].rx_enabled)
|
||||
{
|
||||
rx_enable(p_instance);
|
||||
m_cb[p_instance->drv_inst_idx].rx_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void nrfx_uart_rx_disable(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
|
||||
m_cb[p_instance->drv_inst_idx].rx_enabled = false;
|
||||
}
|
||||
|
||||
uint32_t nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
|
||||
return nrf_uart_errorsrc_get_and_clear(p_instance->p_reg);
|
||||
}
|
||||
|
||||
static void rx_done_event(uart_control_block_t * p_cb,
|
||||
size_t bytes,
|
||||
uint8_t * p_data)
|
||||
{
|
||||
nrfx_uart_event_t event;
|
||||
|
||||
event.type = NRFX_UART_EVT_RX_DONE;
|
||||
event.data.rxtx.bytes = bytes;
|
||||
event.data.rxtx.p_data = p_data;
|
||||
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
}
|
||||
|
||||
static void tx_done_event(uart_control_block_t * p_cb,
|
||||
size_t bytes)
|
||||
{
|
||||
nrfx_uart_event_t event;
|
||||
|
||||
event.type = NRFX_UART_EVT_TX_DONE;
|
||||
event.data.rxtx.bytes = bytes;
|
||||
event.data.rxtx.p_data = (uint8_t *)p_cb->p_tx_buffer;
|
||||
|
||||
p_cb->tx_buffer_length = 0;
|
||||
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
}
|
||||
|
||||
void nrfx_uart_tx_abort(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
p_cb->tx_abort = true;
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPTX);
|
||||
if (p_cb->handler)
|
||||
{
|
||||
tx_done_event(p_cb, p_cb->tx_counter);
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("TX transaction aborted.");
|
||||
}
|
||||
|
||||
void nrfx_uart_rx_abort(nrfx_uart_t const * p_instance)
|
||||
{
|
||||
nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
|
||||
NRF_UART_INT_MASK_ERROR);
|
||||
nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
|
||||
|
||||
NRFX_LOG_INFO("RX transaction aborted.");
|
||||
}
|
||||
|
||||
static void uart_irq_handler(NRF_UART_Type * p_uart,
|
||||
uart_control_block_t * p_cb)
|
||||
{
|
||||
if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_ERROR) &&
|
||||
nrf_uart_event_check(p_uart, NRF_UART_EVENT_ERROR))
|
||||
{
|
||||
nrfx_uart_event_t event;
|
||||
nrf_uart_event_clear(p_uart, NRF_UART_EVENT_ERROR);
|
||||
NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_UART_EVENT_ERROR));
|
||||
nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
|
||||
NRF_UART_INT_MASK_ERROR);
|
||||
if (!p_cb->rx_enabled)
|
||||
{
|
||||
nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
|
||||
}
|
||||
event.type = NRFX_UART_EVT_ERROR;
|
||||
event.data.error.error_mask = nrf_uart_errorsrc_get_and_clear(p_uart);
|
||||
event.data.error.rxtx.bytes = p_cb->rx_buffer_length;
|
||||
event.data.error.rxtx.p_data = p_cb->p_rx_buffer;
|
||||
|
||||
// Abort transfer.
|
||||
p_cb->rx_buffer_length = 0;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
|
||||
p_cb->handler(&event,p_cb->p_context);
|
||||
}
|
||||
else if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_RXDRDY) &&
|
||||
nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXDRDY))
|
||||
{
|
||||
rx_byte(p_uart, p_cb);
|
||||
if (p_cb->rx_buffer_length == p_cb->rx_counter)
|
||||
{
|
||||
if (p_cb->rx_secondary_buffer_length)
|
||||
{
|
||||
uint8_t * p_data = p_cb->p_rx_buffer;
|
||||
size_t rx_counter = p_cb->rx_counter;
|
||||
|
||||
// Switch to secondary buffer.
|
||||
p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length;
|
||||
p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
p_cb->rx_counter = 0;
|
||||
rx_done_event(p_cb, rx_counter, p_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!p_cb->rx_enabled)
|
||||
{
|
||||
nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
|
||||
}
|
||||
nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
|
||||
NRF_UART_INT_MASK_ERROR);
|
||||
p_cb->rx_buffer_length = 0;
|
||||
rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY))
|
||||
{
|
||||
// Use a local variable to avoid undefined order of accessing two volatile variables
|
||||
// in one statement.
|
||||
size_t const tx_buffer_length = p_cb->tx_buffer_length;
|
||||
if (p_cb->tx_counter < tx_buffer_length && !p_cb->tx_abort)
|
||||
{
|
||||
tx_byte(p_uart, p_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
|
||||
if (p_cb->tx_buffer_length)
|
||||
{
|
||||
tx_done_event(p_cb, p_cb->tx_buffer_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXTO))
|
||||
{
|
||||
nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXTO);
|
||||
|
||||
// RXTO event may be triggered as a result of abort call. In th
|
||||
if (p_cb->rx_enabled)
|
||||
{
|
||||
nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STARTRX);
|
||||
}
|
||||
if (p_cb->rx_buffer_length)
|
||||
{
|
||||
p_cb->rx_buffer_length = 0;
|
||||
rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_UART0_ENABLED)
|
||||
void nrfx_uart_0_irq_handler(void)
|
||||
{
|
||||
uart_irq_handler(NRF_UART0, &m_cb[NRFX_UART0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_UART_ENABLED)
|
||||
702
modules/nrfx/drivers/src/nrfx_uarte.c
Normal file
702
modules/nrfx/drivers/src/nrfx_uarte.c
Normal file
@@ -0,0 +1,702 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE_ENABLED)
|
||||
|
||||
#if !(NRFX_CHECK(NRFX_UARTE0_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_UARTE1_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_UARTE2_ENABLED) || \
|
||||
NRFX_CHECK(NRFX_UARTE3_ENABLED))
|
||||
#error "No enabled UARTE instances. Check <nrfx_config.h>."
|
||||
#endif
|
||||
|
||||
#include <nrfx_uarte.h>
|
||||
#include "prs/nrfx_prs.h"
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#define NRFX_LOG_MODULE UARTE
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define EVT_TO_STR(event) \
|
||||
(event == NRF_UARTE_EVENT_ERROR ? "NRF_UARTE_EVENT_ERROR" : \
|
||||
"UNKNOWN EVENT")
|
||||
|
||||
#define UARTEX_LENGTH_VALIDATE(peripheral, drv_inst_idx, len1, len2) \
|
||||
(((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
|
||||
NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, len1, len2))
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
|
||||
#define UARTE0_LENGTH_VALIDATE(...) UARTEX_LENGTH_VALIDATE(UARTE0, __VA_ARGS__)
|
||||
#else
|
||||
#define UARTE0_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
|
||||
#define UARTE1_LENGTH_VALIDATE(...) UARTEX_LENGTH_VALIDATE(UARTE1, __VA_ARGS__)
|
||||
#else
|
||||
#define UARTE1_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE2_ENABLED)
|
||||
#define UARTE2_LENGTH_VALIDATE(...) UARTEX_LENGTH_VALIDATE(UARTE2, __VA_ARGS__)
|
||||
#else
|
||||
#define UARTE2_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE3_ENABLED)
|
||||
#define UARTE3_LENGTH_VALIDATE(...) UARTEX_LENGTH_VALIDATE(UARTE3, __VA_ARGS__)
|
||||
#else
|
||||
#define UARTE3_LENGTH_VALIDATE(...) 0
|
||||
#endif
|
||||
|
||||
#define UARTE_LENGTH_VALIDATE(drv_inst_idx, length) \
|
||||
(UARTE0_LENGTH_VALIDATE(drv_inst_idx, length, 0) || \
|
||||
UARTE1_LENGTH_VALIDATE(drv_inst_idx, length, 0) || \
|
||||
UARTE2_LENGTH_VALIDATE(drv_inst_idx, length, 0) || \
|
||||
UARTE3_LENGTH_VALIDATE(drv_inst_idx, length, 0))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void * p_context;
|
||||
nrfx_uarte_event_handler_t handler;
|
||||
uint8_t const * p_tx_buffer;
|
||||
uint8_t * p_rx_buffer;
|
||||
uint8_t * p_rx_secondary_buffer;
|
||||
volatile size_t tx_buffer_length;
|
||||
size_t rx_buffer_length;
|
||||
size_t rx_secondary_buffer_length;
|
||||
nrfx_drv_state_t state;
|
||||
} uarte_control_block_t;
|
||||
static uarte_control_block_t m_cb[NRFX_UARTE_ENABLED_COUNT];
|
||||
|
||||
static void apply_config(nrfx_uarte_t const * p_instance,
|
||||
nrfx_uarte_config_t const * p_config)
|
||||
{
|
||||
if (p_config->pseltxd != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->pseltxd);
|
||||
nrf_gpio_cfg_output(p_config->pseltxd);
|
||||
}
|
||||
if (p_config->pselrxd != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL);
|
||||
}
|
||||
|
||||
nrf_uarte_baudrate_set(p_instance->p_reg, p_config->baudrate);
|
||||
nrf_uarte_configure(p_instance->p_reg, p_config->parity, p_config->hwfc);
|
||||
nrf_uarte_txrx_pins_set(p_instance->p_reg, p_config->pseltxd, p_config->pselrxd);
|
||||
if (p_config->hwfc == NRF_UARTE_HWFC_ENABLED)
|
||||
{
|
||||
if (p_config->pselcts != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL);
|
||||
}
|
||||
if (p_config->pselrts != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_pin_set(p_config->pselrts);
|
||||
nrf_gpio_cfg_output(p_config->pselrts);
|
||||
}
|
||||
nrf_uarte_hwfc_pins_set(p_instance->p_reg, p_config->pselrts, p_config->pselcts);
|
||||
}
|
||||
}
|
||||
|
||||
static void interrupts_enable(nrfx_uarte_t const * p_instance,
|
||||
uint8_t interrupt_priority)
|
||||
{
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ERROR);
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_RXTO);
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
|
||||
nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ENDRX_MASK |
|
||||
NRF_UARTE_INT_ENDTX_MASK |
|
||||
NRF_UARTE_INT_ERROR_MASK |
|
||||
NRF_UARTE_INT_RXTO_MASK |
|
||||
NRF_UARTE_INT_TXSTOPPED_MASK);
|
||||
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number((void *)p_instance->p_reg),
|
||||
interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
|
||||
}
|
||||
|
||||
static void interrupts_disable(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
nrf_uarte_int_disable(p_instance->p_reg, NRF_UARTE_INT_ENDRX_MASK |
|
||||
NRF_UARTE_INT_ENDTX_MASK |
|
||||
NRF_UARTE_INT_ERROR_MASK |
|
||||
NRF_UARTE_INT_RXTO_MASK |
|
||||
NRF_UARTE_INT_TXSTOPPED_MASK);
|
||||
NRFX_IRQ_DISABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
|
||||
}
|
||||
|
||||
static void pins_to_default(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
/* Reset pins to default states */
|
||||
uint32_t txd;
|
||||
uint32_t rxd;
|
||||
uint32_t rts;
|
||||
uint32_t cts;
|
||||
|
||||
txd = nrf_uarte_tx_pin_get(p_instance->p_reg);
|
||||
rxd = nrf_uarte_rx_pin_get(p_instance->p_reg);
|
||||
rts = nrf_uarte_rts_pin_get(p_instance->p_reg);
|
||||
cts = nrf_uarte_cts_pin_get(p_instance->p_reg);
|
||||
nrf_uarte_txrx_pins_disconnect(p_instance->p_reg);
|
||||
nrf_uarte_hwfc_pins_disconnect(p_instance->p_reg);
|
||||
|
||||
if (txd != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(txd);
|
||||
}
|
||||
if (rxd != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(rxd);
|
||||
}
|
||||
if (cts != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(cts);
|
||||
}
|
||||
if (rts != NRF_UARTE_PSEL_DISCONNECTED)
|
||||
{
|
||||
nrf_gpio_cfg_default(rts);
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_uarte_init(nrfx_uarte_t const * p_instance,
|
||||
nrfx_uarte_config_t const * p_config,
|
||||
nrfx_uarte_event_handler_t event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
nrfx_err_t err_code = NRFX_SUCCESS;
|
||||
|
||||
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
static nrfx_irq_handler_t const irq_handlers[NRFX_UARTE_ENABLED_COUNT] = {
|
||||
#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
|
||||
nrfx_uarte_0_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
|
||||
nrfx_uarte_1_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_UARTE2_ENABLED)
|
||||
nrfx_uarte_2_irq_handler,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_UARTE3_ENABLED)
|
||||
nrfx_uarte_3_irq_handler,
|
||||
#endif
|
||||
};
|
||||
if (nrfx_prs_acquire(p_instance->p_reg,
|
||||
irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
|
||||
apply_config(p_instance, p_config);
|
||||
|
||||
#if defined(NRF5340_XXAA_APPLICATION) || defined(NRF5340_XXAA_NETWORK) || defined(NRF9160_XXAA)
|
||||
// Apply workaround for anomalies:
|
||||
// - nRF9160 - anomaly 23
|
||||
// - nRF5340 - anomaly 44
|
||||
volatile uint32_t const * rxenable_reg =
|
||||
(volatile uint32_t *)(((uint32_t)p_instance->p_reg) + 0x564);
|
||||
volatile uint32_t const * txenable_reg =
|
||||
(volatile uint32_t *)(((uint32_t)p_instance->p_reg) + 0x568);
|
||||
|
||||
if (*txenable_reg == 1)
|
||||
{
|
||||
nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPTX);
|
||||
}
|
||||
|
||||
if (*rxenable_reg == 1)
|
||||
{
|
||||
nrf_uarte_enable(p_instance->p_reg);
|
||||
nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPRX);
|
||||
|
||||
while (*rxenable_reg)
|
||||
{}
|
||||
|
||||
(void)nrf_uarte_errorsrc_get_and_clear(p_instance->p_reg);
|
||||
nrf_uarte_disable(p_instance->p_reg);
|
||||
}
|
||||
#endif // defined(NRF5340_XXAA_APPLICATION) || defined(NRF5340_XXAA_NETWORK) || defined(NRF9160_XXAA)
|
||||
|
||||
p_cb->handler = event_handler;
|
||||
p_cb->p_context = p_config->p_context;
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
interrupts_enable(p_instance, p_config->interrupt_priority);
|
||||
}
|
||||
|
||||
nrf_uarte_enable(p_instance->p_reg);
|
||||
p_cb->rx_buffer_length = 0;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
p_cb->tx_buffer_length = 0;
|
||||
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void nrfx_uarte_uninit(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRF_UARTE_Type * p_reg = p_instance->p_reg;
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
interrupts_disable(p_instance);
|
||||
}
|
||||
// Make sure all transfers are finished before UARTE is disabled
|
||||
// to achieve the lowest power consumption.
|
||||
nrf_uarte_shorts_disable(p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX);
|
||||
|
||||
// Check if there is any ongoing reception.
|
||||
if (p_cb->rx_buffer_length)
|
||||
{
|
||||
nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_RXTO);
|
||||
nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPRX);
|
||||
}
|
||||
|
||||
nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_TXSTOPPED);
|
||||
nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPTX);
|
||||
|
||||
// Wait for TXSTOPPED event and for RXTO event, provided that there was ongoing reception.
|
||||
while (!nrf_uarte_event_check(p_reg, NRF_UARTE_EVENT_TXSTOPPED) ||
|
||||
(p_cb->rx_buffer_length && !nrf_uarte_event_check(p_reg, NRF_UARTE_EVENT_RXTO)))
|
||||
{}
|
||||
|
||||
nrf_uarte_disable(p_reg);
|
||||
pins_to_default(p_instance);
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
nrfx_prs_release(p_reg);
|
||||
#endif
|
||||
|
||||
p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
|
||||
p_cb->handler = NULL;
|
||||
NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance,
|
||||
uint8_t const * p_data,
|
||||
size_t length)
|
||||
{
|
||||
uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
|
||||
NRFX_ASSERT(p_data);
|
||||
NRFX_ASSERT(length > 0);
|
||||
NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length));
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
// EasyDMA requires that transfer buffers are placed in DataRAM,
|
||||
// signal error if the are not.
|
||||
if (!nrfx_is_in_ram(p_data))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if (nrfx_uarte_tx_in_progress(p_instance))
|
||||
{
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
p_cb->tx_buffer_length = length;
|
||||
p_cb->p_tx_buffer = p_data;
|
||||
|
||||
NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length);
|
||||
NRFX_LOG_DEBUG("Tx data:");
|
||||
NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer,
|
||||
p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0]));
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
|
||||
nrf_uarte_tx_buffer_set(p_instance->p_reg, p_cb->p_tx_buffer, p_cb->tx_buffer_length);
|
||||
nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTTX);
|
||||
|
||||
if (p_cb->handler == NULL)
|
||||
{
|
||||
bool endtx;
|
||||
bool txstopped;
|
||||
do
|
||||
{
|
||||
endtx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
|
||||
txstopped = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
|
||||
}
|
||||
while ((!endtx) && (!txstopped));
|
||||
|
||||
if (txstopped)
|
||||
{
|
||||
err_code = NRFX_ERROR_FORBIDDEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transmitter has to be stopped by triggering the STOPTX task to achieve
|
||||
// the lowest possible level of the UARTE power consumption.
|
||||
nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPTX);
|
||||
|
||||
while (!nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED))
|
||||
{}
|
||||
}
|
||||
p_cb->tx_buffer_length = 0;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
bool nrfx_uarte_tx_in_progress(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
return (m_cb[p_instance->drv_inst_idx].tx_buffer_length != 0);
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_uarte_rx(nrfx_uarte_t const * p_instance,
|
||||
uint8_t * p_data,
|
||||
size_t length)
|
||||
{
|
||||
uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
|
||||
NRFX_ASSERT(p_data);
|
||||
NRFX_ASSERT(length > 0);
|
||||
NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length));
|
||||
|
||||
nrfx_err_t err_code;
|
||||
|
||||
// EasyDMA requires that transfer buffers are placed in DataRAM,
|
||||
// signal error if the are not.
|
||||
if (!nrfx_is_in_ram(p_data))
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_ADDR;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
bool second_buffer = false;
|
||||
|
||||
if (p_cb->handler)
|
||||
{
|
||||
nrf_uarte_int_disable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK |
|
||||
NRF_UARTE_INT_ENDRX_MASK);
|
||||
}
|
||||
if (p_cb->rx_buffer_length != 0)
|
||||
{
|
||||
if (p_cb->rx_secondary_buffer_length != 0)
|
||||
{
|
||||
if (p_cb->handler)
|
||||
{
|
||||
nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK |
|
||||
NRF_UARTE_INT_ENDRX_MASK);
|
||||
}
|
||||
err_code = NRFX_ERROR_BUSY;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
second_buffer = true;
|
||||
}
|
||||
|
||||
if (!second_buffer)
|
||||
{
|
||||
p_cb->rx_buffer_length = length;
|
||||
p_cb->p_rx_buffer = p_data;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_cb->p_rx_secondary_buffer = p_data;
|
||||
p_cb->rx_secondary_buffer_length = length;
|
||||
}
|
||||
|
||||
NRFX_LOG_INFO("Transfer rx_len: %d.", length);
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_RXTO);
|
||||
nrf_uarte_rx_buffer_set(p_instance->p_reg, p_data, length);
|
||||
if (!second_buffer)
|
||||
{
|
||||
nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTRX);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_uarte_shorts_enable(p_instance->p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX);
|
||||
}
|
||||
|
||||
if (m_cb[p_instance->drv_inst_idx].handler == NULL)
|
||||
{
|
||||
bool endrx;
|
||||
bool rxto;
|
||||
bool error;
|
||||
do {
|
||||
endrx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
|
||||
rxto = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_RXTO);
|
||||
error = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ERROR);
|
||||
} while ((!endrx) && (!rxto) && (!error));
|
||||
|
||||
m_cb[p_instance->drv_inst_idx].rx_buffer_length = 0;
|
||||
|
||||
if (error)
|
||||
{
|
||||
err_code = NRFX_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
if (rxto)
|
||||
{
|
||||
err_code = NRFX_ERROR_FORBIDDEN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK |
|
||||
NRF_UARTE_INT_ENDRX_MASK);
|
||||
}
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
bool nrfx_uarte_rx_ready(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
return nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
|
||||
}
|
||||
|
||||
uint32_t nrfx_uarte_errorsrc_get(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ERROR);
|
||||
return nrf_uarte_errorsrc_get_and_clear(p_instance->p_reg);
|
||||
}
|
||||
|
||||
static void rx_done_event(uarte_control_block_t * p_cb,
|
||||
size_t bytes,
|
||||
uint8_t * p_data)
|
||||
{
|
||||
nrfx_uarte_event_t event;
|
||||
|
||||
event.type = NRFX_UARTE_EVT_RX_DONE;
|
||||
event.data.rxtx.bytes = bytes;
|
||||
event.data.rxtx.p_data = p_data;
|
||||
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
}
|
||||
|
||||
static void tx_done_event(uarte_control_block_t * p_cb,
|
||||
size_t bytes)
|
||||
{
|
||||
nrfx_uarte_event_t event;
|
||||
|
||||
event.type = NRFX_UARTE_EVT_TX_DONE;
|
||||
event.data.rxtx.bytes = bytes;
|
||||
event.data.rxtx.p_data = (uint8_t *)p_cb->p_tx_buffer;
|
||||
|
||||
p_cb->tx_buffer_length = 0;
|
||||
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
}
|
||||
|
||||
void nrfx_uarte_tx_abort(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
|
||||
nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPTX);
|
||||
if (p_cb->handler == NULL)
|
||||
{
|
||||
while (!nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED))
|
||||
{}
|
||||
}
|
||||
NRFX_LOG_INFO("TX transaction aborted.");
|
||||
}
|
||||
|
||||
void nrfx_uarte_rx_abort(nrfx_uarte_t const * p_instance)
|
||||
{
|
||||
uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
|
||||
|
||||
// Short between ENDRX event and STARTRX task must be disabled before
|
||||
// aborting transmission.
|
||||
if (p_cb->rx_secondary_buffer_length != 0)
|
||||
{
|
||||
nrf_uarte_shorts_disable(p_instance->p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX);
|
||||
}
|
||||
nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPRX);
|
||||
NRFX_LOG_INFO("RX transaction aborted.");
|
||||
}
|
||||
|
||||
static void uarte_irq_handler(NRF_UARTE_Type * p_uarte,
|
||||
uarte_control_block_t * p_cb)
|
||||
{
|
||||
if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ERROR))
|
||||
{
|
||||
nrfx_uarte_event_t event;
|
||||
|
||||
nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ERROR);
|
||||
|
||||
event.type = NRFX_UARTE_EVT_ERROR;
|
||||
event.data.error.error_mask = nrf_uarte_errorsrc_get_and_clear(p_uarte);
|
||||
event.data.error.rxtx.bytes = nrf_uarte_rx_amount_get(p_uarte);
|
||||
event.data.error.rxtx.p_data = p_cb->p_rx_buffer;
|
||||
|
||||
// Abort transfer.
|
||||
p_cb->rx_buffer_length = 0;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
|
||||
p_cb->handler(&event, p_cb->p_context);
|
||||
}
|
||||
else if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDRX))
|
||||
{
|
||||
nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDRX);
|
||||
size_t amount = nrf_uarte_rx_amount_get(p_uarte);
|
||||
// If the transfer was stopped before completion, amount of transfered bytes
|
||||
// will not be equal to the buffer length. Interrupted transfer is ignored.
|
||||
if (amount == p_cb->rx_buffer_length)
|
||||
{
|
||||
if (p_cb->rx_secondary_buffer_length != 0)
|
||||
{
|
||||
uint8_t * p_data = p_cb->p_rx_buffer;
|
||||
nrf_uarte_shorts_disable(p_uarte, NRF_UARTE_SHORT_ENDRX_STARTRX);
|
||||
p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length;
|
||||
p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer;
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
rx_done_event(p_cb, amount, p_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_cb->rx_buffer_length = 0;
|
||||
rx_done_event(p_cb, amount, p_cb->p_rx_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_RXTO))
|
||||
{
|
||||
nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_RXTO);
|
||||
|
||||
if (p_cb->rx_buffer_length != 0)
|
||||
{
|
||||
p_cb->rx_buffer_length = 0;
|
||||
// In case of using double-buffered reception both variables storing buffer length
|
||||
// have to be cleared to prevent incorrect behaviour of the driver.
|
||||
p_cb->rx_secondary_buffer_length = 0;
|
||||
rx_done_event(p_cb, nrf_uarte_rx_amount_get(p_uarte), p_cb->p_rx_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDTX))
|
||||
{
|
||||
nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDTX);
|
||||
|
||||
// Transmitter has to be stopped by triggering STOPTX task to achieve
|
||||
// the lowest possible level of the UARTE power consumption.
|
||||
nrf_uarte_task_trigger(p_uarte, NRF_UARTE_TASK_STOPTX);
|
||||
|
||||
if (p_cb->tx_buffer_length != 0)
|
||||
{
|
||||
tx_done_event(p_cb, nrf_uarte_tx_amount_get(p_uarte));
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_TXSTOPPED))
|
||||
{
|
||||
nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_TXSTOPPED);
|
||||
if (p_cb->tx_buffer_length != 0)
|
||||
{
|
||||
tx_done_event(p_cb, nrf_uarte_tx_amount_get(p_uarte));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
|
||||
void nrfx_uarte_0_irq_handler(void)
|
||||
{
|
||||
uarte_irq_handler(NRF_UARTE0, &m_cb[NRFX_UARTE0_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
|
||||
void nrfx_uarte_1_irq_handler(void)
|
||||
{
|
||||
uarte_irq_handler(NRF_UARTE1, &m_cb[NRFX_UARTE1_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE2_ENABLED)
|
||||
void nrfx_uarte_2_irq_handler(void)
|
||||
{
|
||||
uarte_irq_handler(NRF_UARTE2, &m_cb[NRFX_UARTE2_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NRFX_CHECK(NRFX_UARTE3_ENABLED)
|
||||
void nrfx_uarte_3_irq_handler(void)
|
||||
{
|
||||
uarte_irq_handler(NRF_UARTE3, &m_cb[NRFX_UARTE3_INST_IDX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_UARTE_ENABLED)
|
||||
2282
modules/nrfx/drivers/src/nrfx_usbd.c
Normal file
2282
modules/nrfx/drivers/src/nrfx_usbd.c
Normal file
File diff suppressed because it is too large
Load Diff
93
modules/nrfx/drivers/src/nrfx_usbd_errata.h
Normal file
93
modules/nrfx/drivers/src/nrfx_usbd_errata.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 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 NRFX_USBD_ERRATA_H__
|
||||
#define NRFX_USBD_ERRATA_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
#include <nrf_erratas.h>
|
||||
|
||||
#ifndef NRFX_USBD_ERRATA_ENABLE
|
||||
/**
|
||||
* @brief The constant that informs if errata should be enabled at all.
|
||||
*
|
||||
* If this constant is set to 0, all the Errata bug fixes will be automatically disabled.
|
||||
*/
|
||||
#define NRFX_USBD_ERRATA_ENABLE 1
|
||||
#endif
|
||||
|
||||
|
||||
/* Errata: ISO double buffering not functional. */
|
||||
static inline bool nrfx_usbd_errata_166(void)
|
||||
{
|
||||
return NRFX_USBD_ERRATA_ENABLE && nrf52_errata_166();
|
||||
}
|
||||
|
||||
/* Errata: USBD might not reach its active state. */
|
||||
static inline bool nrfx_usbd_errata_171(void)
|
||||
{
|
||||
return NRFX_USBD_ERRATA_ENABLE && nrf52_errata_171();
|
||||
}
|
||||
|
||||
/* Errata: USB cannot be enabled. */
|
||||
static inline bool nrfx_usbd_errata_187(void)
|
||||
{
|
||||
return NRFX_USBD_ERRATA_ENABLE && nrf52_errata_187();
|
||||
}
|
||||
|
||||
/* Errata: USBD cannot receive tasks during DMA. */
|
||||
static inline bool nrfx_usbd_errata_199(void)
|
||||
{
|
||||
return NRFX_USBD_ERRATA_ENABLE && nrf52_errata_199();
|
||||
}
|
||||
|
||||
/* Errata: Device remains in SUSPEND too long. */
|
||||
static inline bool nrfx_usbd_errata_211(void)
|
||||
{
|
||||
return NRFX_USBD_ERRATA_ENABLE && nrf52_errata_211();
|
||||
}
|
||||
|
||||
/* Errata: Unexpected behavior after reset. **/
|
||||
static inline bool nrfx_usbd_errata_223(void)
|
||||
{
|
||||
return NRFX_USBD_ERRATA_ENABLE && nrf52_errata_223();
|
||||
}
|
||||
|
||||
#endif // NRFX_USBD_ERRATA_H__
|
||||
166
modules/nrfx/drivers/src/nrfx_wdt.c
Normal file
166
modules/nrfx/drivers/src/nrfx_wdt.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_WDT_ENABLED)
|
||||
#include <nrfx_wdt.h>
|
||||
|
||||
#define NRFX_LOG_MODULE WDT
|
||||
#include <nrfx_log.h>
|
||||
|
||||
/**@brief WDT state. */
|
||||
static nrfx_drv_state_t m_state;
|
||||
|
||||
/**@brief WDT alloc table. */
|
||||
static uint8_t m_alloc_index;
|
||||
|
||||
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
|
||||
/**@brief WDT event handler. */
|
||||
static nrfx_wdt_event_handler_t m_wdt_event_handler;
|
||||
|
||||
/**@brief WDT interrupt handler. */
|
||||
void nrfx_wdt_irq_handler(void)
|
||||
{
|
||||
if (nrf_wdt_event_check(NRF_WDT_EVENT_TIMEOUT))
|
||||
{
|
||||
m_wdt_event_handler();
|
||||
nrf_wdt_event_clear(NRF_WDT_EVENT_TIMEOUT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
|
||||
nrfx_wdt_event_handler_t wdt_event_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_config);
|
||||
nrfx_err_t err_code;
|
||||
|
||||
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
|
||||
NRFX_ASSERT(wdt_event_handler != NULL);
|
||||
m_wdt_event_handler = wdt_event_handler;
|
||||
#else
|
||||
NRFX_ASSERT(wdt_event_handler == NULL);
|
||||
(void)wdt_event_handler;
|
||||
#endif
|
||||
if (m_state == NRFX_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
m_state = NRFX_DRV_STATE_INITIALIZED;
|
||||
}
|
||||
else
|
||||
{
|
||||
err_code = NRFX_ERROR_INVALID_STATE;
|
||||
NRFX_LOG_WARNING("Function: %s, error code: %s.",
|
||||
__func__,
|
||||
NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
nrf_wdt_behaviour_set(p_config->behaviour);
|
||||
|
||||
uint64_t ticks = (p_config->reload_value * 32768ULL) / 1000;
|
||||
NRFX_ASSERT(ticks <= UINT32_MAX);
|
||||
|
||||
nrf_wdt_reload_value_set((uint32_t) ticks);
|
||||
|
||||
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
|
||||
NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority);
|
||||
NRFX_IRQ_ENABLE(WDT_IRQn);
|
||||
#endif
|
||||
|
||||
err_code = NRFX_SUCCESS;
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
void nrfx_wdt_enable(void)
|
||||
{
|
||||
NRFX_ASSERT(m_alloc_index != 0);
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
|
||||
nrf_wdt_int_enable(NRF_WDT_INT_TIMEOUT_MASK);
|
||||
#endif
|
||||
nrf_wdt_task_trigger(NRF_WDT_TASK_START);
|
||||
m_state = NRFX_DRV_STATE_POWERED_ON;
|
||||
NRFX_LOG_INFO("Enabled.");
|
||||
}
|
||||
|
||||
|
||||
void nrfx_wdt_feed(void)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
|
||||
for (uint8_t i = 0; i < m_alloc_index; i++)
|
||||
{
|
||||
nrf_wdt_reload_request_set((nrf_wdt_rr_register_t)(NRF_WDT_RR0 + i));
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_wdt_channel_alloc(nrfx_wdt_channel_id * p_channel_id)
|
||||
{
|
||||
nrfx_err_t result;
|
||||
NRFX_ASSERT(p_channel_id);
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
|
||||
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
if (m_alloc_index < NRF_WDT_CHANNEL_NUMBER)
|
||||
{
|
||||
*p_channel_id = (nrfx_wdt_channel_id)(NRF_WDT_RR0 + m_alloc_index);
|
||||
m_alloc_index++;
|
||||
nrf_wdt_reload_request_enable(*p_channel_id);
|
||||
result = NRFX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = NRFX_ERROR_NO_MEM;
|
||||
}
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void nrfx_wdt_channel_feed(nrfx_wdt_channel_id channel_id)
|
||||
{
|
||||
NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
|
||||
nrf_wdt_reload_request_set(channel_id);
|
||||
}
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_WDT_ENABLED)
|
||||
166
modules/nrfx/drivers/src/prs/nrfx_prs.c
Normal file
166
modules/nrfx/drivers/src/prs/nrfx_prs.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 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 <nrfx.h>
|
||||
|
||||
#if NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
#include "nrfx_prs.h"
|
||||
|
||||
#define NRFX_LOG_MODULE PRS
|
||||
#include <nrfx_log.h>
|
||||
|
||||
#define LOG_FUNCTION_EXIT(level, ret_code) \
|
||||
NRFX_LOG_##level("Function: %s, error code: %s.", \
|
||||
__func__, \
|
||||
NRFX_LOG_ERROR_STRING_GET(ret_code))
|
||||
|
||||
|
||||
typedef struct {
|
||||
nrfx_irq_handler_t handler;
|
||||
bool acquired;
|
||||
} prs_box_t;
|
||||
|
||||
#define PRS_BOX_DEFINE(n) \
|
||||
static prs_box_t m_prs_box_##n = { .handler = NULL, .acquired = false }; \
|
||||
void nrfx_prs_box_##n##_irq_handler(void) \
|
||||
{ \
|
||||
NRFX_ASSERT(m_prs_box_##n.handler); \
|
||||
m_prs_box_##n.handler(); \
|
||||
}
|
||||
|
||||
#if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
|
||||
PRS_BOX_DEFINE(0)
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
|
||||
PRS_BOX_DEFINE(1)
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
|
||||
PRS_BOX_DEFINE(2)
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
|
||||
PRS_BOX_DEFINE(3)
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
|
||||
PRS_BOX_DEFINE(4)
|
||||
#endif
|
||||
|
||||
|
||||
static prs_box_t * prs_box_get(void const * p_base_addr)
|
||||
{
|
||||
#if !defined(IS_PRS_BOX)
|
||||
#define IS_PRS_BOX(n, p_base_addr) ((p_base_addr) == NRFX_PRS_BOX_##n##_ADDR)
|
||||
#endif
|
||||
|
||||
#if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
|
||||
if (IS_PRS_BOX(0, p_base_addr)) { return &m_prs_box_0; }
|
||||
else
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
|
||||
if (IS_PRS_BOX(1, p_base_addr)) { return &m_prs_box_1; }
|
||||
else
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
|
||||
if (IS_PRS_BOX(2, p_base_addr)) { return &m_prs_box_2; }
|
||||
else
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
|
||||
if (IS_PRS_BOX(3, p_base_addr)) { return &m_prs_box_3; }
|
||||
else
|
||||
#endif
|
||||
#if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
|
||||
if (IS_PRS_BOX(4, p_base_addr)) { return &m_prs_box_4; }
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nrfx_err_t nrfx_prs_acquire(void const * p_base_addr,
|
||||
nrfx_irq_handler_t irq_handler)
|
||||
{
|
||||
NRFX_ASSERT(p_base_addr);
|
||||
|
||||
nrfx_err_t ret_code;
|
||||
|
||||
prs_box_t * p_box = prs_box_get(p_base_addr);
|
||||
if (p_box != NULL)
|
||||
{
|
||||
bool busy = false;
|
||||
|
||||
NRFX_CRITICAL_SECTION_ENTER();
|
||||
if (p_box->acquired)
|
||||
{
|
||||
busy = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_box->handler = irq_handler;
|
||||
p_box->acquired = true;
|
||||
}
|
||||
NRFX_CRITICAL_SECTION_EXIT();
|
||||
|
||||
if (busy)
|
||||
{
|
||||
ret_code = NRFX_ERROR_BUSY;
|
||||
LOG_FUNCTION_EXIT(WARNING, ret_code);
|
||||
return ret_code;
|
||||
}
|
||||
}
|
||||
|
||||
ret_code = NRFX_SUCCESS;
|
||||
LOG_FUNCTION_EXIT(INFO, ret_code);
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
void nrfx_prs_release(void const * p_base_addr)
|
||||
{
|
||||
NRFX_ASSERT(p_base_addr);
|
||||
|
||||
prs_box_t * p_box = prs_box_get(p_base_addr);
|
||||
if (p_box != NULL)
|
||||
{
|
||||
p_box->handler = NULL;
|
||||
p_box->acquired = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
|
||||
155
modules/nrfx/drivers/src/prs/nrfx_prs.h
Normal file
155
modules/nrfx/drivers/src/prs/nrfx_prs.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 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 NRFX_PRS_H__
|
||||
#define NRFX_PRS_H__
|
||||
|
||||
#include <nrfx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup nrfx_prs Peripheral Resource Sharing (PRS)
|
||||
* @{
|
||||
* @ingroup nrfx
|
||||
*
|
||||
* @brief Peripheral Resource Sharing interface (PRS).
|
||||
*/
|
||||
|
||||
#if defined(NRF51)
|
||||
// SPI0, TWI0
|
||||
#define NRFX_PRS_BOX_0_ADDR NRF_SPI0
|
||||
// SPI1, SPIS1, TWI1
|
||||
#define NRFX_PRS_BOX_1_ADDR NRF_SPI1
|
||||
#elif defined(NRF52810_XXAA)
|
||||
// TWIM0, TWIS0, TWI0
|
||||
#define NRFX_PRS_BOX_0_ADDR NRF_TWIM0
|
||||
// SPIM0, SPIS0, SPI0
|
||||
#define NRFX_PRS_BOX_1_ADDR NRF_SPIM0
|
||||
// UARTE0, UART0
|
||||
#define NRFX_PRS_BOX_2_ADDR NRF_UARTE0
|
||||
#elif defined(NRF52811_XXAA)
|
||||
// TWIM0, TWIS0, TWI0, SPIM1, SPIS1, SPI1
|
||||
#define NRFX_PRS_BOX_0_ADDR NRF_TWIM0
|
||||
// SPIM0, SPIS0, SPI0
|
||||
#define NRFX_PRS_BOX_1_ADDR NRF_SPIM0
|
||||
// UART0, UARTE0
|
||||
#define NRFX_PRS_BOX_2_ADDR NRF_UART0
|
||||
#elif defined(NRF52820_XXAA)
|
||||
// SPIM0, SPIS0, TWIM0, TWIS0, SPI0, TWI0
|
||||
#define NRFX_PRS_BOX_0_ADDR NRF_SPIM0
|
||||
// SPIM1, SPIS1, TWIM1, TWIS1, SPI1, TWI1
|
||||
#define NRFX_PRS_BOX_1_ADDR NRF_SPIM1
|
||||
// UARTE0, UART0
|
||||
#define NRFX_PRS_BOX_2_ADDR NRF_UARTE0
|
||||
#elif defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
|
||||
defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
|
||||
// SPIM0, SPIS0, TWIM0, TWIS0, SPI0, TWI0
|
||||
#define NRFX_PRS_BOX_0_ADDR NRF_SPIM0
|
||||
// SPIM1, SPIS1, TWIM1, TWIS1, SPI1, TWI1
|
||||
#define NRFX_PRS_BOX_1_ADDR NRF_SPIM1
|
||||
// SPIM2, SPIS2, SPI2
|
||||
#define NRFX_PRS_BOX_2_ADDR NRF_SPIM2
|
||||
// COMP, LPCOMP
|
||||
#define NRFX_PRS_BOX_3_ADDR NRF_COMP
|
||||
// UARTE0, UART0
|
||||
#define NRFX_PRS_BOX_4_ADDR NRF_UARTE0
|
||||
#elif defined(NRF9160_XXAA)
|
||||
// UARTE0, SPIM0, SPIS0, TWIM0, TWIS0
|
||||
#define NRFX_PRS_BOX_0_ADDR NRF_UARTE0
|
||||
// UARTE1, SPIM1, SPIS1, TWIM1, TWIS1
|
||||
#define NRFX_PRS_BOX_1_ADDR NRF_UARTE1
|
||||
// UARTE2, SPIM2, SPIS2, TWIM2, TWIS2
|
||||
#define NRFX_PRS_BOX_2_ADDR NRF_UARTE2
|
||||
// UARTE3, SPIM3, SPIS3, TWIM3, TWIS3
|
||||
#define NRFX_PRS_BOX_3_ADDR NRF_UARTE3
|
||||
#else
|
||||
#error "Unknown device."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function for acquiring shared peripheral resources associated with
|
||||
* the specified peripheral.
|
||||
*
|
||||
* Certain resources and registers are shared among peripherals that have
|
||||
* the same ID (for example: SPI0, SPIM0, SPIS0, TWI0, TWIM0, and TWIS0 in
|
||||
* nRF52832). Only one of them can be utilized at a given time. This function
|
||||
* reserves proper resources to be used by the specified peripheral.
|
||||
* If NRFX_PRS_ENABLED is set to a non-zero value, IRQ handlers for peripherals
|
||||
* that are sharing resources with others are implemented by the @ref nrfx_prs
|
||||
* module instead of individual drivers. The drivers must then specify their
|
||||
* interrupt handling routines and register them by using this function.
|
||||
*
|
||||
* @param[in] p_base_addr Requested peripheral base pointer.
|
||||
* @param[in] irq_handler Interrupt handler to register.
|
||||
*
|
||||
* @retval NRFX_SUCCESS If resources were acquired successfully or the
|
||||
* specified peripheral is not handled by the PRS
|
||||
* subsystem and there is no need to acquire resources
|
||||
* for it.
|
||||
* @retval NRFX_ERROR_BUSY If resources were already acquired.
|
||||
*/
|
||||
nrfx_err_t nrfx_prs_acquire(void const * p_base_addr,
|
||||
nrfx_irq_handler_t irq_handler);
|
||||
|
||||
/**
|
||||
* @brief Function for releasing shared resources reserved previously by
|
||||
* @ref nrfx_prs_acquire() for the specified peripheral.
|
||||
*
|
||||
* @param[in] p_base_addr Released peripheral base pointer.
|
||||
*/
|
||||
void nrfx_prs_release(void const * p_base_addr);
|
||||
|
||||
/** @} */
|
||||
|
||||
void nrfx_prs_box_0_irq_handler(void);
|
||||
void nrfx_prs_box_1_irq_handler(void);
|
||||
void nrfx_prs_box_2_irq_handler(void);
|
||||
void nrfx_prs_box_3_irq_handler(void);
|
||||
void nrfx_prs_box_4_irq_handler(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRFX_PRS_H__
|
||||
Reference in New Issue
Block a user