2020-02-27 03:18 AM
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;
}
}
2020-02-27 09:14 AM
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
2020-02-28 03:52 AM
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.
2020-03-02 02:23 PM
This is solved now.
There were three critical aspects in my previous code