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

Migrating a design from Raspberry pi Zero to nRF9160 DK - Need I2C and SPI interfaces

Hi,

I have developed a simple system based around a Raspberry Pi Zero. The system uses a couple of sensors to measure temperature and water pressure using a ADS51115 A/D and a MAX 31865 RTD to digital convertor. These connect to the Pi zero via the !2C bus and the SPI interface. I would like to replace the Pi zero with the nRF9160 dev board, can some one point me to some example hw and sw that will enable me to quickly convert. Thanks, Rod

Parents
  • Hi, 

    In order to use SPI and I2C peripherals, the following configurations can be placed in `prj.conf` to enable them and select the nrfx driver:

    CONFIG_I2C=y
    CONFIG_I2C_NRFX=y
    CONFIG_I2C_2=y
    CONFIG_I2C_2_NRF_TWIM=y

    CONFIG_SPI=y
    CONFIG_SPI_NRFX=y
    CONFIG_SPI_3=y
    CONFIG_SPI_3_NRF_SPIM=y

    This will enable I2C instance 2 and SPI instance 3, configure them to use nrfx driver. Note that these are the ones declared in the default secure boot to be available for a non-secure application:
    https://github.com/NordicPlayground/fw-nrfconnect-nrf/blob/master/samples/nrf9160/secure_boot/src/main.c#L321

    You can choose other instances as long as you also adjust which peripherals are set as non-secure.

    You then need to defined the peripherals in an overlay file for the board where you can set the pin numbers and clock speed. Name it `nrf9160_pca10090.overlay` and place it in the application folder. The contents of the file may be as follows:


    &i2c2 {
            status = "ok";
            sda-pin = <30>;
            scl-pin = <31>;
            clock-frequency = <I2C_BITRATE_FAST>;
    };

    &spi3 {
            status = "ok";
            sck-pin = <6>;
            mosi-pin = <7>;
            miso-pin = <8>;
            spi-max-frequency = <4000000>;
    };


    The devices get the labels "I2C_2" and "SPI_3" to be used in the `device_get_binding()` call, according to their instance numbers.

    When you have the configuration set, you will be able to use the generic I2C and SPI drivers in Zephyr, and can build use those samples and the API documentation as reference:

    I2C API:
    https://docs.zephyrproject.org/latest/api/io_interfaces.html?#i2c-interface

    SPI API:
    https://docs.zephyrproject.org/latest/api/io_interfaces.html?#spi-interface

    Samples:
    https://github.com/zephyrproject-rtos/zephyr/tree/master/samples/drivers 

  • Jan, thank you for your reply. A couple  of follow on questions.
    1. Am I correct in saying that I can assign any GPIO pins as SPI and I2C interfaces?
    2. As part of my development process, I want to phase in the replacement of the Raspberry Pi. In the next version on the prototype, I would like to keep the Pi zero and add the nRF9160DK effectively as a peripheral. 
    So, please can you advise how I can add the nRF9160DK as a peripheral to the Pi. Do I just connect over UART or can you suggest a better way?
  • Hi Jan,

    Replying to this as your latest comments don't have an associated reply button.

    Yes, I am connecting the BME280 to the 9160 DK. As per your previous reply, I created an overlay file, which I called nrf9160_pca10090.overlay and added the I2C and SPI code above.

    I then try to build this with the command

    cmake -GNinja -DSHIELD=nrf9160_pca10090 -DBOARD=nrf9160_pca10090 ..

    I get an error

    Zephyr version: 1.14.0

    -- Found PythonInterp: /usr/local/bin/python3 (found suitable version "3.7.3", minimum required is "3.4") 

    -- Selected BOARD nrf9160_pca10090

    No shield named 'nrf9160_pca10090' found

    So, are you suggesting that I create a shield called BME280.overlay which contain the I2C and SPI code above and then build using

    cmake -GNinja -DSHIELD=BME280 -DBOARD=nrf9160_pca10090 ..

    Regards,

    Rod

    Sorry, I thought I ad replied to this earlier, but my replay seems to have disappeared. 

  • Hi,

    I'd just remove the -DSHIELD altogether, as you've already added the BME280 to the PCA10090 overlay. You can also define which pins to use as shown in an earlier reply in this thread in that same overlay. The alternative is as you mention to add an overlay called bme280.overlay and set -DSHIELD=bme280.

    Regards,

    Jan Tore

  • Does this mean that, although NRF9160 has 4 SPI, 4 I2C and 4 UART on the datasheet, it is actually not the same as using 3X4=12 peripheral interfaces at the same time, and can only use 4 peripheral interfaces at most?

  • Hi,

    It means that a maximum of 4 of these serial instances can be used at the same time. However, the nrfx drivers have a feature called PRS (Peripheral Resource Sharing) that allows you to switch instances on and off runtime as you need them.

    Disclaimer: I have not used the PRS recently myself, and the below information is based on documentation. I'll update this comment when I get the chance to do a proper test and confim that the below information is correct.

    If you use nrfx drivers directly, this is achieved by enabling NRFX_PRS on the serial boxes where you want them, and then calling init()/uninit() functions beore and after transactions. Here's the API docs:
    https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.0/group__nrfx__prs.html

    ---

    Update: There is a mechanism in the device tree parsing that prevents multiple instances for the same serial box from being enabled at the same time, leaving the suggested workaround below unusable. I will check more in this and comment here when I have more information.


    If you are using NCS, and don't want to use nrfx drivers directly, but rather Zephyr's drivers, you will have to use the device power management features to switch an instance on and off (euivalent to calling init()/uninit()). I am not sure about the implications using PRS might have on device tree configuration, and how driver initialization in Zephyr works. I have not tested this myself.

    Here's documentation for the related Kconfigs:
    CONFIG_NRFX_PRS

    CONFIG_NRFX_PRS_BOX_0

    CONFIG_DEVICE_POWER_MANAGEMENT

    Docs on device power management is found here.

    To enable a peripheral, use DEVICE_PM_ACTIVE_STATE.

    To disable it, use on of these three states: DEVICE_PM_LOW_POWER_STATE, DEVICE_PM_SUSPEND_STATE or DEVICE_PM_OFF_STATE.

    Let us know if you run into any issues. 
    Best regards,
    Jan Tore
Reply
  • Hi,

    It means that a maximum of 4 of these serial instances can be used at the same time. However, the nrfx drivers have a feature called PRS (Peripheral Resource Sharing) that allows you to switch instances on and off runtime as you need them.

    Disclaimer: I have not used the PRS recently myself, and the below information is based on documentation. I'll update this comment when I get the chance to do a proper test and confim that the below information is correct.

    If you use nrfx drivers directly, this is achieved by enabling NRFX_PRS on the serial boxes where you want them, and then calling init()/uninit() functions beore and after transactions. Here's the API docs:
    https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.0/group__nrfx__prs.html

    ---

    Update: There is a mechanism in the device tree parsing that prevents multiple instances for the same serial box from being enabled at the same time, leaving the suggested workaround below unusable. I will check more in this and comment here when I have more information.


    If you are using NCS, and don't want to use nrfx drivers directly, but rather Zephyr's drivers, you will have to use the device power management features to switch an instance on and off (euivalent to calling init()/uninit()). I am not sure about the implications using PRS might have on device tree configuration, and how driver initialization in Zephyr works. I have not tested this myself.

    Here's documentation for the related Kconfigs:
    CONFIG_NRFX_PRS

    CONFIG_NRFX_PRS_BOX_0

    CONFIG_DEVICE_POWER_MANAGEMENT

    Docs on device power management is found here.

    To enable a peripheral, use DEVICE_PM_ACTIVE_STATE.

    To disable it, use on of these three states: DEVICE_PM_LOW_POWER_STATE, DEVICE_PM_SUSPEND_STATE or DEVICE_PM_OFF_STATE.

    Let us know if you run into any issues. 
    Best regards,
    Jan Tore
Children
No Data
Related