cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to configure hardware SPI 1

Amirreza
Associate

Hi I am trying to set up hardware SPI using the following. My software SPI works fine, but the hardware SPI doesn't even have a clock signal.

 
/**

******************************************************************************

* @file : main.c

* @brief : P7-SPI2: Two bursts, same 6 bytes. Burst1: SW SPI (PE2/PE6).

* Burst2: Hardware SPI1 (PA5/PA7). Probe D0=PE2, D1=PE6, D2=PA5, D3=PA7.

* HW SPI1: kernel clock per_ck, GPIO before SPI, CSTART errata workaround.

******************************************************************************

*/



#include <stdint.h>



#define RCC_AHB4ENR (*(volatile uint32_t *)0x580244E0u)

#define RCC_APB2ENR (*(volatile uint32_t *)0x580244F0u)

#define RCC_D2CCIP1R (*(volatile uint32_t *)0x58024450u)

#define GPIOA_MODER (*(volatile uint32_t *)0x58020000u)

#define GPIOA_AFRL (*(volatile uint32_t *)0x58020020u)

#define GPIOA_ODR (*(volatile uint32_t *)0x58020014u)

#define GPIOE_MODER (*(volatile uint32_t *)0x58021000u)

#define GPIOE_ODR (*(volatile uint32_t *)0x58021014u)



#define GPIOAEN (1u << 0)

#define GPIOEEN (1u << 4)

#define SPI1EN (1u << 12)



#define SW_SCK_PIN (1u << 2)

#define SW_MOSI_PIN (1u << 6)

#define PA_SCK_PIN (1u << 5)

#define PA_MOSI_PIN (1u << 7)



#define SW_SPI_DELAY 64u



/* ----- SPI1: P5/STM32H753xx style. CR1@0x00, CR2@0x04, CFG1@0x08, CFG2@0x0C, SR@0x14, TXDR@0x20, RXDR@0x30 ----- */

#define SPI1_BASE 0x40013000u

#define SPI1_CR1 (*(volatile uint32_t *)(SPI1_BASE + 0x00u))

#define SPI1_CR2 (*(volatile uint32_t *)(SPI1_BASE + 0x04u))

#define SPI1_CFG1 (*(volatile uint32_t *)(SPI1_BASE + 0x08u))

#define SPI1_CFG2 (*(volatile uint32_t *)(SPI1_BASE + 0x0Cu))

#define SPI1_SR (*(volatile uint32_t *)(SPI1_BASE + 0x14u))

#define SPI1_IFCR (*(volatile uint32_t *)(SPI1_BASE + 0x18u))

#define SPI1_TXDR8 (*(volatile uint8_t *)(SPI1_BASE + 0x20u))

#define SPI1_RXDR8 (*(volatile uint8_t *)(SPI1_BASE + 0x30u))



/* RM0433 50.11: CR1@0x00, CR2@0x04, CFG1@0x08. CFG1: MBR[30:28], FTHLV[8:5]=0 (1 frame), DSIZE[4:0]=7 (8-bit). */

#define SPI_CFG1_MBR_DIV16 (3u << 28)

#define SPI_CFG1_FTHLV_0 (0u << 5) /* 1 data frame per packet so TXP/RXWNE per byte */

#define SPI_CFG1_DSIZE_8BIT (7u << 0)

#define SPI_CFG2_MASTER (1u << 22)

#define SPI_CFG2_SSM (1u << 26)

#define SPI_CR1_SPE (1u << 0)

#define SPI_CR1_CSTART (1u << 9)

#define SPI_CR1_SSI (1u << 12)

#define SPI_SR_TXP (1u << 1)

#define SPI_SR_RXWNE (1u << 15)



static const uint8_t msg[] = { 0x55u, 0xAAu, 0xF0u, 0x0Fu, 0x12u, 0x34u };

#define MSG_LEN 6u



void SystemInit(void) { }



static void delay_cycles(volatile uint32_t n)

{

while (n--) { __asm volatile ("nop"); }

}



/* ----- Software SPI: PE2=SCK, PE6=MOSI ----- */

static void sw_spi_init(void)

{

RCC_AHB4ENR |= GPIOEEN;

(void)RCC_AHB4ENR;

GPIOE_MODER &= ~(3u << 4 | 3u << 12);

GPIOE_MODER |= (1u << 4) | (1u << 12);

GPIOE_ODR &= ~(SW_SCK_PIN | SW_MOSI_PIN);

}



static void sw_spi_send_byte(uint8_t tx)

{

int i;

for (i = 7; i >= 0; i--) {

if (tx & (1u << i))

GPIOE_ODR |= SW_MOSI_PIN;

else

GPIOE_ODR &= ~SW_MOSI_PIN;

delay_cycles(SW_SPI_DELAY);

GPIOE_ODR |= SW_SCK_PIN;

delay_cycles(SW_SPI_DELAY);

GPIOE_ODR &= ~SW_SCK_PIN;

delay_cycles(SW_SPI_DELAY);

}

}



/* ----- Burst2: bit-bang on PA5 (SCK), PA7 (MOSI). Same timing as burst1 so you see both on analyzer. ----- */

static void pa_bb_spi_init(void)

{

RCC_AHB4ENR |= GPIOAEN;

(void)RCC_AHB4ENR;

GPIOA_MODER &= ~(3u << 10 | 3u << 14);

GPIOA_MODER |= (1u << 10) | (1u << 14); /* PA5, PA7 output */

GPIOA_ODR &= ~(PA_SCK_PIN | PA_MOSI_PIN);

}



static void pa_bb_send_byte(uint8_t tx)

{

int i;

for (i = 7; i >= 0; i--) {

if (tx & (1u << i))

GPIOA_ODR |= PA_MOSI_PIN;

else

GPIOA_ODR &= ~PA_MOSI_PIN;

delay_cycles(SW_SPI_DELAY);

GPIOA_ODR |= PA_SCK_PIN;

delay_cycles(SW_SPI_DELAY);

GPIOA_ODR &= ~PA_SCK_PIN;

delay_cycles(SW_SPI_DELAY);

}

}



/* ----- Hardware SPI1: P5 layout, CSTART + TXDR/RXDR ----- */

static void spi1_wait_txp(void)

{

uint32_t t = 10000u;

while (!(SPI1_SR & SPI_SR_TXP) && t) { t--; }

}



static void spi1_wait_rxwne(void)

{

uint32_t t = 10000u;

while (!(SPI1_SR & SPI_SR_RXWNE) && t) { t--; }

}



/* 50.4.10: write TXDR then set CSTART. Errata: delay after EOT before next CSTART to avoid stall. */

static void hw_spi_send_byte(uint8_t tx)

{

spi1_wait_txp();

SPI1_TXDR8 = tx;

SPI1_CR1 |= SPI_CR1_CSTART;

spi1_wait_rxwne();

(void)SPI1_RXDR8;

delay_cycles(100u); /* errata: wait after EOT before next CSTART */

}



/* SPI1/2/3 kernel clock: 0=PLL1Q, 3=per_ck. Use per_ck when PLL not running. RM0433 RCC D2CCIP1R. */

#define SPI123SEL_PERCK (3u << 12)



static void hw_spi_init(void)

{

/* GPIO before SPI (required: AF must be set before enabling SPI). */

RCC_AHB4ENR |= GPIOAEN;

(void)RCC_AHB4ENR;

/* PA5=SCK, PA6=MISO, PA7=MOSI = AF5 for SPI1 */

GPIOA_MODER &= ~(3u << 10 | 3u << 12 | 3u << 14);

GPIOA_MODER |= (2u << 10 | 2u << 12 | 2u << 14);

GPIOA_AFRL &= ~(0xFFFu << 20);

GPIOA_AFRL |= (0x555u << 20);



RCC_APB2ENR |= SPI1EN;

RCC_D2CCIP1R = (RCC_D2CCIP1R & ~(7u << 12)) | SPI123SEL_PERCK;

(void)RCC_APB2ENR;



/* Config only writable when SPE=0. Do not set CSTART here; set it per transfer. */

SPI1_CR1 = 0u;

SPI1_IFCR = 0xFFFFFFFFu; /* clear status flags */

SPI1_CFG1 = SPI_CFG1_MBR_DIV16 | SPI_CFG1_FTHLV_0 | SPI_CFG1_DSIZE_8BIT;

SPI1_CFG2 = SPI_CFG2_MASTER | SPI_CFG2_SSM;

SPI1_CR2 = 0u; /* TSIZE=0: trigger by TXDR write + CSTART */

SPI1_CR1 = SPI_CR1_SPE | SPI_CR1_SSI;

}



int main(void)

{

uint32_t i;



sw_spi_init();

hw_spi_init(); /* burst2 = hardware SPI1 on PA5/PA7 */



for (;;) {

for (i = 0; i < MSG_LEN; i++)

sw_spi_send_byte(msg[i]);

delay_cycles(50000u);



for (i = 0; i < MSG_LEN; i++)

hw_spi_send_byte(msg[i]);

delay_cycles(500000u);

}

}

 

 

 

1 REPLY 1
gbm
Principal

1. Rewrite your code so that it uses standard peripheral, register and bit mask definition from stm32xxxx.h. Most of errors like yours origin from mistakes in non-standard user definitions.

2. Format your code using code tags </>

3. After you do the above, supply the most basic piece of information missing from your post - the MCU type.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice