Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NRF52: Stall on SPI Master + RTC IRQs and compile fixes for non SOFTDEVICE_PRESENT target #6908

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/

#include "app_fifo.h"
#include "nrf_error.h"
#include "app_util.h"

/**
* @brief Verify NULL parameters are not passed to an API by application.
*/
#define NULL_PARAM_CHECK(PARAM) \
if ((PARAM) == NULL) \
{ \
return (NRF_ERROR_NULL); \
}


static __INLINE uint32_t fifo_length(app_fifo_t * p_fifo)
{
uint32_t tmp = p_fifo->read_pos;
return p_fifo->write_pos - tmp;
}


#define FIFO_LENGTH fifo_length(p_fifo) /**< Macro for calculating the FIFO length. */


/**@brief Put one byte to the FIFO. */
static __INLINE void fifo_put(app_fifo_t * p_fifo, uint8_t byte)
{
p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask] = byte;
p_fifo->write_pos++;
}


/**@brief Get one byte to the FIFO. */
static __INLINE void fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte)
{
*p_byte = p_fifo->p_buf[p_fifo->read_pos & p_fifo->buf_size_mask];
p_fifo->read_pos++;
}


uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size)
{
// Check buffer for null pointer.
if (p_buf == NULL)
{
return NRF_ERROR_NULL;
}

// Check that the buffer size is a power of two.
if (!IS_POWER_OF_TWO(buf_size))
{
return NRF_ERROR_INVALID_LENGTH;
}

p_fifo->p_buf = p_buf;
p_fifo->buf_size_mask = buf_size - 1;
p_fifo->read_pos = 0;
p_fifo->write_pos = 0;

return NRF_SUCCESS;
}


uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte)
{
if (FIFO_LENGTH <= p_fifo->buf_size_mask)
{
fifo_put(p_fifo, byte);
return NRF_SUCCESS;
}

return NRF_ERROR_NO_MEM;
}


uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte)
{
if (FIFO_LENGTH != 0)
{
fifo_get(p_fifo, p_byte);
return NRF_SUCCESS;
}

return NRF_ERROR_NOT_FOUND;

}


uint32_t app_fifo_flush(app_fifo_t * p_fifo)
{
p_fifo->read_pos = p_fifo->write_pos;
return NRF_SUCCESS;
}


uint32_t app_fifo_read(app_fifo_t * p_fifo, uint8_t * p_byte_array, uint32_t * p_size)
{
NULL_PARAM_CHECK(p_fifo);
NULL_PARAM_CHECK(p_size);

const uint32_t byte_count = fifo_length(p_fifo);
const uint32_t requested_len = (*p_size);
uint32_t index = 0;
uint32_t read_size = 0;

(*p_size) = byte_count;

// Check if the FIFO is empty.
if (byte_count == 0)
{
return NRF_ERROR_NOT_FOUND;
}

// Check if application has requested only the size.
if (p_byte_array == NULL)
{
(*p_size) = byte_count;
return NRF_SUCCESS;
}

// Check is available bytes in FIFO less than requested.
if (requested_len < byte_count)
{
read_size = requested_len;
}
else
{
read_size = byte_count;
}

// Fetch bytes from the FIFO.
do
{
fifo_get(p_fifo, &p_byte_array[index++]);
} while (index < read_size);

(*p_size) = read_size;

return NRF_SUCCESS;
}


uint32_t app_fifo_write(app_fifo_t * p_fifo, uint8_t const * p_byte_array, uint32_t * p_size)
{
NULL_PARAM_CHECK(p_fifo);
NULL_PARAM_CHECK(p_size);

const uint32_t available_count = p_fifo->buf_size_mask - fifo_length(p_fifo) + 1;
const uint32_t requested_len = (*p_size);
uint32_t index = 0;
uint32_t write_size = 0;

(*p_size) = available_count;

// Check if the FIFO is FULL.
if (available_count == 0)
{
return NRF_ERROR_NO_MEM;
}

// Check if application has requested only the size.
if (p_byte_array == NULL)
{
(*p_size) = available_count;
return NRF_SUCCESS;
}

// Check is available bytes in FIFO less than requested.
if (requested_len < available_count)
{
write_size = requested_len;
}
else
{
write_size = available_count;
}

//Fetch bytes from the FIFO.
do
{
fifo_put(p_fifo, p_byte_array[index++]);
} while (index < write_size);

(*p_size) = write_size;

return NRF_SUCCESS;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/

/**@file
*
* @defgroup app_fifo FIFO implementation
* @{
* @ingroup app_common
*
* @brief FIFO implementation.
*/

#ifndef APP_FIFO_H__
#define APP_FIFO_H__

#include <stdint.h>
#include <stdlib.h>

/**@brief A FIFO instance structure.
* @details Keeps track of which bytes to read and write next.
* Also, it keeps the information about which memory is allocated for the buffer
* and its size. This structure must be initialized by app_fifo_init() before use.
*/
typedef struct
{
uint8_t * p_buf; /**< Pointer to FIFO buffer memory. */
uint16_t buf_size_mask; /**< Read/write index mask. Also used for size checking. */
volatile uint32_t read_pos; /**< Next read position in the FIFO buffer. */
volatile uint32_t write_pos; /**< Next write position in the FIFO buffer. */
} app_fifo_t;

/**@brief Function for initializing the FIFO.
*
* @param[out] p_fifo FIFO object.
* @param[in] p_buf FIFO buffer for storing data. The buffer size must be a power of two.
* @param[in] buf_size Size of the FIFO buffer provided. This size must be a power of two.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_NULL If a NULL pointer is provided as buffer.
* @retval NRF_ERROR_INVALID_LENGTH If size of buffer provided is not a power of two.
*/
uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size);

/**@brief Function for adding an element to the FIFO.
*
* @param[in] p_fifo Pointer to the FIFO.
* @param[in] byte Data byte to add to the FIFO.
*
* @retval NRF_SUCCESS If an element has been successfully added to the FIFO.
* @retval NRF_ERROR_NO_MEM If the FIFO is full.
*/
uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte);

/**@brief Function for getting the next element from the FIFO.
*
* @param[in] p_fifo Pointer to the FIFO.
* @param[out] p_byte Byte fetched from the FIFO.
*
* @retval NRF_SUCCESS If an element was returned.
* @retval NRF_ERROR_NOT_FOUND If there are no more elements in the queue.
*/
uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte);

/**@brief Function for flushing the FIFO.
*
* @param[in] p_fifo Pointer to the FIFO.
*
* @retval NRF_SUCCESS If the FIFO was flushed successfully.
*/
uint32_t app_fifo_flush(app_fifo_t * p_fifo);

/**@brief Function for reading bytes from the FIFO.
*
* This function can also be used to get the number of bytes in the FIFO.
*
* @param[in] p_fifo Pointer to the FIFO. Must not be NULL.
* @param[out] p_byte_array Memory pointer where the read bytes are fetched from the FIFO.
* Can be NULL. If NULL, the number of bytes that can be read in the FIFO
* are returned in the p_size parameter.
* @param[inout] p_size Address to memory indicating the maximum number of bytes to be read.
* The provided memory is overwritten with the actual number of bytes
* read if the procedure was successful. This field must not be NULL.
* If p_byte_array is set to NULL by the application, this parameter
* returns the number of bytes in the FIFO.
*
* @retval NRF_SUCCESS If the procedure is successful. The actual number of bytes read might
* be less than the requested maximum, depending on how many elements exist
* in the FIFO. Even if less bytes are returned, the procedure is considered
* successful.
* @retval NRF_ERROR_NULL If a NULL parameter was passed for a parameter that must not
* be NULL.
* @retval NRF_ERROR_NOT_FOUND If the FIFO is empty.
*/
uint32_t app_fifo_read(app_fifo_t * p_fifo, uint8_t * p_byte_array, uint32_t * p_size);

/**@brief Function for writing bytes to the FIFO.
*
* This function can also be used to get the available size on the FIFO.
*
* @param[in] p_fifo Pointer to the FIFO. Must not be NULL.
* @param[in] p_byte_array Memory pointer containing the bytes to be written to the FIFO.
* Can be NULL. If NULL, this function returns the number of bytes
* that can be written to the FIFO.
* @param[inout] p_size Address to memory indicating the maximum number of bytes to be written.
* The provided memory is overwritten with the number of bytes that were actually
* written if the procedure is successful. This field must not be NULL.
* If p_byte_array is set to NULL by the application, this parameter
* returns the number of bytes available in the FIFO.
*
* @retval NRF_SUCCESS If the procedure is successful. The actual number of bytes written might
* be less than the requested maximum, depending on how much room there is in
* the FIFO. Even if less bytes are written, the procedure is considered
* successful. If the write was partial, the application should use
* subsequent calls to attempt writing the data again.
* @retval NRF_ERROR_NULL If a NULL parameter was passed for a parameter that must not
* be NULL.
* @retval NRF_ERROR_NO_MEM If the FIFO is full.
*
*/
uint32_t app_fifo_write(app_fifo_t * p_fifo, uint8_t const * p_byte_array, uint32_t * p_size);

#endif // APP_FIFO_H__

/** @} */
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,11 @@ static void spi_xfer(NRF_SPI_Type * p_spi,

nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);

if (p_cb->handler)
{
nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK);
}

// 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.
Expand All @@ -441,11 +446,8 @@ static void spi_xfer(NRF_SPI_Type * p_spi,
// 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

if (!p_cb->handler)
{
do {
while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
Expand Down
7 changes: 7 additions & 0 deletions targets/TARGET_NORDIC/TARGET_NRF5/nordic_critical.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ static volatile bool state_saved = false;

static void nordic_nvic_critical_region_enter(void);
static void nordic_nvic_critical_region_exit(void);
#else
extern void app_util_enable_irq();
extern void app_util_disable_irq();
#endif

void hal_critical_section_enter()
Expand Down Expand Up @@ -56,7 +59,11 @@ void hal_critical_section_exit()

bool hal_in_critical_section(void)
{
#if defined(SOFTDEVICE_PRESENT)
return (state_saved != 0);
#else
return false;
#endif
}


Expand Down