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.
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?