nrfx_saadc crashing nrfx_spim using st7735 tft

Hi,

I have an application where I use nrfx_saadc for getting some samples and I also run the st7735 driver, modified to use nrfx_spim instead nrf_drv.

For the nrfx_saadc code, I have used the example described in: https://github.com/NordicSemiconductor/nrfx/wiki/SAADC-Advanced-mode-with-IRQs

The spi driver using nrfx_spim I wrote is quite simple, to be able to use more stuff.

#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "eeprom.h"
#include "nrfx_spim.h"

#define SPI_PIN_UNUSED NRFX_SPIM_PIN_NOT_USED
typedef struct {
    uint8_t miso;
    uint8_t mosi;
    uint8_t clk;
} spi_pindef_t;

void spi_init(const spi_pindef_t pins);
void spi_xfer(uint8_t user_cs, uint8_t * tx_data, uint16_t tx_size, uint8_t * rx_data, uint16_t rx_size);

static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(2);
// We allocate memory for the biggest eeprom just in case
static uint8_t rx_buf[EEPROM_SIZE_CAT25040 + 3];

void spi_init(const spi_pindef_t pins) {
    nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    // SS is not init because we will use a different CS depending on the device
    spi_config.ss_pin   = NRFX_SPIM_PIN_NOT_USED;
    spi_config.miso_pin = pins.miso;
    spi_config.mosi_pin = pins.mosi;
    spi_config.sck_pin  = pins.clk;

    APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, NULL, NULL));
}
void spi_xfer(uint8_t user_cs, uint8_t * tx_data, uint16_t tx_size, uint8_t * rx_data, uint16_t rx_size) {
    if(user_cs != NRFX_SPIM_PIN_NOT_USED) {
        nrf_gpio_pin_clear(user_cs);
    }
    nrfx_spim_xfer_desc_t xfer_desc = {
        .p_tx_buffer = tx_data,
        .tx_length = tx_size,
        .p_rx_buffer = rx_buf,
        // Account for that the data needs to be clocked out
        .rx_length = rx_size + tx_size,
    };


    APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));
    if(user_cs != NRFX_SPIM_PIN_NOT_USED) {
        nrf_gpio_pin_set(user_cs);
    }
    for (uint8_t i = 0; i < rx_size; i++) {
        rx_data[i] = rx_buf[tx_size + i];
    }
}

The only thing I changed from the original st7735.c at

components/drivers_ext/st7735/st7735.c
is :
static inline void spi_write(const void * data, size_t size) {
    spi_xfer(_pins.cs, data, size, NULL, 0);
}

Once I've used the saadc for a single conversion, spi stops to work, when I use the debugger it gets 'trapped' inside the spi driver. In a task that if I don't use the adc, works no problem.

  • Hello Pablo,

    Thanks for your queries. 

    We just need to know few things before providing proper solution. The questions are as follow:

    1. Which pins do you use for SAADC and SPIM?

    2. Could you please share your code for SAADC including configuration and and handlers?

    3. Which function or exact line where the application gets stuck on SPI driver if debugging?

    BR

    Kazi Afroza Sultana

  • For the adc,

     I  omitted the non relevant code.

    A consecutive call of get_data does the data sampling and processing no problem. But when I want to leave this part of the application, there is a screen change

    ///// SDK
    #include "nrfx_saadc.h"
    #include "app_error.h"
    ///// MODULES
    #include "eventqueue.h"
    
    #define SAMPLES_NUMBER      128
    #define ADC_SAMPLE_RATE     10000
    
    static nrf_saadc_value_t adc_buf[2][SAMPLES_NUMBER];
    static nrf_saadc_value_t process_buf[SAMPLES_NUMBER];
    static uint32_t buf_to_load;
    static uint16_t adc_samples = 0;
    
    static void adc_evt_handler(nrfx_saadc_evt_t const * p_event) {
        switch (p_event->type) {
            case NRFX_SAADC_EVT_DONE: {
                // Buffer with data is available here: p_event->data.done.p_buffer
                adc_samples = p_event->data.done.size;
                for (uint32_t i = 0; i < adc_samples; i++) {
                    process_buf[i] = p_event->data.done.p_buffer[i];
                }
                event_post(DATA_READY);
            }
            break;
            case NRFX_SAADC_EVT_BUF_REQ:
                nrfx_saadc_buffer_set(adc_buf[buf_to_load % 2], SAMPLES_NUMBER);
                buf_to_load++;
                break;
            default:
                break;
        }
    }
    
    /*
        EVENT HANDLER NOT IN INTERRUPT CONTEXT
     */
    void data_event_handler(eventq_type_t type, void *arg) {
        if(type == DATA_READY) {
            process_data();
        } else if(type == GET_DATA) {
            get_data();
        }
    }
    
    static void adc_init(void) {
        ret_code_t err_code;
        nrfx_saadc_channel_t tuner_ch   = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 0);
        nrfx_saadc_adv_config_t adc_cfg = {
            .oversampling      = NRF_SAADC_OVERSAMPLE_DISABLED, // Disable oversample.
            .burst             = false,                         // Disable burst.
            .internal_timer_cc = 16000000UL/ADC_SAMPLE_RATE,    // Sample at 10kHz.
            .start_on_end      = false,                         // Latch next buffer at END event in interrupt.
        };
        err_code = nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY);
        APP_ERROR_CHECK(err_code);
        err_code = nrfx_saadc_channels_config(&tuner_ch, 1);
        APP_ERROR_CHECK(err_code);
        err_code = nrfx_saadc_advanced_mode_set((1<<0), NRF_SAADC_RESOLUTION_10BIT, &adc_cfg, adc_evt_handler);
        APP_ERROR_CHECK(err_code);
        err_code = nrfx_saadc_buffer_set(adc_buf[buf_to_load % 2], SAMPLES_NUMBER);
        APP_ERROR_CHECK(err_code);
        buf_to_load++;
        err_code = nrfx_saadc_mode_trigger();
        APP_ERROR_CHECK(err_code);
    }
    
    static void get_data() {
        adc_init();
    }
    /*
        EVENT HANDLER WILL CALL THIS EVENTUALLY
    
     */
    static void process_data() {
        /*
         */
    
        nrfx_saadc_uninit();
        dbg("Processing samples\n");
        /*
            SOME PROCESSING
         */
    }
    

    The pintout for the spi and tft is:

    // SPI
    #define SPI_MOSI_PIN 16
    #define SPI_MISO_PIN 17
    #define SPI_CLK_PIN 18
    // TFT
    #define TFT_CS_PIN 26
    #define TFT_RST_PIN 25
    #define TFT_D_C_PIN 27
    
    

    If I stop de execution when nothing happens: I appear at:

    modules/nrfx/hal/nrf_spim.h:560

    I will resume execution and pause it from time to time and I will she how the spi code is run

    eventually I will endup in:

    modules/nrfx/drivers/nrfx_common.h:309

    But I don't know if thats relevant because it looks like its going through the calls, eventhough it takes forever and nothing happens. No error is dropped, I can still communicate with the application via serial.

    Before I call the ADC the SAADC peripheral is this state:

    And SPIM2 in this state:

    And once I init and trigger the adc and leave that part of the code, the status is:

    SAADC

    SPIM2

  • Hello Pablo,

    Sorry for late reply. As your reply arrived in weekend.

    Looking at the part of codes (as not the complete project) I have few comment: -

    Normally no code being run from header files so I am just thinking how it gets stuck in the header files. 

    It seems like nrf_spim.h:560 is a check for an event, but it should not get stuck there. 

    May be it gets stuck somewhere else if the driver that uses this function to wait for an event that is never generated.  

    If it is possible you can send the complete project.

    BR

    Kazi Afroza Sultana

  • Hi Kazi,

    I had put the code into the same snippet for convenience, but is not a single header file, sorry for the confusion.

    I don't want to share the entire project.

    Is there any configuration (visible in the already shared code snippers) that I've done to the NRFX_SPIM and NRFX_SAADC that is not compatible or might be prone to error, given the pinout used in my project ?

    Do the NRFX_SAADC and NRFX_SPIM share any resource that should be handled differently ? Is any of the NRFX_SAADC config code "overwriting" in some how something that has been configured by the NRFX_SPIM before ?

    BR

  • Hello,

    It may not be seen obvious issues from the snippet; However there are some configuration and relevant parts missing from the post, for example- the value of NRFX_SAADC_CONFIG_IRQ_PRIORITY / NRFX_SPIM_DEFAULT_CONFIG ,

       

    How SPI transfers and SAADC sampling are triggered (could be interrupt priority issues), etc. 

    A few things that could potentially cause issues:

    1. We can see from your snippet that you have set AIN3 pin for SADDAC (nrfx_saadc_channel_t tuner_ch   = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 0)). This pin is by default used for RTS pin on DK if project initializes the UART library and driver (Nordic Semiconductor Infocenter).

    2. Pin 16 to 18 (P0.16 to P0.18) is used for SPI in  your code. But these are used for LEDs and Buttons on the DK. This may be an issue if Board Support package (BSP) is initialized in the project.

    Best Regards,

    Kazi Afroza Sultana

Related