This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI Working example please for read and write to SRAM

I really did not want to ask, howeverI have spent a lot of time on this and still no joy.

I have a epaper shield have got the electronic paper display working. so SPI writes to the epd is working.

Does anyone have a working example in Zephyr working with the 

23LCV1024. I have tested this shield on the Arduino and got the SRAM_23LC-1.1.2 SRAM_Example.ino working on the Arduino.
fixed up SRAM_23LC so it should work on Zephyr and nrf9160 dk.All code works and compiles, writes give no error, however all reads give either a 0xFF or 0x00.
I get the loopback nordic zephyr spi working fine.
So if anyone can help? need to read and writes for byte and block.
Using nordic sdk / ncs / v1.3.0. 
Parents
  • Hi!

    Nordic does not have any samples for the 23LCV1024 unfortunately.

    I'd be happy to help you get it working, but I will need some more information about your application and setup.

    Best regards,

    Heidi

  • Heidi,

    Thanks and apologies for the delay in responding. Been trying to get the code readable again.

    I have tried many many variations, different spi configs, etc... Even trying in pure c.

    Looked everywhere for a comprehensive zephyr nordic SPI example to work off, with no success.

    Using the nrf9160dk and using Asset Tracker app as the base.

    The overlay file (nrf9160dk_nrf9160ns.overlay) in my project boards directory is currently:-

    &spi3 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    sck-pin = <10>;
    mosi-pin = <11>;
    miso-pin = <12>;
    };

    Main.cpp is:-
    // use this main for testing only. For production reinstate main.cppkeep
    
    #include <stddef.h>
    #include <iostream>
    #include "asset_tracker.h"
    
    // spi test
    #include <drivers/gpio.h>
    #include <drivers/spi.h>
    #include <string.h>
    #include <z_cart_helper.h>
    
    #include "SRAM_23LC.h"
    //#include <nrfx_spim.h>
    
    //#include "zSX1509.h"
    // SX1509 ioExtend1;
    
    void main(void) {
      // test SPI and spi_SRAM
      struct device* spi_dev;
      const char* const spiName = "SPI_3";
      spi_dev = device_get_binding(spiName);
      if (spi_dev == NULL) {
        printk("Could not get SPI %s device\n", spiName);
        return;
      }
    
    /* Device can be:
     * 128KB: SRAM_23LCV1024, SRAM_23LC1024, SRAM_23A1024
     * 64KB: SRAM_23LCV512, SRAM_23LC512, SRAM_23A512
     * 32KB: SRAM_23A256, SRAM_23K256
     * 8KB: SRAM_23A640, SRAM_23K640
     */
    #if USE_SX1509_RAM_CS
      SRAM_23LC SRAM(spi_dev, SX15091_IO05_SPIRAM_CS, SRAM_23LCV1024);
    #else
      SRAM_23LC SRAM(spi_dev, GPIO_SPIRAM_CS, SRAM_23LCV1024);
    #endif
    
    SRAM.begin(2000000);
    SRAM.spiRamWriteReadTest();
    k_msleep(1000);
    
      // testeigen1();
      // test_eigen2();
    
      // test to execute shell command
      // k_msleep(10);
      // it works here but leaves user on prompt and mixed message
      // shell_execute_cmd(shell_backend_uart_get_ptr(), "user version");
      // shell_execute_cmd(shell_backend_rtt_get_ptr(), "user version");
    
      k_work_q_start(&application_work_q, application_stack_area, K_THREAD_STACK_SIZEOF(application_stack_area),
                     CONFIG_APPLICATION_WORKQUEUE_PRIORITY);
      if (IS_ENABLED(CONFIG_WATCHDOG)) {
        watchdog_init_and_start(&application_work_q);
      }
    
    #if defined(CONFIG_LWM2M_CARRIER)
      k_sem_take(&bsdlib_initialized, K_FOREVER);
    #else
      handle_bsdlib_init_ret();
    #endif
    
      cloud_api_init();
    
    #if defined(CONFIG_USE_UI_MODULE)
      ui_init(ui_evt_handler);
    #endif
      work_init();
    
      while (modem_configure() != 0) {
        LOG_WRN("Failed to establish LTE connection.");
        LOG_WRN("Will retry in %d seconds.", CONFIG_CLOUD_CONNECT_RETRY_DELAY);
        k_sleep(K_SECONDS(CONFIG_CLOUD_CONNECT_RETRY_DELAY));
      }
    
    #if defined(CONFIG_LWM2M_CARRIER)
      LOG_INF("Waiting for LWM2M carrier to complete initialization...");
      k_sem_take(&cloud_ready_to_connect, K_FOREVER);
    #endif
    
      connect_to_cloud(0);
    }
    SRAM_23LC.h is:-
    /*
     * Driver for Microchip Technology Inc. 23LC (23LCV) SPI SRAM chips for
     * AVR, SAM3X (Due), and SAM M0+ (SAMD, SAML, SAMC) microcontrollers
     *
     * Copyright (c) 2017-2019, Justin Mattair ([email protected])
     *
     * Permission to use, copy, modify, and distribute this software
     * and its documentation for any purpose and without fee is hereby
     * granted, provided that the above copyright notice appear in all
     * copies and that both that the copyright notice and this
     * permission notice and warranty disclaimer appear in supporting
     * documentation, and that the name of the author not be used in
     * advertising or publicity pertaining to distribution of the
     * software without specific, written prior permission.
     *
     * The author disclaim all warranties with regard to this
     * software, including all implied warranties of merchantability
     * and fitness.  In no event shall the author be liable for any
     * special, indirect or consequential damages or any damages
     * whatsoever resulting from loss of use, data or profits, whether
     * in an action of contract, negligence or other tortious action,
     * arising out of or in connection with the use or performance of
     * this software.
     */
    
    #ifndef SRAM_23LC_h_
    #define SRAM_23LC_h_
    
    //#include "Arduino.h"
    //#include <SPI.h>
    #include "z_cart_helper.h"
    
    #define USE_SX1509_RAM_CS 0
    
    #if USE_SX1509_RAM_CS
    #include "zSX1509.h"
    #else
    #include <drivers/gpio.h>
    #endif
    
    #include <drivers/spi.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <zephyr.h>
    
    //#if (!defined(SPI_HAS_TRANSACTION) || SPI_HAS_TRANSACTION == 0)
    //#error "SRAM_23LC library requires SPI library transaction support (SPI_HAS_TRANSACTION = 1)"
    //#endif
    
    typedef enum _SRAM_23LC_Device {
      // 128KB
      SRAM_23LCV1024 = 0,
      SRAM_23LC1024,
      SRAM_23A1024,
      // 64KB
      SRAM_23LCV512,
      SRAM_23LC512,
      SRAM_23A512,
      // 32KB
      SRAM_23A256,
      SRAM_23K256,
      // 8KB
      SRAM_23A640,
      SRAM_23K640,
    } SRAM_23LC_Device;
    
    #define SRAM_CAPACITY_23LCV1024 0x20000
    #define SRAM_CAPACITY_23LC1024 0x20000
    #define SRAM_CAPACITY_23A1024 0x20000
    #define SRAM_CAPACITY_23LCV512 0x10000
    #define SRAM_CAPACITY_23LC512 0x10000
    #define SRAM_CAPACITY_23A512 0x10000
    #define SRAM_CAPACITY_23A256 0x8000
    #define SRAM_CAPACITY_23K256 0x8000
    #define SRAM_CAPACITY_23A640 0x2000
    #define SRAM_CAPACITY_23K640 0x2000
    
    #define SRAM_23LC_ADDRESS_16BIT 0
    #define SRAM_23LC_ADDRESS_24BIT 1
    
    #define SRAM_23LC_DUMMY_BYTE 0xFF
    
    // Commands supported by all chips
    #define SRAM_23LC_COMMAND_READ 0x03
    #define SRAM_23LC_COMMAND_WRITE 0x02
    #define SRAM_23LC_COMMAND_RDMR 0x05
    #define SRAM_23LC_COMMAND_WRMR 0x01
    
    // Additional commands supported by some chips
    #define SRAM_23LC_COMMAND_EDIO 0x3B
    #define SRAM_23LC_COMMAND_EQIO 0x38
    #define SRAM_23LC_COMMAND_RSTIO 0xFF
    
    typedef union {
      struct {
        uint8_t MODE : 2;
        uint8_t : 6;  // reserved
      } bit;
      uint32_t word;
    } SRAM_23LC_Mode_Register;
    
    #define SRAM_23LC_MODE_Pos 6
    #define SRAM_23LC_MODE_Msk (0x3ul << SRAM_23LC_MODE_Pos)
    #define SRAM_23LC_MODE(value) (SRAM_23LC_MODE_Msk & ((value) << SRAM_23LC_MODE_Pos))
    #define SRAM_23LC_MODE_BYTE_Val 0x0ul
    #define SRAM_23LC_MODE_SEQUENTIAL_Val 0x1ul
    #define SRAM_23LC_MODE_PAGE_Val 0x2ul
    #define SRAM_23LC_MODE_BYTE (SRAM_23LC_MODE_BYTE_Val << SRAM_23LC_MODE_Pos)
    #define SRAM_23LC_MODE_SEQUENTIAL (SRAM_23LC_MODE_SEQUENTIAL_Val << SRAM_23LC_MODE_Pos)
    #define SRAM_23LC_MODE_PAGE (SRAM_23LC_MODE_PAGE_Val << SRAM_23LC_MODE_Pos)
    
    class SRAM_23LC {
     public:
      SRAM_23LC(struct device *spi, const uint8_t chipSelect, const SRAM_23LC_Device device);
      // SRAM_23LC(SPIClass * spi, const uint8_t chipSelect, const SRAM_23LC_Device device);
    
      void begin(void);
      void begin(const uint32_t clkSpeed);
      void end(void);
    
      // uint8_t getMode(void);
      // void setMode(uint8_t mode);
    
      uint8_t readByte(const uint32_t address);
      size_t writeByte(const uint32_t address, const uint8_t byte);
    
      size_t readBlock(const uint32_t address, const size_t length, void *buffer);
      size_t writeBlock(const uint32_t address, const size_t length, void *buffer);
    
      void startCommand(const uint8_t command, const uint32_t address);
      void endCommand(void);
      void spi_endTransaction(void);                          // end transaction
      int spiWriteByte(uint8_t val);                          // hpm write a byte
      int spiReadByte(uint8_t dummy);                         // hpm read bytes. max is set at 32 bytes
      int spiReadBlock(uint8_t *buffer, size_t length);       // read bytes
      int spiWriteBlock(uint8_t *buffer, size_t length);      // write bytes
      int spiRamWriteReadTest();  // test as per SRAM_Example.ino
     protected:
     private:
      struct device *_spi;
    #if USE_SX1509_RAM_CS
      SX1509 ioExtend1;
    #else
      struct device *_gpio;
    #endif
      struct spi_config _spiSettings = {};
      SRAM_23LC_Device _device;
      uint32_t _capacity;
      uint8_t _chipSelect;
      uint32_t _clkSpeed;
      //following tx and rx details need to be shifted once working as expected.
      uint8_t tx_buffer[33];
      uint8_t rx_buffer[33];
      struct spi_buf tx_buf = {.buf = tx_buffer, .len = sizeof(tx_buffer)};
      struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1};
    
      struct spi_buf rx_buf = {
          .buf = rx_buffer,
          .len = sizeof(rx_buffer),
      };
      struct spi_buf_set rx = {.buffers = &rx_buf, .count = 1};
    
    
      void sendAddressBytes(const uint32_t address);
    };
    
    #endif
    
    and SRAM_23LC.cpp is :-
    /*
     * Driver for Microchip Technology Inc. 23LC (23LCV) SPI SRAM chips for
     * AVR, SAM3X (Due), and SAM M0+ (SAMD, SAML, SAMC) microcontrollers
     *
     * Copyright (c) 2017, Justin Mattair ([email protected])
     *
     * Permission to use, copy, modify, and distribute this software
     * and its documentation for any purpose and without fee is hereby
     * granted, provided that the above copyright notice appear in all
     * copies and that both that the copyright notice and this
     * permission notice and warranty disclaimer appear in supporting
     * documentation, and that the name of the author not be used in
     * advertising or publicity pertaining to distribution of the
     * software without specific, written prior permission.
     *
     * The author disclaim all warranties with regard to this
     * software, including all implied warranties of merchantability
     * and fitness.  In no event shall the author be liable for any
     * special, indirect or consequential damages or any damages
     * whatsoever resulting from loss of use, data or profits, whether
     * in an action of contract, negligence or other tortious action,
     * arising out of or in connection with the use or performance of
     * this software.
     */
    
    #include "SRAM_23LC.h"
    
    #include <logging/log.h>
    
    #include <cstring>
    LOG_MODULE_REGISTER(SRAM_23LC, LOG_LEVEL_DBG);
    
    SRAM_23LC::SRAM_23LC(struct device *spi, const uint8_t chipSelect, const SRAM_23LC_Device device) {
      LOG_DBG("Called");
    
      if ((device == SRAM_23LCV1024) || (device == SRAM_23LC1024) || (device == SRAM_23A1024)) {
        _capacity = 0x20000;
      } else if ((device == SRAM_23LCV512) || (device == SRAM_23LC512) || (device == SRAM_23A512)) {
        _capacity = 0x10000;
      } else if ((device == SRAM_23A256) || (device == SRAM_23K256)) {
        _capacity = 0x8000;
      } else if ((device == SRAM_23A640) || (device == SRAM_23K640)) {
        _capacity = 0x2000;
      }
    
      _device = device;
      _spi = spi;
      _chipSelect = chipSelect;
      _spiSettings.operation = SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE;
      _spiSettings.frequency = SPI3_FREQ_HZ;
      _spiSettings.slave = 0;
      //_spiSettings = SPISettings();	// use default settings
    }
    
    void SRAM_23LC::begin(void) {
      LOG_DBG("called no options");
    #if defined(ARDUINO_ARCH_SAMD)
      begin(12000000UL);
    #elif defined(ARDUINO_ARCH_AVR)
      begin(4000000UL);
    #elif defined(ARDUINO_ARCH_SAM)
      begin(14000000UL);
    #else
      begin(SPI3_FREQ_HZ);
    #endif
    }
    
    void SRAM_23LC::begin(const uint32_t clkSpeed) {
      LOG_DBG("Called");
      // clear out buffers and defined
      memset(rx_buffer, 0, 32);
      memset(tx_buffer, 0, 32);
    
    #if USE_SX1509_RAM_CS
      // set up the SX1509. It should be already setup. so no reset.
      ioExtend1.begin(SX1509_1_ADDRESS, 0xff, 0);
      ioExtend1.pinMode(_chipSelect, OUTPUT);
      ioExtend1.digitalWrite(_chipSelect, HIGH);
      k_msleep(10);
      LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
    #else
      _gpio = device_get_binding(LABEL_GPIO_0);
      gpio_pin_configure(_gpio, _chipSelect, GPIO_OUTPUT_ACTIVE);
      gpio_pin_set(_gpio, _chipSelect, 1);  // just to ensure it is high.
    #endif
    
      // _spi contains the binding to the SPI device
      // set up the SPI
      _clkSpeed = clkSpeed;
      _spiSettings.frequency = _clkSpeed;
      _spiSettings.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
      _spiSettings.slave = 0;
    
      //_spiSettings = SPISettings(_clkSpeed, MSBFIRST, SPI_MODE0);
      // SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE;
      //_spi->begin();
      // LOG_DBG("Step 01");
      startCommand(SRAM_23LC_COMMAND_WRMR, 0);
      spiWriteByte(SRAM_23LC_MODE_SEQUENTIAL);
      //_spi->transfer(SRAM_23LC_MODE_SEQUENTIAL);
      endCommand();
    }
    
    void SRAM_23LC::end(void) {
      // nothing to do at the moment
      // later might need to unasssign the _chipSelect;
      // pinMode(_chipSelect, INPUT);
    }
    
    uint8_t SRAM_23LC::readByte(const uint32_t address) {
      if (address >= _capacity) {
        return (0);
      }
      startCommand(SRAM_23LC_COMMAND_READ, address);
      spiReadByte(SRAM_23LC_DUMMY_BYTE);
      // uint8_t ret = _spi->transfer(SRAM_23LC_DUMMY_BYTE);
      endCommand();
    
      return rx_buffer[0];
    }  // end of readByte
    
    size_t SRAM_23LC::writeByte(const uint32_t address, const uint8_t byte) {
      if (address >= _capacity) {
        LOG_DBG("ERROR address above capacity");
        return (1);
      }
    
      startCommand(SRAM_23LC_COMMAND_WRITE, address);
      // LOG_DBG("called to write byte 0x%02x", byte);
      int rc = spiWriteByte(byte);
      // LOG_DBG("spiWriteByte RC is %d", rc);
      //_spi->transfer(byte);
      endCommand();
      return (rc);
    }
    
    size_t SRAM_23LC::readBlock(const uint32_t address, const size_t length, void *buffer) {
      if (address >= _capacity || length == 0) {
        return (0);
      }
    
      startCommand(SRAM_23LC_COMMAND_READ, address);
      spiReadBlock((uint8_t *)buffer, length);
      //_spi->transfer(buffer, length);
      endCommand();
    
      return (length);
    }
    
    size_t SRAM_23LC::writeBlock(const uint32_t address, const size_t length, void *buffer) {
      uint8_t *buf = reinterpret_cast<uint8_t *>(buffer);
      size_t len = length;
    
      if (address >= _capacity || length == 0) {
        return (0);
      }
    
      startCommand(SRAM_23LC_COMMAND_WRITE, address);
    
      while (len--) {
        spiWriteByte(*buf);
        buf++;
      }
    
      //  while (len--) {
      //    _spi->transfer(*buf);
      //    buf++;
      //  }
    
      endCommand();
    
      return (length);
    }
    
    void SRAM_23LC::startCommand(const uint8_t command, const uint32_t address) {
      // LOG_DBG("Called");
    //_spi->beginTransaction(_spiSettings);
    #if USE_SX1509_RAM_CS
      // LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
      ioExtend1.digitalWrite(_chipSelect, 0);
      // LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
    #else
      gpio_pin_set(_gpio, _chipSelect, 0);
    #endif
    
      int rc = 0;
      // LOG_DBG("Step00");
      rc = spiWriteByte(command);
      if (rc) {
        LOG_DBG("ERROR spiWriteByte rc is %d", rc);
      }
      // LOG_DBG("Step01 rc is %d", rc);
      //_spi->transfer(command);
      if (command == SRAM_23LC_COMMAND_READ || command == SRAM_23LC_COMMAND_WRITE) {
        sendAddressBytes(address);
      }
    }
    
    void SRAM_23LC::sendAddressBytes(const uint32_t address) {
      // LOG_DBG("Called");
      int rc = 0;
      if (_capacity > 0x10000) {
        rc = spiWriteByte((uint8_t)((address >> 16) & 0xFF));
        //_spi->transfer((uint8_t)((address >> 16) & 0xFF));
        // LOG_DBG("STEP00 rc is %d", rc);
      }
      if (rc) {
        LOG_DBG("ERROR step 0 rc is %d", rc);
      }
      rc = spiWriteByte((uint8_t)((address >> 8) & 0xFF));
      if (rc) {
        LOG_DBG("ERROR step 1 rc is %d", rc);
      }
      //_spi->transfer((uint8_t)((address >> 8) & 0xFF));
      rc = spiWriteByte((uint8_t)(address & 0xFF));
      if (rc) {
        LOG_DBG("ERROR step 2 rc is %d", rc);
      }
      //_spi->transfer((uint8_t)(address & 0xFF));
    }
    
    void SRAM_23LC::endCommand(void) {
      // LOG_DBG("called");
    #if USE_SX1509_RAM_CS
      // LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
      ioExtend1.digitalWrite(_chipSelect, 1);  //
    #else
      gpio_pin_set(_gpio, _chipSelect, 1);
    #endif
      spi_endTransaction();
      //_spi->endTransaction();
    }
    
    int SRAM_23LC::spiWriteByte(uint8_t val) {
      // LOG_DBG("Called to write %d", val);
      tx_buffer[0] = val;
      tx_buf.len = 1;
      int rc = spi_write(_spi, &_spiSettings, &tx);
      if (rc) {
        LOG_WRN("ERROR spi_write rc is %d", rc);
      }
    
      return rc;
    
    }  // end of spiWriteByte
    
    int SRAM_23LC::spiReadByte(const uint8_t dummy) {
      // LOG_DBG("Called");
      int rc = 0;
      // sends dummy so we get the read
      tx_buffer[0] = dummy;
      tx_buf.len = 1;
      rx_buffer[0] = 0xfe;  // testing. to make sure the read overrites this.
      rx_buf.len = 1;
      rc = spi_transceive(_spi, &_spiSettings, &tx, &rx);  // now rx_buffer[0] shoudl contain the read value
      if (rc) {
        LOG_WRN("ERROR spi_transceive rc is %d", rc);
      }
      return rc;
    }  // end of spiReadByte
    
    // write a block of data. currently limited to 32 bytes
    int SRAM_23LC::spiWriteBlock(uint8_t *buffer, size_t length) {
      // tx_buffer = memc;
      if (length > 32) {
        length = 32;
      }
      memcpy(tx_buffer, buffer, length);
      tx_buf.len = length;
    
      return spi_write(_spi, &_spiSettings, &tx);
    };  // end of spiWriteBlock
    
    // read a block of data. currently limited to 32 bytes
    int SRAM_23LC::spiReadBlock(uint8_t *buffer, size_t length) {
      if (length > 32) {
        length = 32;
      }
      rx_buf.len = length;
      tx_buf.len = length;
    
      int rc = spi_read(_spi, &_spiSettings, &rx);
      memcpy(buffer, tx_buffer, length);
      return rc;
    };  // end of spiReadBlock
    
    void SRAM_23LC::spi_endTransaction(void) {
      // do nothing for now.
      // need to invoke int spi_release(structdevice *dev, conststructspi_config *config) ????????
    }
    
    int SRAM_23LC::spiRamWriteReadTest() {
    #define TEST_RAM_START_ADDR 250
      LOG_DBG("called");
      char buffer[] =
          "The MattairTech MT-D21E is a development board for the 32-pin Microchip / Atmel SAMx21E ARM Cortex M0+ microcontrollers. Choose "
          "between the D21E, L21E, or C21E. Arduino compatible core files for all 3 chips is provided.";
      size_t buffer_size = (sizeof(buffer) / sizeof(uint8_t));
      char temp_buffer[buffer_size];
      memcpy(&temp_buffer[0], &buffer[0], buffer_size);
      LOG_DBG("called");
    
      // Print buffer to serial monitor
      printk("Write Block: ");
      for (size_t i = 0; i < buffer_size; i++) {
        printk("%c", temp_buffer[i]);
      }
      printk("\n");
    
      // Write block
      if (!writeBlock(TEST_RAM_START_ADDR, buffer_size, buffer)) {
        printk("Write Block Failure\n");
      } else {
        printk("Write Block Success\n");
      }
    
      // Clear buffer
      memset(&buffer[0], 0, buffer_size);
    
      // Read Byte, print to serial monitor
      printk("Read Byte:  ");
      for (size_t i = 0; i < buffer_size; i++) {
        buffer[i] = readByte(TEST_RAM_START_ADDR + i);
        printk("0x%02x ", buffer[i]);
      }
      printk("\n");
    
      // copy buffer
      memcpy(&buffer[0], &temp_buffer[0], buffer_size);
    
      // Write Byte, print to serial monitor
      // Write Byte, print to serial monitor
      printk("Write Byte:  ");
      for (size_t i = 0; i < buffer_size; i++) {
        printk("%c", buffer[i]);
        writeByte(TEST_RAM_START_ADDR + i, buffer[i]);
      }
      printk("\n");
    
      // Clear buffer
      memset(&buffer[0], 0, buffer_size);
    
      // Read Byte, print to serial monitor
      // Clear buffer
      memset(&buffer[0], 1, buffer_size);
      printk("Read Byte:  ");
      for (size_t i = 0; i < buffer_size; i++) {
        buffer[i] = readByte(TEST_RAM_START_ADDR + i);
        printk("0x%02x ", buffer[i]);
      }
      printk("\n");
    
      // Read block
      memset(&buffer[0], 1, buffer_size);
      if (!readBlock(TEST_RAM_START_ADDR, buffer_size, buffer)) {
        printk("Read Block Failure\n");
      } else {
        printk("Read Block Success\n");
      }
      printk("Read Block:  ");
    
      for (size_t i = 0; i < buffer_size; i++) {
        printk("0x%02x ", buffer[i]);
      }
      printk("\n");
    
      memset(&buffer[0], 1, buffer_size);
      // Print buffer to serial monitor
      size_t len = 0;
      printk("Read Rx_buffer:  ");
      if (buffer_size > 32) {
        len = 32;
      } else {
        len = buffer_size;
      }
      for (size_t i = 0; i < len; i++) {
        printk("0x%02x ", rx_buffer[i]);
      }
      printk("\n");
      return 0;
    }
    
    in z_cart_helper.h we have (what relevant):- 
    #define GPIO_SPIRAM_CS 13 // D5 External SPIRAM chip selection
    // SPI . currently we have spi_3
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_0), okay)
    #define LABEL_SPI0 DT_LABEL(DT_ALIAS(spi_0))
    #endif
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_1), okay)
    #define LABEL_SPI1 DT_LABEL(DT_ALIAS(spi_1))
    #endif
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_2), okay)
    #define LABEL_SPI2 DT_LABEL(DT_ALIAS(spi_2))
    #endif
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_3), okay)
    #define LABEL_SPI3 DT_LABEL(DT_ALIAS(spi_3))
    #endif
    #define SPI3_FREQ_HZ 2000000UL
    And finally proj.conf:-
    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
    #
    # General config
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    CONFIG_ASSERT=y
    CONFIG_REBOOT=y
    
    #Zevice cpp
    CONFIG_CPLUSPLUS=y # should now be able to programm in c++
    CONFIG_LIB_CPLUSPLUS=y # Link with STD C++ library
    CONFIG_STD_CPP17=y # to say we are programming to this standard 
    
    #log
    CONFIG_LOG=y
    # if you have lo_immediate it will cause problems with interrupts, isr and callbacks.
    CONFIG_LOG_IMMEDIATE=y
    
    # Network
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=n
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_OFFLOAD=y
    
    # LTE link control
    CONFIG_POWER_OPTIMIZATION_ENABLE=n
    CONFIG_LTE_LINK_CONTROL=y
    CONFIG_LTE_NETWORK_MODE_LTE_M_GPS=y
    CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
    CONFIG_LTE_LINK_CONTROL_LOG_LEVEL_DBG=y
    
    CONFIG_LTE_NETWORK_MODE_NBIOT_GPS=n
    CONFIG_LTE_LEGACY_PCO_MODE=n
    CONFIG_LTE_PSM_REQ_RPTAU="00000110"
    CONFIG_LTE_PSM_REQ_RAT="00000010"
    
    # Modem info
    CONFIG_MODEM_INFO=y
    
    # BSD library
    CONFIG_BSD_LIBRARY=y
    CONFIG_BSD_LIBRARY_TRACE_ENABLED=n
    
    # nRF Cloud
    CONFIG_CLOUD_API=y
    CONFIG_NRF_CLOUD=y
    CONFIG_NRF_CLOUD_LOG_LEVEL_DBG=y
    CONFIG_NRF_CLOUD_AGPS=y
    CONFIG_NRF_CLOUD_CONNECTION_POLL_THREAD=y
    CONFIG_NRF_CLOUD_NONBLOCKING_SEND=y
    # Needed for the cloud codec
    CONFIG_CJSON_LIB=y
    # Shorter to prevent NAT timeouts
    CONFIG_MQTT_KEEPALIVE=120
    # Don't resubscribe to topics if broker remembers them
    CONFIG_CLOUD_PERSISTENT_SESSIONS=y
    
    # Sensors
    CONFIG_ACCEL_USE_SIM=y
    CONFIG_TEMP_USE_SIM=y
    CONFIG_CLOUD_BUTTON=n
    
    # GPS
    CONFIG_NRF9160_GPS=y
    # CONFIG_GPS_USE_SIM=y
    CONFIG_NRF9160_GPS_LOG_LEVEL_DBG=y
    CONFIG_GPS_USE_EXTERNAL=y
    CONFIG_GPS_DEV_NAME="NRF9160_GPS"
    CONFIG_GPS_CONTROL_PSM_ENABLE_ON_START=y
    
    CONFIG_GPS_CONTROL_FIRST_FIX_CHECK_DELAY=10
    CONFIG_GPS_CONTROL_FIX_CHECK_INTERVAL=30
    CONFIG_GPS_CONTROL_FIX_TRY_TIME=360
    CONFIG_GPS_CONTROL_PSM_DISABLE_ON_STOP=n
    
    # Library for buttons and LEDs
    CONFIG_DK_LIBRARY=y
    CONFIG_DK_LIBRARY_INVERT_LEDS=n
    
    # Console
    CONFIG_CONSOLE_SUBSYS=y
    CONFIG_CONSOLE_HANDLER=y
    CONFIG_CONSOLE_GETCHAR=y
    # Zevice Console
    CONFIG_UART_CONSOLE_ON_DEV_NAME="UART_0"
    
    # Heap and stacks
    CONFIG_HEAP_MEM_POOL_SIZE=16384
    CONFIG_MAIN_STACK_SIZE=8192
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    CONFIG_HW_STACK_PROTECTION=y
    
    # MCUBOOT
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_IMG_MANAGER=y
    CONFIG_MCUBOOT_IMG_MANAGER=y
    
    # Flash
    CONFIG_FLASH=y
    CONFIG_IMG_ERASE_PROGRESSIVELY=y
    
    # AWS FOTA
    CONFIG_AWS_FOTA=y
    CONFIG_FOTA_DOWNLOAD=y
    CONFIG_AWS_FOTA_LOG_LEVEL_DBG=y
    CONFIG_AWS_JOBS_LOG_LEVEL_DBG=y
    CONFIG_DFU_TARGET=y
    
    # Download client (needed by AWS FOTA)
    CONFIG_DOWNLOAD_CLIENT=y
    CONFIG_DOWNLOAD_CLIENT_STACK_SIZE=4096
    
    # Fatal error
    CONFIG_RESET_ON_FATAL_ERROR=n
    CONFIG_WATCHDOG=y
    
    #Zevice SPI 
    #SPI_3 enabled by default. 
    
    
    #Zevice I2C
    # IC2
    CONFIG_I2C=y
    
    #Zevice SPI
    # SPI
    #SPI_3 should already be enabled by default.
    #overlay changes pins to 10,11,12
    CONFIG_SPI=y
    CONFIG_SPI_3=y
    #CONFIG_SPI_3_NRF_SPIM=y
    #CONFIG_SPI_3=y 
    CONFIG_SPI_NRFX=y
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=16
    #CONFIG_SPI=y
    #CONFIG_SPI_ASYNC=y
    #CONFIG_SPI_LOG_LEVEL_INF=y
    # SPI
    #CONFIG_SPI=y
    #CONFIG_SPI_3=y
    #CONFIG_SPI_3_NRF_SPIM=y
    #CONFIG_SPI_3=y 
    #CONFIG_SPI_NRFX=y
    #CONFIG_MAIN_STACK_SIZE=4096
    
    #Zevice adc
    CONFIG_ADC=y
    CONFIG_ADC_ASYNC=y
    
    # Zevice shell and RTT
    #CONFIG_RTT_CONSOLE=y
    #CONFIG_USE_SEGGER_RTT=y
    # CONFIG_UART_CONSOLE=n
    
    # Zevice shell
    CONFIG_SHELL=y
    CONFIG_UART_SHELL_ON_DEV_NAME="UART_1"
    CONFIG_SHELL_PROMPT_UART="zevice uart:~$ "
    CONFIG_SHELL_STACK_SIZE=4096
    CONFIG_KERNEL_SHELL=y
    # CONFIG_DEVICE_SHELL=y
    # CONFIG_GPIO_SHELL=y
    # CONFIG_I2C_SHELL=n
    #CONFIG_ADC_SHELL=y
    # CONFIG_SENSOR_SHELL=y
    # CONFIG_SHELL_BACKEND_RTT=y
    #CONFIG_SHELL_BACKENDS=y
    # CONFIG_SHELL_PROMPT_RTT="rtt:~$ "
    # CONFIG_RTT_
    # CONFIG_SHELL_BACKENDS=y # Enable shell backends.
    # CONFIG_SHELL_STACK_SIZE=2048
    # CONFIG_SHELL_PROMPT_UART="zevice uarts:~$ "
    # CONFIG_DEVICE_SHELL=y
    # CONFIG_GPIO_SHELL=y
    # CONFIG_SENSOR_SHELL=y
    # CONFIG_DATE_SHELL=y
    
    # CONFIG_SHELL_BACKEND_RTT=y
    
    # CONFIG_SHELL_BACKEND_SERIAL=y
    # CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=y
    # CONFIG_SHELL_BACKEND_RTT=y
    
    # CONFIG_SHELL=y
    #CONFIG_SHELL_PROMPT_UART="zevice uart:~$ "
    #CONFIG_KERNEL_SHELL=y
    #CONFIG_ADC_SHELL=y
    
    Ideally would like to read and write a byte and to read and write variable length bytes. Currently I have limited it to about 32 bytes.
    Again, really appreciate you skills in getting this prob fixed. Slight smile
Reply
  • Heidi,

    Thanks and apologies for the delay in responding. Been trying to get the code readable again.

    I have tried many many variations, different spi configs, etc... Even trying in pure c.

    Looked everywhere for a comprehensive zephyr nordic SPI example to work off, with no success.

    Using the nrf9160dk and using Asset Tracker app as the base.

    The overlay file (nrf9160dk_nrf9160ns.overlay) in my project boards directory is currently:-

    &spi3 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    sck-pin = <10>;
    mosi-pin = <11>;
    miso-pin = <12>;
    };

    Main.cpp is:-
    // use this main for testing only. For production reinstate main.cppkeep
    
    #include <stddef.h>
    #include <iostream>
    #include "asset_tracker.h"
    
    // spi test
    #include <drivers/gpio.h>
    #include <drivers/spi.h>
    #include <string.h>
    #include <z_cart_helper.h>
    
    #include "SRAM_23LC.h"
    //#include <nrfx_spim.h>
    
    //#include "zSX1509.h"
    // SX1509 ioExtend1;
    
    void main(void) {
      // test SPI and spi_SRAM
      struct device* spi_dev;
      const char* const spiName = "SPI_3";
      spi_dev = device_get_binding(spiName);
      if (spi_dev == NULL) {
        printk("Could not get SPI %s device\n", spiName);
        return;
      }
    
    /* Device can be:
     * 128KB: SRAM_23LCV1024, SRAM_23LC1024, SRAM_23A1024
     * 64KB: SRAM_23LCV512, SRAM_23LC512, SRAM_23A512
     * 32KB: SRAM_23A256, SRAM_23K256
     * 8KB: SRAM_23A640, SRAM_23K640
     */
    #if USE_SX1509_RAM_CS
      SRAM_23LC SRAM(spi_dev, SX15091_IO05_SPIRAM_CS, SRAM_23LCV1024);
    #else
      SRAM_23LC SRAM(spi_dev, GPIO_SPIRAM_CS, SRAM_23LCV1024);
    #endif
    
    SRAM.begin(2000000);
    SRAM.spiRamWriteReadTest();
    k_msleep(1000);
    
      // testeigen1();
      // test_eigen2();
    
      // test to execute shell command
      // k_msleep(10);
      // it works here but leaves user on prompt and mixed message
      // shell_execute_cmd(shell_backend_uart_get_ptr(), "user version");
      // shell_execute_cmd(shell_backend_rtt_get_ptr(), "user version");
    
      k_work_q_start(&application_work_q, application_stack_area, K_THREAD_STACK_SIZEOF(application_stack_area),
                     CONFIG_APPLICATION_WORKQUEUE_PRIORITY);
      if (IS_ENABLED(CONFIG_WATCHDOG)) {
        watchdog_init_and_start(&application_work_q);
      }
    
    #if defined(CONFIG_LWM2M_CARRIER)
      k_sem_take(&bsdlib_initialized, K_FOREVER);
    #else
      handle_bsdlib_init_ret();
    #endif
    
      cloud_api_init();
    
    #if defined(CONFIG_USE_UI_MODULE)
      ui_init(ui_evt_handler);
    #endif
      work_init();
    
      while (modem_configure() != 0) {
        LOG_WRN("Failed to establish LTE connection.");
        LOG_WRN("Will retry in %d seconds.", CONFIG_CLOUD_CONNECT_RETRY_DELAY);
        k_sleep(K_SECONDS(CONFIG_CLOUD_CONNECT_RETRY_DELAY));
      }
    
    #if defined(CONFIG_LWM2M_CARRIER)
      LOG_INF("Waiting for LWM2M carrier to complete initialization...");
      k_sem_take(&cloud_ready_to_connect, K_FOREVER);
    #endif
    
      connect_to_cloud(0);
    }
    SRAM_23LC.h is:-
    /*
     * Driver for Microchip Technology Inc. 23LC (23LCV) SPI SRAM chips for
     * AVR, SAM3X (Due), and SAM M0+ (SAMD, SAML, SAMC) microcontrollers
     *
     * Copyright (c) 2017-2019, Justin Mattair ([email protected])
     *
     * Permission to use, copy, modify, and distribute this software
     * and its documentation for any purpose and without fee is hereby
     * granted, provided that the above copyright notice appear in all
     * copies and that both that the copyright notice and this
     * permission notice and warranty disclaimer appear in supporting
     * documentation, and that the name of the author not be used in
     * advertising or publicity pertaining to distribution of the
     * software without specific, written prior permission.
     *
     * The author disclaim all warranties with regard to this
     * software, including all implied warranties of merchantability
     * and fitness.  In no event shall the author be liable for any
     * special, indirect or consequential damages or any damages
     * whatsoever resulting from loss of use, data or profits, whether
     * in an action of contract, negligence or other tortious action,
     * arising out of or in connection with the use or performance of
     * this software.
     */
    
    #ifndef SRAM_23LC_h_
    #define SRAM_23LC_h_
    
    //#include "Arduino.h"
    //#include <SPI.h>
    #include "z_cart_helper.h"
    
    #define USE_SX1509_RAM_CS 0
    
    #if USE_SX1509_RAM_CS
    #include "zSX1509.h"
    #else
    #include <drivers/gpio.h>
    #endif
    
    #include <drivers/spi.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <zephyr.h>
    
    //#if (!defined(SPI_HAS_TRANSACTION) || SPI_HAS_TRANSACTION == 0)
    //#error "SRAM_23LC library requires SPI library transaction support (SPI_HAS_TRANSACTION = 1)"
    //#endif
    
    typedef enum _SRAM_23LC_Device {
      // 128KB
      SRAM_23LCV1024 = 0,
      SRAM_23LC1024,
      SRAM_23A1024,
      // 64KB
      SRAM_23LCV512,
      SRAM_23LC512,
      SRAM_23A512,
      // 32KB
      SRAM_23A256,
      SRAM_23K256,
      // 8KB
      SRAM_23A640,
      SRAM_23K640,
    } SRAM_23LC_Device;
    
    #define SRAM_CAPACITY_23LCV1024 0x20000
    #define SRAM_CAPACITY_23LC1024 0x20000
    #define SRAM_CAPACITY_23A1024 0x20000
    #define SRAM_CAPACITY_23LCV512 0x10000
    #define SRAM_CAPACITY_23LC512 0x10000
    #define SRAM_CAPACITY_23A512 0x10000
    #define SRAM_CAPACITY_23A256 0x8000
    #define SRAM_CAPACITY_23K256 0x8000
    #define SRAM_CAPACITY_23A640 0x2000
    #define SRAM_CAPACITY_23K640 0x2000
    
    #define SRAM_23LC_ADDRESS_16BIT 0
    #define SRAM_23LC_ADDRESS_24BIT 1
    
    #define SRAM_23LC_DUMMY_BYTE 0xFF
    
    // Commands supported by all chips
    #define SRAM_23LC_COMMAND_READ 0x03
    #define SRAM_23LC_COMMAND_WRITE 0x02
    #define SRAM_23LC_COMMAND_RDMR 0x05
    #define SRAM_23LC_COMMAND_WRMR 0x01
    
    // Additional commands supported by some chips
    #define SRAM_23LC_COMMAND_EDIO 0x3B
    #define SRAM_23LC_COMMAND_EQIO 0x38
    #define SRAM_23LC_COMMAND_RSTIO 0xFF
    
    typedef union {
      struct {
        uint8_t MODE : 2;
        uint8_t : 6;  // reserved
      } bit;
      uint32_t word;
    } SRAM_23LC_Mode_Register;
    
    #define SRAM_23LC_MODE_Pos 6
    #define SRAM_23LC_MODE_Msk (0x3ul << SRAM_23LC_MODE_Pos)
    #define SRAM_23LC_MODE(value) (SRAM_23LC_MODE_Msk & ((value) << SRAM_23LC_MODE_Pos))
    #define SRAM_23LC_MODE_BYTE_Val 0x0ul
    #define SRAM_23LC_MODE_SEQUENTIAL_Val 0x1ul
    #define SRAM_23LC_MODE_PAGE_Val 0x2ul
    #define SRAM_23LC_MODE_BYTE (SRAM_23LC_MODE_BYTE_Val << SRAM_23LC_MODE_Pos)
    #define SRAM_23LC_MODE_SEQUENTIAL (SRAM_23LC_MODE_SEQUENTIAL_Val << SRAM_23LC_MODE_Pos)
    #define SRAM_23LC_MODE_PAGE (SRAM_23LC_MODE_PAGE_Val << SRAM_23LC_MODE_Pos)
    
    class SRAM_23LC {
     public:
      SRAM_23LC(struct device *spi, const uint8_t chipSelect, const SRAM_23LC_Device device);
      // SRAM_23LC(SPIClass * spi, const uint8_t chipSelect, const SRAM_23LC_Device device);
    
      void begin(void);
      void begin(const uint32_t clkSpeed);
      void end(void);
    
      // uint8_t getMode(void);
      // void setMode(uint8_t mode);
    
      uint8_t readByte(const uint32_t address);
      size_t writeByte(const uint32_t address, const uint8_t byte);
    
      size_t readBlock(const uint32_t address, const size_t length, void *buffer);
      size_t writeBlock(const uint32_t address, const size_t length, void *buffer);
    
      void startCommand(const uint8_t command, const uint32_t address);
      void endCommand(void);
      void spi_endTransaction(void);                          // end transaction
      int spiWriteByte(uint8_t val);                          // hpm write a byte
      int spiReadByte(uint8_t dummy);                         // hpm read bytes. max is set at 32 bytes
      int spiReadBlock(uint8_t *buffer, size_t length);       // read bytes
      int spiWriteBlock(uint8_t *buffer, size_t length);      // write bytes
      int spiRamWriteReadTest();  // test as per SRAM_Example.ino
     protected:
     private:
      struct device *_spi;
    #if USE_SX1509_RAM_CS
      SX1509 ioExtend1;
    #else
      struct device *_gpio;
    #endif
      struct spi_config _spiSettings = {};
      SRAM_23LC_Device _device;
      uint32_t _capacity;
      uint8_t _chipSelect;
      uint32_t _clkSpeed;
      //following tx and rx details need to be shifted once working as expected.
      uint8_t tx_buffer[33];
      uint8_t rx_buffer[33];
      struct spi_buf tx_buf = {.buf = tx_buffer, .len = sizeof(tx_buffer)};
      struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1};
    
      struct spi_buf rx_buf = {
          .buf = rx_buffer,
          .len = sizeof(rx_buffer),
      };
      struct spi_buf_set rx = {.buffers = &rx_buf, .count = 1};
    
    
      void sendAddressBytes(const uint32_t address);
    };
    
    #endif
    
    and SRAM_23LC.cpp is :-
    /*
     * Driver for Microchip Technology Inc. 23LC (23LCV) SPI SRAM chips for
     * AVR, SAM3X (Due), and SAM M0+ (SAMD, SAML, SAMC) microcontrollers
     *
     * Copyright (c) 2017, Justin Mattair ([email protected])
     *
     * Permission to use, copy, modify, and distribute this software
     * and its documentation for any purpose and without fee is hereby
     * granted, provided that the above copyright notice appear in all
     * copies and that both that the copyright notice and this
     * permission notice and warranty disclaimer appear in supporting
     * documentation, and that the name of the author not be used in
     * advertising or publicity pertaining to distribution of the
     * software without specific, written prior permission.
     *
     * The author disclaim all warranties with regard to this
     * software, including all implied warranties of merchantability
     * and fitness.  In no event shall the author be liable for any
     * special, indirect or consequential damages or any damages
     * whatsoever resulting from loss of use, data or profits, whether
     * in an action of contract, negligence or other tortious action,
     * arising out of or in connection with the use or performance of
     * this software.
     */
    
    #include "SRAM_23LC.h"
    
    #include <logging/log.h>
    
    #include <cstring>
    LOG_MODULE_REGISTER(SRAM_23LC, LOG_LEVEL_DBG);
    
    SRAM_23LC::SRAM_23LC(struct device *spi, const uint8_t chipSelect, const SRAM_23LC_Device device) {
      LOG_DBG("Called");
    
      if ((device == SRAM_23LCV1024) || (device == SRAM_23LC1024) || (device == SRAM_23A1024)) {
        _capacity = 0x20000;
      } else if ((device == SRAM_23LCV512) || (device == SRAM_23LC512) || (device == SRAM_23A512)) {
        _capacity = 0x10000;
      } else if ((device == SRAM_23A256) || (device == SRAM_23K256)) {
        _capacity = 0x8000;
      } else if ((device == SRAM_23A640) || (device == SRAM_23K640)) {
        _capacity = 0x2000;
      }
    
      _device = device;
      _spi = spi;
      _chipSelect = chipSelect;
      _spiSettings.operation = SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE;
      _spiSettings.frequency = SPI3_FREQ_HZ;
      _spiSettings.slave = 0;
      //_spiSettings = SPISettings();	// use default settings
    }
    
    void SRAM_23LC::begin(void) {
      LOG_DBG("called no options");
    #if defined(ARDUINO_ARCH_SAMD)
      begin(12000000UL);
    #elif defined(ARDUINO_ARCH_AVR)
      begin(4000000UL);
    #elif defined(ARDUINO_ARCH_SAM)
      begin(14000000UL);
    #else
      begin(SPI3_FREQ_HZ);
    #endif
    }
    
    void SRAM_23LC::begin(const uint32_t clkSpeed) {
      LOG_DBG("Called");
      // clear out buffers and defined
      memset(rx_buffer, 0, 32);
      memset(tx_buffer, 0, 32);
    
    #if USE_SX1509_RAM_CS
      // set up the SX1509. It should be already setup. so no reset.
      ioExtend1.begin(SX1509_1_ADDRESS, 0xff, 0);
      ioExtend1.pinMode(_chipSelect, OUTPUT);
      ioExtend1.digitalWrite(_chipSelect, HIGH);
      k_msleep(10);
      LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
    #else
      _gpio = device_get_binding(LABEL_GPIO_0);
      gpio_pin_configure(_gpio, _chipSelect, GPIO_OUTPUT_ACTIVE);
      gpio_pin_set(_gpio, _chipSelect, 1);  // just to ensure it is high.
    #endif
    
      // _spi contains the binding to the SPI device
      // set up the SPI
      _clkSpeed = clkSpeed;
      _spiSettings.frequency = _clkSpeed;
      _spiSettings.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
      _spiSettings.slave = 0;
    
      //_spiSettings = SPISettings(_clkSpeed, MSBFIRST, SPI_MODE0);
      // SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE;
      //_spi->begin();
      // LOG_DBG("Step 01");
      startCommand(SRAM_23LC_COMMAND_WRMR, 0);
      spiWriteByte(SRAM_23LC_MODE_SEQUENTIAL);
      //_spi->transfer(SRAM_23LC_MODE_SEQUENTIAL);
      endCommand();
    }
    
    void SRAM_23LC::end(void) {
      // nothing to do at the moment
      // later might need to unasssign the _chipSelect;
      // pinMode(_chipSelect, INPUT);
    }
    
    uint8_t SRAM_23LC::readByte(const uint32_t address) {
      if (address >= _capacity) {
        return (0);
      }
      startCommand(SRAM_23LC_COMMAND_READ, address);
      spiReadByte(SRAM_23LC_DUMMY_BYTE);
      // uint8_t ret = _spi->transfer(SRAM_23LC_DUMMY_BYTE);
      endCommand();
    
      return rx_buffer[0];
    }  // end of readByte
    
    size_t SRAM_23LC::writeByte(const uint32_t address, const uint8_t byte) {
      if (address >= _capacity) {
        LOG_DBG("ERROR address above capacity");
        return (1);
      }
    
      startCommand(SRAM_23LC_COMMAND_WRITE, address);
      // LOG_DBG("called to write byte 0x%02x", byte);
      int rc = spiWriteByte(byte);
      // LOG_DBG("spiWriteByte RC is %d", rc);
      //_spi->transfer(byte);
      endCommand();
      return (rc);
    }
    
    size_t SRAM_23LC::readBlock(const uint32_t address, const size_t length, void *buffer) {
      if (address >= _capacity || length == 0) {
        return (0);
      }
    
      startCommand(SRAM_23LC_COMMAND_READ, address);
      spiReadBlock((uint8_t *)buffer, length);
      //_spi->transfer(buffer, length);
      endCommand();
    
      return (length);
    }
    
    size_t SRAM_23LC::writeBlock(const uint32_t address, const size_t length, void *buffer) {
      uint8_t *buf = reinterpret_cast<uint8_t *>(buffer);
      size_t len = length;
    
      if (address >= _capacity || length == 0) {
        return (0);
      }
    
      startCommand(SRAM_23LC_COMMAND_WRITE, address);
    
      while (len--) {
        spiWriteByte(*buf);
        buf++;
      }
    
      //  while (len--) {
      //    _spi->transfer(*buf);
      //    buf++;
      //  }
    
      endCommand();
    
      return (length);
    }
    
    void SRAM_23LC::startCommand(const uint8_t command, const uint32_t address) {
      // LOG_DBG("Called");
    //_spi->beginTransaction(_spiSettings);
    #if USE_SX1509_RAM_CS
      // LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
      ioExtend1.digitalWrite(_chipSelect, 0);
      // LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
    #else
      gpio_pin_set(_gpio, _chipSelect, 0);
    #endif
    
      int rc = 0;
      // LOG_DBG("Step00");
      rc = spiWriteByte(command);
      if (rc) {
        LOG_DBG("ERROR spiWriteByte rc is %d", rc);
      }
      // LOG_DBG("Step01 rc is %d", rc);
      //_spi->transfer(command);
      if (command == SRAM_23LC_COMMAND_READ || command == SRAM_23LC_COMMAND_WRITE) {
        sendAddressBytes(address);
      }
    }
    
    void SRAM_23LC::sendAddressBytes(const uint32_t address) {
      // LOG_DBG("Called");
      int rc = 0;
      if (_capacity > 0x10000) {
        rc = spiWriteByte((uint8_t)((address >> 16) & 0xFF));
        //_spi->transfer((uint8_t)((address >> 16) & 0xFF));
        // LOG_DBG("STEP00 rc is %d", rc);
      }
      if (rc) {
        LOG_DBG("ERROR step 0 rc is %d", rc);
      }
      rc = spiWriteByte((uint8_t)((address >> 8) & 0xFF));
      if (rc) {
        LOG_DBG("ERROR step 1 rc is %d", rc);
      }
      //_spi->transfer((uint8_t)((address >> 8) & 0xFF));
      rc = spiWriteByte((uint8_t)(address & 0xFF));
      if (rc) {
        LOG_DBG("ERROR step 2 rc is %d", rc);
      }
      //_spi->transfer((uint8_t)(address & 0xFF));
    }
    
    void SRAM_23LC::endCommand(void) {
      // LOG_DBG("called");
    #if USE_SX1509_RAM_CS
      // LOG_DBG("pin is %d", ioExtend1.digitalRead(_chipSelect));
      ioExtend1.digitalWrite(_chipSelect, 1);  //
    #else
      gpio_pin_set(_gpio, _chipSelect, 1);
    #endif
      spi_endTransaction();
      //_spi->endTransaction();
    }
    
    int SRAM_23LC::spiWriteByte(uint8_t val) {
      // LOG_DBG("Called to write %d", val);
      tx_buffer[0] = val;
      tx_buf.len = 1;
      int rc = spi_write(_spi, &_spiSettings, &tx);
      if (rc) {
        LOG_WRN("ERROR spi_write rc is %d", rc);
      }
    
      return rc;
    
    }  // end of spiWriteByte
    
    int SRAM_23LC::spiReadByte(const uint8_t dummy) {
      // LOG_DBG("Called");
      int rc = 0;
      // sends dummy so we get the read
      tx_buffer[0] = dummy;
      tx_buf.len = 1;
      rx_buffer[0] = 0xfe;  // testing. to make sure the read overrites this.
      rx_buf.len = 1;
      rc = spi_transceive(_spi, &_spiSettings, &tx, &rx);  // now rx_buffer[0] shoudl contain the read value
      if (rc) {
        LOG_WRN("ERROR spi_transceive rc is %d", rc);
      }
      return rc;
    }  // end of spiReadByte
    
    // write a block of data. currently limited to 32 bytes
    int SRAM_23LC::spiWriteBlock(uint8_t *buffer, size_t length) {
      // tx_buffer = memc;
      if (length > 32) {
        length = 32;
      }
      memcpy(tx_buffer, buffer, length);
      tx_buf.len = length;
    
      return spi_write(_spi, &_spiSettings, &tx);
    };  // end of spiWriteBlock
    
    // read a block of data. currently limited to 32 bytes
    int SRAM_23LC::spiReadBlock(uint8_t *buffer, size_t length) {
      if (length > 32) {
        length = 32;
      }
      rx_buf.len = length;
      tx_buf.len = length;
    
      int rc = spi_read(_spi, &_spiSettings, &rx);
      memcpy(buffer, tx_buffer, length);
      return rc;
    };  // end of spiReadBlock
    
    void SRAM_23LC::spi_endTransaction(void) {
      // do nothing for now.
      // need to invoke int spi_release(structdevice *dev, conststructspi_config *config) ????????
    }
    
    int SRAM_23LC::spiRamWriteReadTest() {
    #define TEST_RAM_START_ADDR 250
      LOG_DBG("called");
      char buffer[] =
          "The MattairTech MT-D21E is a development board for the 32-pin Microchip / Atmel SAMx21E ARM Cortex M0+ microcontrollers. Choose "
          "between the D21E, L21E, or C21E. Arduino compatible core files for all 3 chips is provided.";
      size_t buffer_size = (sizeof(buffer) / sizeof(uint8_t));
      char temp_buffer[buffer_size];
      memcpy(&temp_buffer[0], &buffer[0], buffer_size);
      LOG_DBG("called");
    
      // Print buffer to serial monitor
      printk("Write Block: ");
      for (size_t i = 0; i < buffer_size; i++) {
        printk("%c", temp_buffer[i]);
      }
      printk("\n");
    
      // Write block
      if (!writeBlock(TEST_RAM_START_ADDR, buffer_size, buffer)) {
        printk("Write Block Failure\n");
      } else {
        printk("Write Block Success\n");
      }
    
      // Clear buffer
      memset(&buffer[0], 0, buffer_size);
    
      // Read Byte, print to serial monitor
      printk("Read Byte:  ");
      for (size_t i = 0; i < buffer_size; i++) {
        buffer[i] = readByte(TEST_RAM_START_ADDR + i);
        printk("0x%02x ", buffer[i]);
      }
      printk("\n");
    
      // copy buffer
      memcpy(&buffer[0], &temp_buffer[0], buffer_size);
    
      // Write Byte, print to serial monitor
      // Write Byte, print to serial monitor
      printk("Write Byte:  ");
      for (size_t i = 0; i < buffer_size; i++) {
        printk("%c", buffer[i]);
        writeByte(TEST_RAM_START_ADDR + i, buffer[i]);
      }
      printk("\n");
    
      // Clear buffer
      memset(&buffer[0], 0, buffer_size);
    
      // Read Byte, print to serial monitor
      // Clear buffer
      memset(&buffer[0], 1, buffer_size);
      printk("Read Byte:  ");
      for (size_t i = 0; i < buffer_size; i++) {
        buffer[i] = readByte(TEST_RAM_START_ADDR + i);
        printk("0x%02x ", buffer[i]);
      }
      printk("\n");
    
      // Read block
      memset(&buffer[0], 1, buffer_size);
      if (!readBlock(TEST_RAM_START_ADDR, buffer_size, buffer)) {
        printk("Read Block Failure\n");
      } else {
        printk("Read Block Success\n");
      }
      printk("Read Block:  ");
    
      for (size_t i = 0; i < buffer_size; i++) {
        printk("0x%02x ", buffer[i]);
      }
      printk("\n");
    
      memset(&buffer[0], 1, buffer_size);
      // Print buffer to serial monitor
      size_t len = 0;
      printk("Read Rx_buffer:  ");
      if (buffer_size > 32) {
        len = 32;
      } else {
        len = buffer_size;
      }
      for (size_t i = 0; i < len; i++) {
        printk("0x%02x ", rx_buffer[i]);
      }
      printk("\n");
      return 0;
    }
    
    in z_cart_helper.h we have (what relevant):- 
    #define GPIO_SPIRAM_CS 13 // D5 External SPIRAM chip selection
    // SPI . currently we have spi_3
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_0), okay)
    #define LABEL_SPI0 DT_LABEL(DT_ALIAS(spi_0))
    #endif
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_1), okay)
    #define LABEL_SPI1 DT_LABEL(DT_ALIAS(spi_1))
    #endif
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_2), okay)
    #define LABEL_SPI2 DT_LABEL(DT_ALIAS(spi_2))
    #endif
    #if DT_NODE_HAS_STATUS(DT_ALIAS(spi_3), okay)
    #define LABEL_SPI3 DT_LABEL(DT_ALIAS(spi_3))
    #endif
    #define SPI3_FREQ_HZ 2000000UL
    And finally proj.conf:-
    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
    #
    # General config
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    CONFIG_ASSERT=y
    CONFIG_REBOOT=y
    
    #Zevice cpp
    CONFIG_CPLUSPLUS=y # should now be able to programm in c++
    CONFIG_LIB_CPLUSPLUS=y # Link with STD C++ library
    CONFIG_STD_CPP17=y # to say we are programming to this standard 
    
    #log
    CONFIG_LOG=y
    # if you have lo_immediate it will cause problems with interrupts, isr and callbacks.
    CONFIG_LOG_IMMEDIATE=y
    
    # Network
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=n
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_OFFLOAD=y
    
    # LTE link control
    CONFIG_POWER_OPTIMIZATION_ENABLE=n
    CONFIG_LTE_LINK_CONTROL=y
    CONFIG_LTE_NETWORK_MODE_LTE_M_GPS=y
    CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
    CONFIG_LTE_LINK_CONTROL_LOG_LEVEL_DBG=y
    
    CONFIG_LTE_NETWORK_MODE_NBIOT_GPS=n
    CONFIG_LTE_LEGACY_PCO_MODE=n
    CONFIG_LTE_PSM_REQ_RPTAU="00000110"
    CONFIG_LTE_PSM_REQ_RAT="00000010"
    
    # Modem info
    CONFIG_MODEM_INFO=y
    
    # BSD library
    CONFIG_BSD_LIBRARY=y
    CONFIG_BSD_LIBRARY_TRACE_ENABLED=n
    
    # nRF Cloud
    CONFIG_CLOUD_API=y
    CONFIG_NRF_CLOUD=y
    CONFIG_NRF_CLOUD_LOG_LEVEL_DBG=y
    CONFIG_NRF_CLOUD_AGPS=y
    CONFIG_NRF_CLOUD_CONNECTION_POLL_THREAD=y
    CONFIG_NRF_CLOUD_NONBLOCKING_SEND=y
    # Needed for the cloud codec
    CONFIG_CJSON_LIB=y
    # Shorter to prevent NAT timeouts
    CONFIG_MQTT_KEEPALIVE=120
    # Don't resubscribe to topics if broker remembers them
    CONFIG_CLOUD_PERSISTENT_SESSIONS=y
    
    # Sensors
    CONFIG_ACCEL_USE_SIM=y
    CONFIG_TEMP_USE_SIM=y
    CONFIG_CLOUD_BUTTON=n
    
    # GPS
    CONFIG_NRF9160_GPS=y
    # CONFIG_GPS_USE_SIM=y
    CONFIG_NRF9160_GPS_LOG_LEVEL_DBG=y
    CONFIG_GPS_USE_EXTERNAL=y
    CONFIG_GPS_DEV_NAME="NRF9160_GPS"
    CONFIG_GPS_CONTROL_PSM_ENABLE_ON_START=y
    
    CONFIG_GPS_CONTROL_FIRST_FIX_CHECK_DELAY=10
    CONFIG_GPS_CONTROL_FIX_CHECK_INTERVAL=30
    CONFIG_GPS_CONTROL_FIX_TRY_TIME=360
    CONFIG_GPS_CONTROL_PSM_DISABLE_ON_STOP=n
    
    # Library for buttons and LEDs
    CONFIG_DK_LIBRARY=y
    CONFIG_DK_LIBRARY_INVERT_LEDS=n
    
    # Console
    CONFIG_CONSOLE_SUBSYS=y
    CONFIG_CONSOLE_HANDLER=y
    CONFIG_CONSOLE_GETCHAR=y
    # Zevice Console
    CONFIG_UART_CONSOLE_ON_DEV_NAME="UART_0"
    
    # Heap and stacks
    CONFIG_HEAP_MEM_POOL_SIZE=16384
    CONFIG_MAIN_STACK_SIZE=8192
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    CONFIG_HW_STACK_PROTECTION=y
    
    # MCUBOOT
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_IMG_MANAGER=y
    CONFIG_MCUBOOT_IMG_MANAGER=y
    
    # Flash
    CONFIG_FLASH=y
    CONFIG_IMG_ERASE_PROGRESSIVELY=y
    
    # AWS FOTA
    CONFIG_AWS_FOTA=y
    CONFIG_FOTA_DOWNLOAD=y
    CONFIG_AWS_FOTA_LOG_LEVEL_DBG=y
    CONFIG_AWS_JOBS_LOG_LEVEL_DBG=y
    CONFIG_DFU_TARGET=y
    
    # Download client (needed by AWS FOTA)
    CONFIG_DOWNLOAD_CLIENT=y
    CONFIG_DOWNLOAD_CLIENT_STACK_SIZE=4096
    
    # Fatal error
    CONFIG_RESET_ON_FATAL_ERROR=n
    CONFIG_WATCHDOG=y
    
    #Zevice SPI 
    #SPI_3 enabled by default. 
    
    
    #Zevice I2C
    # IC2
    CONFIG_I2C=y
    
    #Zevice SPI
    # SPI
    #SPI_3 should already be enabled by default.
    #overlay changes pins to 10,11,12
    CONFIG_SPI=y
    CONFIG_SPI_3=y
    #CONFIG_SPI_3_NRF_SPIM=y
    #CONFIG_SPI_3=y 
    CONFIG_SPI_NRFX=y
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=16
    #CONFIG_SPI=y
    #CONFIG_SPI_ASYNC=y
    #CONFIG_SPI_LOG_LEVEL_INF=y
    # SPI
    #CONFIG_SPI=y
    #CONFIG_SPI_3=y
    #CONFIG_SPI_3_NRF_SPIM=y
    #CONFIG_SPI_3=y 
    #CONFIG_SPI_NRFX=y
    #CONFIG_MAIN_STACK_SIZE=4096
    
    #Zevice adc
    CONFIG_ADC=y
    CONFIG_ADC_ASYNC=y
    
    # Zevice shell and RTT
    #CONFIG_RTT_CONSOLE=y
    #CONFIG_USE_SEGGER_RTT=y
    # CONFIG_UART_CONSOLE=n
    
    # Zevice shell
    CONFIG_SHELL=y
    CONFIG_UART_SHELL_ON_DEV_NAME="UART_1"
    CONFIG_SHELL_PROMPT_UART="zevice uart:~$ "
    CONFIG_SHELL_STACK_SIZE=4096
    CONFIG_KERNEL_SHELL=y
    # CONFIG_DEVICE_SHELL=y
    # CONFIG_GPIO_SHELL=y
    # CONFIG_I2C_SHELL=n
    #CONFIG_ADC_SHELL=y
    # CONFIG_SENSOR_SHELL=y
    # CONFIG_SHELL_BACKEND_RTT=y
    #CONFIG_SHELL_BACKENDS=y
    # CONFIG_SHELL_PROMPT_RTT="rtt:~$ "
    # CONFIG_RTT_
    # CONFIG_SHELL_BACKENDS=y # Enable shell backends.
    # CONFIG_SHELL_STACK_SIZE=2048
    # CONFIG_SHELL_PROMPT_UART="zevice uarts:~$ "
    # CONFIG_DEVICE_SHELL=y
    # CONFIG_GPIO_SHELL=y
    # CONFIG_SENSOR_SHELL=y
    # CONFIG_DATE_SHELL=y
    
    # CONFIG_SHELL_BACKEND_RTT=y
    
    # CONFIG_SHELL_BACKEND_SERIAL=y
    # CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=y
    # CONFIG_SHELL_BACKEND_RTT=y
    
    # CONFIG_SHELL=y
    #CONFIG_SHELL_PROMPT_UART="zevice uart:~$ "
    #CONFIG_KERNEL_SHELL=y
    #CONFIG_ADC_SHELL=y
    
    Ideally would like to read and write a byte and to read and write variable length bytes. Currently I have limited it to about 32 bytes.
    Again, really appreciate you skills in getting this prob fixed. Slight smile
Children
No Data
Related