cancel
Showing results for 
Search instead for 
Did you mean: 

[SOLVED] What could be wrong with my register based SPI transmitter conf?

Kura
Associate II

So problems with stm32h743VIT6 SPI TX.

No TXC/EOT -flag(s). No TX interrupts. No physical activity on pin side MOSI/SCK.

Like commented to code: I have tried so many variants of configurations (only master transmitters).

I feel I have tried all what I can try with information from RM, DS and errata SPI chapters.

Something is broken, is it my SW or HW?

Note: I deleted the LCD functions from code, so it contain only SPI test functionality. E.g the CMD definition is in header.

If someone can point direction, documentation chapter, some other reference or give a hand to solve this problem, so thank You in advance.

#include "stm32h743xx.h"
#include "st7789InitVal.h"
#include "stdbool.h"
#include "stdlib.h"
 
 
volatile uint64_t bufferCounter;
volatile static bool spiStatus;
 
 
 
void send(uint8_t data, uint8_t cmd);
void spiInit(void);
//void lcdInit(void);
//void setLcdWindow(void);
void delay(void);
void cmdPinInit(void);
 
int main(){
 
	cmdPinInit();
	spiInit();
	send(0xFF, 1);
	
	//lcdInit();
	//setLcdWindow();
	
 
	
	while(1){
		
	}
}
 
void send(uint8_t data, uint8_t cmd){
	
	spiStatus = false;
	
	// CMD defined in header 1/0
	// seems like this is the only successful event in this function
	if(cmd == CMD){
		GPIOA->BSRR |= GPIO_BSRR_BR2;
	} else {
		GPIOA->BSRR |= GPIO_BSRR_BS2;
	}
	
	
 
	
	SPI1->CR2 |= (SPI_CR2_TSIZE & sizeof(data));
	//SPI1->CR2 &= ~(SPI_CR2_TSIZE);
	
	SPI1->CR1 |= SPI_CR1_SPE;
 
	
	
/*
			
if SPI1->CR2 &= ~(SPI_CR2_TSIZE);
>> TXC flag = 1, so clear follow 
SPI1->IFCR |= SPI_IFCR_EOTC;
-Errata (2.12.4)
	
				
			
*/
	
	
	//SPI1->IFCR |= SPI_IFCR_EOTC;
	//NVIC_EnableIRQ(SPI1_IRQn);
	//*((volatile uint16_t*)&(SPI1->TXDR)) = data;
	// *((volatile uint8_t*)&SPI1->TXDR) = data;
	
	
	
	
/*
Errata 2.12.2
				
Upon EOT event, wait for at least one SCK cycle before setting CSTART
		
*/
	
	
	for(uint8_t i = 0; i<15; i++){
		__NOP;
	}
	
	
	
	
	
	SPI1->CR1 |= SPI_CR1_CSTART;
	
	*((volatile uint8_t*)&SPI1->TXDR) = data;
	
	while(((SPI1->SR)& SPI_SR_EOT) != SPI_SR_EOT || ((SPI1->SR)& SPI_SR_TXC) != SPI_SR_TXC);
	
/*
			
Endless loop.
			
if this loop & following spiStatus commented out and interrupt enabled, 
SW-continues to main while loop. 
 
Result = no flags, no interrupts
- Does not care about TSIZE value
			
if TSIZE != 0 -> CTSIZE != 0
- CTSIZE does not decrease
			
*/
	
	
	spiStatus = true;
 
}
 
void spiInit(){
	
	spiStatus = true;
	bufferCounter = 0;
	
	
/*
Many different variants of configurations have tried.
Following is latest of them.
	
Tried with full- and half-duplex transmitters too.
	
*/
 
	
	// CR1
	// crc calculation zero patterns
	SPI1->CR1 &= ~SPI_CR1_TCRCINI;
	// polynomial not used
	SPI1->CR1 &= ~SPI_CR1_CRC33_17;
	
	// SS set high (later) "This bit has an effect only when the SSM bit is set"
	//SPI1->CR1 |= SPI_CR1_SSI;
	
	// spi transmitter
	SPI1->CR1 |= SPI_CR1_HDDIR;
	
	
	// CFG1
	// master clock /2
	SPI1->CFG1 &= ~SPI_CFG1_MBR;
	// CRC computation disable
	SPI1->CFG1 &= ~SPI_CFG1_CRCEN;
	// CRCSIZE = 8-bit as DSIZE (to be sure..)
	SPI1->CFG1 |= SPI_CFG1_CRCSIZE_0 | SPI_CFG1_CRCSIZE_1 | SPI_CFG1_CRCSIZE_2;
	// tx dma disable
	SPI1->CFG1 &= ~I2C_CR1_TXDMAEN;
	// rx dma disable
	SPI1->CFG1 &= ~SPI_CFG1_RXDMAEN;
	// fifo threshold level = 4-data
	SPI1->CFG1 &= ~SPI_CFG1_FTHLV;
	SPI1->CFG1 |= SPI_CFG1_FTHLV_0 | SPI_CFG1_FTHLV_1;
	// Dsize = 8bits
	SPI1->CFG1 &= ~SPI_CFG1_DSIZE;
	SPI1->CFG1 |= SPI_CFG1_DSIZE_0 | SPI_CFG1_DSIZE_1 | SPI_CFG1_DSIZE_2;
	
	// CFG2
	// peripheral keeps always control of GPIOs
	SPI1->CFG2 |= SPI_CFG2_AFCNTR;
	// SS output management in master mode, active till transfer completed
	SPI1->CFG2 &= ~SPI_CFG2_SSOM;
	// multi-master mode disable
	SPI1->CFG2 |= SPI_CFG2_SSOE;
	// SS level, high=active
	SPI1->CFG2 |= SPI_CFG2_SSIOP;
	// SS signal input by bit
	SPI1->CFG2 |= SPI_CFG2_SSM;
	
	
	// clock polarity high on idle
	SPI1->CFG2 |= SPI_CFG2_CPOL;
	// clock phase second clock transition
	SPI1->CFG2 |= SPI_CFG2_CPHA;
	// MSB first
	SPI1->CFG2 &= ~SPI_CFG2_LSBFRST;
	// SPI master mode
	SPI1->CFG2 |= SPI_CFG2_MASTER;
	// motorola protocol
	SPI1->CFG2 &= ~SPI_CFG2_SP;
	// simplex transmitter
	SPI1->CFG2 |= SPI_CFG2_COMM_0;
	
 
	
	
	// EOT interrupt enable
	SPI1->IER |= SPI_IER_EOTIE;
	
	// SS high
	SPI1->CR1 |= SPI_CR1_SSI
	
	
	
}
 
 
void delay(){
	uint64_t i = 2000000;
	while(i--){
		;
	}
	i = 2000000;
	while(i--){
		;
	}
	
}
 
void cmdPinInit(){
	// PORTA, B & C clock enable 
	RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN;
	RCC->AHB4ENR |= RCC_AHB4ENR_GPIOBEN;
	RCC->AHB4ENR |= RCC_AHB4ENR_GPIOGEN;
	
	//SPI1 clock enable 
	RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
	
	
	// SCK & MOSI (open-drain + very high speed)
	GPIOB->MODER &= ~((GPIO_MODER_MODE3_0) | (GPIO_MODER_MODE5_0));
	GPIOB->MODER |= ((GPIO_MODER_MODE3_1) | (GPIO_MODER_MODE5_1));
	GPIOB->OTYPER |= (GPIO_OTYPER_OT3|GPIO_OTYPER_OT5);
	GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED3 | GPIO_OSPEEDR_OSPEED5;
	
	// SS (open-drain)
	GPIOG->MODER &= ~(GPIO_MODER_MODE10_0);
	GPIOG->MODER |= (GPIO_MODER_MODE10_1);
	GPIOG->OTYPER |= (GPIO_OTYPER_OT10);
	
 
	
		// SCK, MOSI, SS SPI1 alternate functions, AF5
	GPIOB->AFR[0] |= 5<<12 | 5<<20;
	GPIOG->AFR[1] |= 5<<8;
 
	
	// led
	GPIOA->MODER |= GPIO_MODER_MODE1_0;
	GPIOA->MODER &= ~(GPIO_MODER_MODE1_1);
	GPIOA->OTYPER |= GPIO_OTYPER_OT1;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED1_1;
	GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED1_0);
	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD1);
	GPIOA->BSRR |= GPIO_BSRR_BR1;
	
	
	// d/c
	GPIOA->MODER |= GPIO_MODER_MODE2_0;
	GPIOA->MODER &= ~(GPIO_MODER_MODE2_1);
	GPIOA->OTYPER |= GPIO_OTYPER_OT2;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED2_1;
	GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED2_0);
	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD2);
	
}
 
 
 
void SPI1_IRQHandler(void){
	
	if(((SPI1->SR)& SPI_SR_EOT) == SPI_SR_EOT){
		NVIC_DisableIRQ(SPI1_IRQn);
		spiStatus = true;
		SPI1->CR1 &= ~SPI_CR1_SPE;
		GPIOA->BSRR |= GPIO_BSRR_BS1;
	}
	
	if(((SPI1->SR)& SPI_SR_TXC) == SPI_SR_TXC){
		
		NVIC_DisableIRQ(SPI1_IRQn);
		spiStatus = true;
		SPI1->CR1 &= ~SPI_CR1_SPE;
		GPIOA->BSRR |= GPIO_BSRR_BS1;
	}
	
	
}
 

3 REPLIES 3

Read out and check content of the relevant SPI and GPIO registers. Mainly check, if SPI is still master (i.e. if some of the SS settings won't change it to Slave).

Rather than going directly to interrupts and stuff, just run an endless loop in the program after the setup, and try to transmit manually from debugger.

The 'H7 SPI has more setup gadgets than I'm willing to check - I don't use the 'H7.

JW

Thanks, the register values should be right way till waiting the flags.

I guess there would be some status flag catching problems when polling register, caused by clokcs differential, not sure...(?)

Actually I tried now feeding the TXDR while TXP, when TSIZE value is set to 0. No results yet.

I think I may located the problem to FIFO threshold level (FTHLV), number of bits in at single SPI data frame (DSIZE) initializations and following expected amount of data feedings to TXDR. This is my first time to use FIFO control and its confusing me totally .

I must refer again reference manual and the full description of data transmission procedures.

Kura
Associate II

This is solved now.

There were three critical aspects in my previous code

  • The PLL1 configuration (not implemented). So made that with CSI.
  • SCK, MOSI, & SS only the alternate function -type is appropriate change in MODER register only + AFR mux selection
  • FTHLV value in my case set to zero