0
\$\begingroup\$

I have 2 STM32F407 discovery boards for which I'm trying to setup a multi slave SPI bus. The first slave is working but the other one is making problems once I connect the second CLK input onto the BUS.

My setup looks like this: enter image description here

Here is the GPIO setup code for the master SPI:

static void intercom_init_gpio(void) {
    clock_enable_gpio(GPIOB);

    gpio_set_mode(GPIOB, 0, GPIO_MODE_OUTPUT); // CS
    gpio_set_mode(GPIOB, 1, GPIO_MODE_OUTPUT); // CS

    gpio_set_mode(GPIOB, 3, GPIO_MODE_AF); // SCK
    gpio_set_mode(GPIOB, 4, GPIO_MODE_AF); // MISO
    gpio_set_mode(GPIOB, 5, GPIO_MODE_AF); // MOSI

    gpio_set_output_speed(GPIOB, 0, GPIO_SPEED_HIGH);
    gpio_set_output_speed(GPIOB, 1, GPIO_SPEED_HIGH);
    gpio_set_output_speed(GPIOB, 3, GPIO_SPEED_HIGH);
    gpio_set_output_speed(GPIOB, 4, GPIO_SPEED_HIGH);
    gpio_set_output_speed(GPIOB, 5, GPIO_SPEED_HIGH);

    gpio_set_pull(GPIOB, 0, GPIO_PULL_UP);
    gpio_set_pull(GPIOB, 1, GPIO_PULL_UP);

    gpio_write(GPIOB, 0, 1);
    gpio_write(GPIOB, 1, 1);

    gpio_set_af(GPIOB, 3, 5);
    gpio_set_af(GPIOB, 4, 5);
    gpio_set_af(GPIOB, 5, 5);
}

And here is the GPIO setup code of the slave SPI:

static void intercom_init_gpio(void) {
    clock_enable_gpio(GPIOA);
    clock_enable_gpio(GPIOB);

    gpio_set_mode(GPIOA, 15, GPIO_MODE_AF); // NSS
    gpio_set_mode(GPIOB, 3, GPIO_MODE_AF); // SCK
    gpio_set_mode(GPIOB, 4, GPIO_MODE_AF); // MISO
    gpio_set_mode(GPIOB, 5, GPIO_MODE_AF); // MOSI

    gpio_set_mode(GPIOB, 12, GPIO_MODE_AF); // NSS
    gpio_set_mode(GPIOB, 13, GPIO_MODE_AF); // SCK
    gpio_set_mode(GPIOB, 14, GPIO_MODE_AF); // MISO
    gpio_set_mode(GPIOB, 15, GPIO_MODE_AF); // MOSI

    gpio_set_af(GPIOA, 15, 5);
    gpio_set_af(GPIOB, 3, 5);
    gpio_set_af(GPIOB, 4, 5);
    gpio_set_af(GPIOB, 5, 5);

    gpio_set_af(GPIOB, 12, 5);
    gpio_set_af(GPIOB, 13, 5);
    gpio_set_af(GPIOB, 14, 5);
    gpio_set_af(GPIOB, 15, 5);
}

Here is the SPI setup code for the master SPI:

static void intercom_init_spi(void) {
    clock_enable_spi(SPI1);

    spi_set_master_mode(SPI1);
    spi_set_clk_prescaler(SPI1, SPI_CLK_DIV256);
    spi_set_clk_phase(SPI1, SPI_CLK_PHASE_0);
    spi_set_clk_polarity(SPI1, SPI_CLK_POLARITY_0);
    spi_set_full_duplex(SPI1);
    spi_set_frame_format(SPI1, SPI_FRAME_FORMAT_LSBFIRST);
    spi_set_frame_size(SPI1, SPI_FRAME_SIZE_8);

    spi_enable(SPI1);
}

Here is the SPI setup code for the slave SPI:

static void intercom_init_spi(void) {
    clock_enable_spi(SPI1);
    clock_enable_spi(SPI2);

    spi_set_slave_mode(SPI1);
    spi_set_clk_prescaler(SPI1, SPI_CLK_DIV256);
    spi_set_clk_phase(SPI1, SPI_CLK_PHASE_0);
    spi_set_clk_polarity(SPI1, SPI_CLK_POLARITY_0);
    spi_set_full_duplex(SPI1);
    spi_set_frame_format(SPI1, SPI_FRAME_FORMAT_LSBFIRST);
    spi_set_frame_size(SPI1, SPI_FRAME_SIZE_8);

    spi_set_slave_mode(SPI2);
    spi_set_clk_prescaler(SPI2, SPI_CLK_DIV256);
    spi_set_clk_phase(SPI2, SPI_CLK_PHASE_0);
    spi_set_clk_polarity(SPI2, SPI_CLK_POLARITY_0);
    spi_set_full_duplex(SPI2);
    spi_set_frame_format(SPI2, SPI_FRAME_FORMAT_LSBFIRST);
    spi_set_frame_size(SPI2, SPI_FRAME_SIZE_8);

    vectors_register_isr(NVIC_SPI1_IRQ, intercom_spi1_handler);
    vectors_register_isr(NVIC_SPI2_IRQ, intercom_spi2_handler);

    vectors_enable_irq(NVIC_SPI1_IRQ);
    vectors_enable_irq(NVIC_SPI2_IRQ);

    spi_enable_rx_interrupt(SPI1);
    spi_enable_rx_interrupt(SPI2);

    spi_enable(SPI1);
    spi_enable(SPI2);
}

Here is the reset clock control configuration:

void clock_enable_gpio(gpio_t* gpio) {
    switch ((uint32_t)gpio) {
        case (uint32_t)GPIOA: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; break;
        case (uint32_t)GPIOB: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; break;
        case (uint32_t)GPIOC: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; break;
        case (uint32_t)GPIOD: RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; break;
        case (uint32_t)GPIOE: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; break;
        case (uint32_t)GPIOF: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOFEN; break;
        case (uint32_t)GPIOG: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN; break;
        case (uint32_t)GPIOH: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN; break;
        case (uint32_t)GPIOI: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN; break;
        case (uint32_t)GPIOJ: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOJEN; break;
        case (uint32_t)GPIOK: RCC->AHB1ENR |= RCC_AHB1ENR_GPIOKEN; break;
    }
}

void clock_enable_spi(spi_t* spi) {
    switch ((uint32_t)spi) {
        case (uint32_t)SPI1: RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; break;
        case (uint32_t)SPI2: RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; break;
        case (uint32_t)SPI3: RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; break;
        case (uint32_t)SPI4: RCC->APB2ENR |= RCC_APB2ENR_SPI4EN; break;
        case (uint32_t)SPI5: RCC->APB2ENR |= RCC_APB2ENR_SPI5EN; break;
        case (uint32_t)SPI6: RCC->APB2ENR |= RCC_APB2ENR_SPI6EN; break;
    }
}

Here are my peripherals:

#define GPIOA ((gpio_t*)0x40020000)
#define GPIOB ((gpio_t*)0x40020400)
#define GPIOC ((gpio_t*)0x40020800)
#define GPIOD ((gpio_t*)0x40020C00)
#define GPIOE ((gpio_t*)0x40021000)
#define GPIOF ((gpio_t*)0x40021400)
#define GPIOG ((gpio_t*)0x40021800)
#define GPIOH ((gpio_t*)0x40021C00)
#define GPIOI ((gpio_t*)0x40022000)
#define GPIOJ ((gpio_t*)0x40022400)
#define GPIOK ((gpio_t*)0x40022800)

#define SPI1 ((spi_t*)0x40013000)
#define SPI2 ((spi_t*)0x40003800)
#define SPI3 ((spi_t*)0x40003C00)
#define SPI4 ((spi_t*)0x40013400)
#define SPI5 ((spi_t*)0x40015000)
#define SPI6 ((spi_t*)0x40015400)

I have double and tripple checked my wiring and all GPIO functions. It should work and it does. I can transfer data between the master and the first slave, but once I additionally hook up the CLK pin from the second SPI suddenly nothing is working anymore... even my USART terminal isn't working anylonger.

I have also checked NSS/CLK/MISO/MOSI with my oscilloscope. For some reason MISO is continuously low. Everything else looks good to me.

How is this all possible?

\$\endgroup\$
4
  • \$\begingroup\$ Have you checked with the scope that only one slave is selected at a time (CS1 or CS2)? \$\endgroup\$
    – Paul
    Nov 22, 2023 at 14:53
  • \$\begingroup\$ Yes only one of the CSx is active at a time. After further debugging it seems my second SPI never worked. I have tested SPI2 and SPI3 but they don't work. The data on the oscilloscope is ok but the interrupt isn't firing. SPI1 with the same wiring is working like a charm on the other hand. \$\endgroup\$
    – Michael
    Nov 22, 2023 at 15:12
  • \$\begingroup\$ Have you check that all your peripherals are functional and are powered correctly ? I faced a similar issue on a board where one of the slaves was not powered \$\endgroup\$
    – BEN
    Nov 22, 2023 at 15:38
  • \$\begingroup\$ Well I have checked all of my peripherals RCC's. They all seem to be properly configured. I'll add the RCC configuration code in my question. I have also double checked all the enable bits. \$\endgroup\$
    – Michael
    Nov 22, 2023 at 16:28

1 Answer 1

0
\$\begingroup\$

I solved it, my GPIO alternating function configuration wasn't working properly... i forgot to subtract 8 on the high register which explains why SPI1 was working and the other two SPI2/SPI3 were not.

void gpio_set_af(gpio_t* gpio, uint32_t pin, uint8_t af) {
    if (pin < 8) {
        gpio->AFRL &= ~(0xF << (4 * pin));
        gpio->AFRL |= af << (4 * pin);
    } else {
        gpio->AFRH &= ~(0xF << (4 * (pin - 8)));
        gpio->AFRH |= af << (4 * (pin - 8));
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.