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

Related