Which macro to get sck, mosi and miso pin on spi master

Hello,

I works with Zephyr, VCS, SDK 2.0.0

I don't find how to get pin number from the DTS pinctrl .

In this folowing code, I want to replace magic number (uplighted in yellow) by macro to acces data of the DTS 

Thank's by advance for your help,

    nrfx_spim_config_t spim_config = NRFX_SPIM_DEFAULT_CONFIG(NRFX_SPIM_PIN_NOT_USED,NRFX_SPIM_PIN_NOT_USED,NRFX_SPIM_PIN_NOT_USED,NRFX_SPIM_PIN_NOT_USED/*NRF_DT_GPIOS_TO_PSEL(SPIM_NODE, cs_gpios)*/);
    spim_config.sck_pin=6+32*1;
    spim_config.mosi_pin=7+32*1;
    spim_config.miso_pin=17+32*0;
    spim_config.frequency = NRF_SPIM_FREQ_1M;
    spim_config.skip_gpio_cfg = true;
    spim_config.skip_psel_cfg = false;
    nrfx_spim_init(&spi_rfid_instance, &spim_config, spi_rfid_handler, NULL);

And my DTS are

&spi1 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    pinctrl-0 = <&spi1_default>;
    pinctrl-1 = <&spi1_sleep>;
    pinctrl-names = "default", "sleep";
    //cs-gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
};

    spi1_default: spi1_default {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 6)>,
                <NRF_PSEL(SPIM_MOSI, 1, 7)>,
                <NRF_PSEL(SPIM_MISO, 0, 17)>;
        };
    };

    spi1_sleep: spi1_sleep {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 6)>,
                <NRF_PSEL(SPIM_MOSI, 1, 7)>,
                <NRF_PSEL(SPIM_MISO, 0, 17)>;
            low-power-enable;
        };
    };
  • Update 30.06.2022: Added strikethrough to an incorrect statement.

    I would recommend you to use the Zephyr API. Then the information specified in DTS will automatically get picked up by the SPI drivers without you needing to do anything. It is also much less complicated to use.

    However, you might have chosen to use the nrfx drivers for a specific reason, but I thought it would be nice to inform you in case you weren't aware.

    To answer your question, you could take a look at the file spi_nrfx_spim.c to see how to get the pin number from the DTS pinctrl (use DT_PROP_OR or DT_PROP macros)

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.0.99-ncs1/drivers/spi/spi_nrfx_spim.c#L487-L488

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.0.99-ncs1/drivers/spi/spi_nrfx_spim.c#L511-L515

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.0.99-ncs1/drivers/spi/spi_nrfx_spim.c#L510

    Best regards,

    Simon

  • Hello Simon,

    Thank you for your reply,
    I took your advice and it is all right with Zephyr API.

    Note that I have to add following properties in "zephyr/dts/bindings/spi/nordic,nrf-spim.yaml"

       spi-max-frequency:
          type: int
          required: false
          default: 4000000
          description: Maximum clock frequency of device's SPI interface in Hz
    
        duplex:
          type: int
          default: 0
          required: false
          description: |
            Duplex mode, full or half. By default it's always full duplex thus 0
            as this is, by far, the most common mode.
            Use the macros not the actual enum value, here is the concordance
            list (see dt-bindings/spi/spi.h)
              0    SPI_FULL_DUPLEX
              2048 SPI_HALF_DUPLEX
          enum:
            - 0
            - 2048
    
        frame-format:
          type: int
          default: 0
          required: false
          description: |
            Motorola or TI frame format. By default it's always Motorola's,
            thus 0 as this is, by far, the most common format.
            Use the macros not the actual enum value, here is the concordance
            list (see dt-bindings/spi/spi.h)
              0     SPI_FRAME_FORMAT_MOTOROLA
              32768 SPI_FRAME_FORMAT_TI
          enum:
            - 0
            - 32768
    

    WIthout that , SPI_CONFIG_DT fail .

    struct spi_dt_spec	spi_rfid={ 
    	.bus=DEVICE_DT_GET(SPI_RFID_NODE), 
    	.config=SPI_CONFIG_DT(SPI_RFID_NODE,SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_MODE_CPHA | SPI_MODE_CPOL,0),
    };
    

    Regards,

    Stéphane

  • To answer your original question (for cases like mine where I use PINCTRL but also had to use the NRFX SPI driver for one of my SPI peripherals in order to utilize PPI), I did not find any DT macros that would just do this. Understanding the Device Tree, you can use a combination of other macros to access pin info. Here's an example:

    dtsi file:

    ...    
        spi1_default: spi1_default {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 1, 9)>,
                        <NRF_PSEL(SPIM_MOSI, 1, 8)>,
                        <NRF_PSEL(SPIM_MISO, 0, 4)>;
            };
        };
    ...

    dts file:

    ...
    &spi1 {
        compatible = "nordic,nrf-spim";
        status = "okay";
        pinctrl-0 = <&spi1_default>;

        pinctrl-1 = <&spi1_sleep>;
        pinctrl-names = "default", "sleep";
        cs-gpios = <&gpio0 31 GPIO_ACTIVE_LOW>;
    };

    ...

    application:

    #define SPI_NODE DT_NODELABEL(spi1)
    #define SPI_PINCTRL_NODE DT_CHILD(DT_PINCTRL_0(SPI_NODE, 0), group1)

    Then in your SPI Configuration structure, you can grab the property like this:
    nrfx_spim_config_t xSpiConfig = {
    .sck_pin        = (uint8_t)DT_PROP_BY_IDX(SPI_PINCTRL_NODE, psels, 0) & 0x3F,
    .mosi_pin       = (uint8_t)DT_PROP_BY_IDX(SPI_PINCTRL_NODE, psels, 1) & 0x3F,
    .miso_pin       = (uint8_t)DT_PROP_BY_IDX(SPI_PINCTRL_NODE, psels, 2) & 0x3F,
    .ss_pin         = DT_GPIO_PIN_BY_IDX(SPI_NODE, cs_gpios, 0),
    ...

    The psel property will return a 32-bit configuration (defined in nrf-pinctrl.h), but you just need the first 6 bits.

    If anyone knows an easier way, please share. 

  • Hello Tristen,

    Interesting, thank you for you experience sharing.

    Stéphane

  • Hello Stéphane,

    It seems like I was wrong in my first reply. The spi_nrfx_spim.c will not use the DT_PROP macros to get the sck, mosi and miso pins when pinctrl is enabled due to this check. Instead it will configure it through pin_ctrl_apply_state()-->pin_ctrl_apply_state_direct()-->pin_ctrl_configure_pins()

    Please use the approach by Tristen instead:   RE: Which macro to get sck, mosi and miso pin on spi master  

    I will get back to you if I find a better approach

    Best regards,

    simon

Related