nopnop2002 / esp-idf-sx127x

SX1276/77/78/79 Low Power Long Range Transceiver driver for esp-idf
MIT License
67 stars 13 forks source link

Conflict with SPI sdcard driver (InstrFetchProhibited) #5

Closed ghost closed 2 years ago

ghost commented 2 years ago

I've ported part of the IRQ handling code from https://github.com/bkgoodman/esp-idf-lora, to your implementation. However, I'm seeing a conflict with both the IRQ handling and the SPI bus initialization:

    esp_err_t err = ESP_OK;

#ifdef LED_PIN
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
#endif

#if CONFIG_I2C_INTERFACE
    int i2c_sda = CONFIG_SDA_GPIO;
    int i2c_sclk = CONFIG_SCL_GPIO;
    int reset_pin = CONFIG_RESET_GPIO;

    ESP_LOGI(TAG, "INTERFACE is i2c");
    ESP_LOGI(TAG, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
    ESP_LOGI(TAG, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
    ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);

    i2c_config_t i2c_config = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = i2c_sda,
        .scl_io_num = i2c_sclk,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ
    };

    ESP_ERROR_CHECK(i2c_param_config(I2C_NUM, &i2c_config));
    ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0));

    if (reset_pin >= 0) {
        //gpio_pad_select_gpio(reset);
        gpio_reset_pin(reset_pin);
        gpio_set_direction(reset_pin, GPIO_MODE_OUTPUT);
        gpio_set_level(reset_pin, 0);
        vTaskDelay(50 / portTICK_PERIOD_MS);
        gpio_set_level(reset_pin, 1);
    }

#ifdef HAS_OLED_DISPLAY
    ssd1306_init(&ssd1306_dev, 128, 64);
    ssd1306_clear_screen(&ssd1306_dev, false);
    ssd1306_contrast(&ssd1306_dev, 0xff);
#endif
#endif // CONFIG_I2C_INTERFACE

#ifdef USE_SDCARD
    spi_bus_config_t bus_cfg = {
        .mosi_io_num = SDCARD_MOSI,
        .miso_io_num = SDCARD_MISO,
        .sclk_io_num = SDCARD_SCK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4000,
    };
    ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_HOST);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize bus.");
        return ret;
    }
#endif

    err = lora_setup(cfg);
    if (err != ESP_OK)
        ESP_LOGW(TAG, "RF communications not functional. Missing component?");

My SD card code is identical to:

https://raw.githubusercontent.com/espressif/esp-idf/a82e6e63d98bb051d4c59cb3d440c537ab9f74b0/examples/storage/sd_card/sdspi/main/sd_card_example_main.c

My TTGO LORA32 board configuration:

#define OLED_RST    -1
#define OLED_SDA    21
#define OLED_SCL    22

#define CONFIG_SDA_GPIO OLED_SDA
#define CONFIG_SCL_GPIO OLED_SCL
#define CONFIG_RESET_GPIO OLED_RST

#define SDCARD_SCK      14
#define SDCARD_MOSI     15
#define SDCARD_MISO     2
#define SDCARD_CS       13

#define LORA_MOSI       27
#define LORA_MISO       19
#define LORA_SCLK       5
#define LORA_CS         18
#define LORA_RST        23
#define LORA_DIO0       26
#define LORA_ISR        LORA_DIO0

#define CONFIG_LORA_CS_GPIO  LORA_CS
#define CONFIG_LORA_RST_GPIO LORA_RST
#define CONFIG_LORA_MISO_GPIO LORA_MISO
#define CONFIG_LORA_MOSI_GPIO LORA_MOSI
#define CONFIG_LORA_SCK_GPIO LORA_SCLK
#define CONFIG_LORA_IRQ_GPIO LORA_ISR

LORA setup:

esp_err_t lora_init(void)
{
   esp_err_t ret;

   /*
    * Configure CPU hardware to communicate with the radio chip
    */
   gpio_pad_select_gpio(CONFIG_LORA_RST_GPIO);
   gpio_set_direction(CONFIG_LORA_RST_GPIO, GPIO_MODE_OUTPUT);

   gpio_reset_pin(CONFIG_LORA_CS_GPIO);
   gpio_pad_select_gpio(CONFIG_LORA_CS_GPIO);
   gpio_set_direction(CONFIG_LORA_CS_GPIO, GPIO_MODE_OUTPUT);
   gpio_set_level(CONFIG_LORA_CS_GPIO, 1);

   spi_bus_config_t bus = {
      .miso_io_num = CONFIG_LORA_MISO_GPIO,
      .mosi_io_num = CONFIG_LORA_MOSI_GPIO,
      .sclk_io_num = CONFIG_LORA_SCK_GPIO,
      .quadwp_io_num = -1,
      .quadhd_io_num = -1,
      .max_transfer_sz = 0
   };

   ret = spi_bus_initialize(SPI_HOST_ID, &bus, SPI_DMA_CH_AUTO);
   if (ret != ESP_OK)
      return ret;

   spi_device_interface_config_t dev = {
      .clock_speed_hz = 9000000,
      .mode = 0,
      .spics_io_num = CONFIG_LORA_CS_GPIO,
      .queue_size = 7,
      .flags = 0,
      .pre_cb = NULL
   };

   ret = spi_bus_add_device(SPI_HOST_ID, &dev, &__spi);
   if (ret != ESP_OK)
      return ret;

   /*
    * Perform hardware reset.
    */
   lora_reset();

   /*
    * Check version.
    */
   uint8_t version;
   uint8_t i = 0;
   while(i++ < TIMEOUT_RESET) {
      version = lora_read_reg(REG_VERSION);
      if(version == 0x12) break;
      vTaskDelay(2);
   }
   assert(i <= TIMEOUT_RESET + 1); // at the end of the loop above, the max value i can reach is TIMEOUT_RESET + 1

   /*
    * Default configuration.
    */
   lora_sleep();
   lora_write_reg(REG_FIFO_RX_BASE_ADDR, 0);
   lora_write_reg(REG_FIFO_TX_BASE_ADDR, 0);
   lora_write_reg(REG_LNA, lora_read_reg(REG_LNA) | 0x03);
   lora_write_reg(REG_MODEM_CONFIG_3, 0x04);
   lora_set_tx_power(17);

   lora_idle();
   return ESP_OK;
}

I've been trying to follow the steps described here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdspi_share.html

Guru Meditation Error: Core  0 panic'ed (InstrFetchProhibited). Exception was unhandled.

Core  0 register dump:
PC      : 0x00000000  PS      : 0x00060030  A0      : 0x00000000  A1      : 0x3ffbc510  
A2      : 0x3ffb9750  A3      : 0x00000000  A4      : 0x3ffb4610  A5      : 0x3ffb4620  
A6      : 0x00000001  A7      : 0x00000060  A8      : 0x8008cec4  A9      : 0x3ffbc4f0  
A10     : 0x3ffb9750  A11     : 0x00000092  A12     : 0x00000091  A13     : 0x00000060  
A14     : 0x00000000  A15     : 0x00000001  SAR     : 0x00000000  EXCCAUSE: 0x00000014  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000  

I'm happy to send you the entire lora.c file. Thank you for your excellent work again, your repositories are an absolute time saver and great reference.

ghost commented 2 years ago

An update: spi: spi_bus_initialize(628): SPI bus already initialized.␛[0 this is possibly related to not using the right bus (I do not know yet how to force use of software SPI bus).

We might want to use VSPI_HOST for LORA, and HSPI_HOST for the sdcard.

nopnop2002 commented 2 years ago

SDSPI initialize

sdmmc_host_t host = SDSPI_HOST_DEFAULT();

SDSPI_HOST_DEFAULT is here. https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/sdspi_host.h

SDSPI_HOST_DEFAULT () has the following contents.

#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#define SDSPI_DEFAULT_HOST HSPI_HOST
#define SDSPI_DEFAULT_DMA  SDSPI_DEFAULT_HOST
#else
#define SDSPI_DEFAULT_HOST SPI2_HOST
#define SDSPI_DEFAULT_DMA  SPI_DMA_CH_AUTO
#endif

/**
 * @brief Default sdmmc_host_t structure initializer for SD over SPI driver
 *
 * Uses SPI mode and max frequency set to 20MHz
 *
 * 'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`.
 */
#define SDSPI_HOST_DEFAULT() {\
    .flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \
    .slot = SDSPI_DEFAULT_HOST, \
    .max_freq_khz = SDMMC_FREQ_DEFAULT, \
    .io_voltage = 3.3f, \
    .init = &sdspi_host_init, \
    .set_bus_width = NULL, \
    .get_bus_width = NULL, \
    .set_bus_ddr_mode = NULL, \
    .set_card_clk = &sdspi_host_set_card_clk, \
    .do_transaction = &sdspi_host_do_transaction, \
    .deinit_p = &sdspi_host_remove_device, \
    .io_int_enable = &sdspi_host_io_int_enable, \
    .io_int_wait = &sdspi_host_io_int_wait, \
    .command_timeout_ms = 0, \
}

HSPI_HOST / SPI2_HOST cannot be used on other devices. Conflicts when using HSPI_HOST / SPI2_HOST on other devices..

#ifdef USE_SDCARD
    spi_bus_config_t bus_cfg = {
        .mosi_io_num = SDCARD_MOSI,
        .miso_io_num = SDCARD_MISO,
        .sclk_io_num = SDCARD_SCK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4000,
    };
    ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_HOST); ---> host.slot is HSPI_HOST/SPI2_HOST
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize bus.");
        return ret;
    }
#endif

LoRa Initialize

When using SDSPI, HSPI_HOST / SPI2_HOST cannot be used for SPI_HOST_ID.

#ifdef CONFIG_IDF_TARGET_ESP32
#define SPI_HOST_ID HSPI_HOST  --> Must be change
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define SPI_HOST_ID SPI2_HOST --> Must be change
#elif defined CONFIG_IDF_TARGET_ESP32S3
#define SPI_HOST_ID SPI2_HOST --> Must be change
#elif defined CONFIG_IDF_TARGET_ESP32C3
#define SPI_HOST_ID SPI2_HOST --> Must be change
#endif

   ret = spi_bus_initialize(SPI_HOST_ID, &bus, SPI_DMA_CH_AUTO);
   if (ret != ESP_OK)
      return ret;
nopnop2002 commented 2 years ago

I've ported part of the IRQ handling code from https://github.com/bkgoodman/esp-idf-lora, to your implementation.

I want to know more details.

nopnop2002 commented 2 years ago

I found this code no longer meaningful: ESP32 has SPI2_HOST/SPI3_HOST.

#ifdef CONFIG_IDF_TARGET_ESP32
#define LCD_HOST HSPI_HOST
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define LCD_HOST SPI2_HOST
#elif defined CONFIG_IDF_TARGET_ESP32S3
#define LCD_HOST SPI2_HOST
#elif defined CONFIG_IDF_TARGET_ESP32C3
#define LCD_HOST SPI2_HOST
#endif

I am considering making it possible to select SPI2_HOST / SPI3_HOST.

nopnop2002 commented 2 years ago

You can now select SPI2_HOST / SPI3_HOST.

Set to SPI3_HOST when using with SDSPI.

We might want to use VSPI_HOST for LORA, and HSPI_HOST for the sdcard.

ESP32S2 / S3 / C3 / H2 / C2 does not have VSPI_HOST.

In ESP32S2 / S3 / C3 / H2 / C2, VSPI_HOST has changed to SPI3_HOST.

config-lora-3