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.

Parents
  • 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

Reply
  • 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

Children
No Data
Related