2021-05-20 08:06 AM
Hello dear community. I'd tried so long so i decided to ask for you.
I need to send some data pack from STM32F7(master) to STM32F1.
I use STM32CubeIDE platform. My code is below.
Problem is that in receiving back data by master. First byte has always corrupts.
Lower SPI speed does not solve the problem.
Second question is about MSIZE bit. Why it is set to "0x1" against my code?
Master:
#define SPI_DATLEN_BYTE 26
uint8_t bufRX[26];
uint8_t bufTX[26];
void SPIInit(void)
{
GPIO_InitTypeDef Init;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI1
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // GPIOA
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // DMA2
/*Configure GPIO pin : PA5,PA6,PA7 */
Init.Pin = SPI1_MASTER_MOSI|SPI1_MASTER_MISO|SPI1_MASTER_CLK;
Init.Mode = GPIO_MODE_AF_PP;
Init.Pull = GPIO_NOPULL;
Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SPI1_PORT, &Init);
/*Configure GPIO pin : PA3,PA4 */
Init.Pin = SPI1_MASTER_NSS1|SPI1_MASTER_NSS2;
Init.Mode = GPIO_MODE_OUTPUT_PP;
Init.Pull = GPIO_NOPULL;
Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SPI1_PORT, &Init);
// SPI settings
SPI1->CR2 = 0x7 << SPI_CR2_DS_Pos ; //frame size 8 bit
SPI1->CR2 |= 1<<SPI_CR2_TXDMAEN_Pos; //Enable DMA requests
SPI1->CR2 |= 1<<SPI_CR2_RXDMAEN_Pos;
SPI1->CR1 = 0<<SPI_CR1_LSBFIRST_Pos //MSB first
| 1<<SPI_CR1_SSM_Pos //soft SS enable
| 1<<SPI_CR1_SSI_Pos //SS pin high
| 0x02<<SPI_CR1_BR_Pos //speed: F_PCLK/8 (000: fPCLK/2 001: fPCLK/4 010: fPCLK/8 011: fPCLK/16 100: fPCLK/32 101: fPCLK/64 110: fPCLK/128)
| 1<<SPI_CR1_MSTR_Pos //master
| 0<<SPI_CR1_CPOL_Pos | 0<<SPI_CR1_CPHA_Pos; //SPI mode: 0
SPI1->CR1 |= 1<<SPI_CR1_SPE_Pos; //SPI1 enable
}
void SPI_Send(void)
{
//disable stream0
DMA2_Stream0->CR &= ~(DMA_SxCR_EN);
while (DMA2_Stream0->CR & DMA_SxCR_EN) { }
//DMA settings
DMA2_Stream0->PAR = (uint32_t)(&SPI1->DR); //Peripheral address of SPI1->DR
DMA2_Stream0->M0AR = (uint32_t)(&bufRX[0]); //Memory address is variable
DMA2_Stream0->NDTR = SPI_DATLEN_BYTE; //DATA LENTH = 26 bytes
DMA2_Stream0->CR =
0x00 << DMA_SxCR_PL_Pos //priority low
| 0x00 << DMA_SxCR_MSIZE_Pos //memory 8bit
| 0x01 << DMA_SxCR_PSIZE_Pos //peripheral register is 16bit
| 1 << DMA_SxCR_MINC_Pos //increase the memory
| 0 << DMA_SxCR_PINC_Pos //do not increase periph
| 0 << DMA_SxCR_CIRC_Pos //circular off
| 0 << DMA_SxCR_DIR_Pos //'0' from peripheral to memory
| (DMA_SxCR_CHSEL_0|DMA_SxCR_CHSEL_1); //channel 3 connect
//disable stream3
DMA2_Stream3->CR &= ~(DMA_SxCR_EN);
while (DMA2_Stream3->CR & DMA_SxCR_EN) {}
DMA2->LIFCR = 0xFFFFFFFF;
//DMA settings
DMA2_Stream3->PAR = (uint32_t)(&SPI1->DR); //Peripheral address of SPI1->DR
DMA2_Stream3->M0AR = (uint32_t)(&bufTX[0]); //Memory address is variable
DMA2_Stream3->NDTR = SPI_DATLEN_BYTE; //DATA LENTH = 26 bytes
DMA2_Stream3->CR =
0x00 << DMA_SxCR_PL_Pos //priority low
| 0x00 << DMA_SxCR_MSIZE_Pos //memory 8bit
| 0x01 << DMA_SxCR_PSIZE_Pos //peripheral register is 16bit
| 1 << DMA_SxCR_MINC_Pos //increase the memory
| 0 << DMA_SxCR_PINC_Pos //do not increase periph
| 0 << DMA_SxCR_CIRC_Pos //circular off
| 1 << DMA_SxCR_DIR_Pos //'1' from memory to peripheral
| (DMA_SxCR_CHSEL_0|DMA_SxCR_CHSEL_1); //channel 3 connect
DMA2_Stream0->CR |= (1 << DMA_SxCR_EN_Pos); //enable receive
DMA2_Stream3->CR |= 1 << DMA_SxCR_EN_Pos; //enable transmit
}
void initial(void) {
GPIO_InitTypeDef Init;
uint32_t i;
uint32_t random_num;
/*Configure GPIO pin : PA3,PA4 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA3,PA4 */
Init.Pin = SPI1_MASTER_NSS1 | SPI1_MASTER_NSS2;
Init.Mode = GPIO_MODE_OUTPUT_PP;
Init.Pull = GPIO_NOPULL;
Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SPI1_PORT, &Init);
HAL_GPIO_WritePin(SPI1_PORT, SPI1_MASTER_NSS1, GPIO_PIN_RESET);
HAL_Delay(50);
/*----Count rows-----*/
//fill the bufTX
for (i = 0; i < 26; i++) {
bufTX[i] = i;
}
//clear the bufRX
for (i = 0; i < 26; i++) {
bufRX[i] = 0;
}
while (1) {
//clear the bufRX
for (i = 0; i < 26; i++) {
bufRX[i] = 0;
}
// random_num = rnd_between(1, 3);
// printf("RND:%d\n", random_num);
//
// switch (random_num) {
// case 1:
// bufTX[0] = NOTHING;
// break;
// case 2:
// bufTX[0] = SEND_ROWS;
// break;
// case 3:
// bufTX[0] = SHUT_DOWN_LEADS;
// break;
// default:
// break;
// }
if (SPI_CHECK_FLAG(SPI1->SR, SPI_FLAG_OVR) == SET) {
printf("OVER\n");
}
if (DMA2->LISR & DMA_LISR_TCIF3) {
printf("CH3:TRANS COMP\n");
}
if (DMA2->LISR & DMA_LISR_HTIF3) {
printf("CH3:HALF TRANS\n");
}
if (DMA2->LISR & DMA_LISR_DMEIF3) {
printf("CH3:DIRMOD ERR\n");
}
if (DMA2->LISR & DMA_LISR_TEIF3) {
printf("CH3:TRANS ERR\n");
}
if (DMA2->LISR & DMA_LISR_FEIF3) {
printf("CH3:FIFO ERR\n");
}
if (DMA2->LISR & DMA_LISR_TCIF0) {
printf("CH0:TRANS COMP\n");
}
if (DMA2->LISR & DMA_LISR_HTIF0) {
printf("CH0:HALF TRANS\n");
}
if (DMA2->LISR & DMA_LISR_DMEIF0) {
printf("CH0:DIRMOD ERR\n");
}
if (DMA2->LISR & DMA_LISR_TEIF0) {
printf("CH0:TRANS ERR\n");
}
if (DMA2->LISR & DMA_LISR_FEIF0) {
printf("CH0:FIFO ERR\n");
}
//Impulse to slave
HAL_GPIO_WritePin(SPI1_PORT, SPI1_MASTER_NSS1, GPIO_PIN_SET);
__asm("NOP");
HAL_GPIO_WritePin(SPI1_PORT, SPI1_MASTER_NSS1, GPIO_PIN_RESET);
SPI_Send();
for (i = 0; i < 26; i++) {
printf("T[%X]R[%X]\n", bufTX[i], bufRX[i]);
}
printf("-------------------------------------------------\n");
HAL_Delay(1000);
}
}
2021-05-24 10:20 AM
Yes, i have updated the code. Now it prints right. Please see oscilloscope shot, there are wrong impulses at the begin.
2021-05-24 10:43 AM
I don't see an oscilloscope plot.
Keep in mind pins can toggle during initialization. Typically this is solved by keeping the CS line high.
I would suggest having a closer eye on the Reference Manual if you're going to use register access for everything.
2021-05-26 12:31 AM
Finely problem was that FRXTH was '0'.
0: RXNE event is generated if the FIFO level is greater than or equal to 1/2 (16-bit)
1: RXNE event is generated if the FIFO level is greater than or equal to 1/4 (8-bit)
Now it works fine at maximum speed 72/4 MHz.
Thanks for answers!
2021-05-27 07:57 AM
New problem please help.
After i polished SPI function everything works fine.
But now i put it into FreeRTOS and no action is detected on MOSI and consequently on MISO pins. Just low level on its.
New code below:
void SPIInit(void) {
GPIO_InitTypeDef Init;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI1
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // GPIOA
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // DMA2
/*Configure GPIO pin : PA5,PA6,PA7 */
Init.Pin = SPI1_MASTER_MOSI | SPI1_MASTER_MISO | SPI1_MASTER_CLK;
Init.Mode = GPIO_MODE_AF_PP;
Init.Pull = GPIO_NOPULL;
Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SPI1_PORT, &Init);
/*Configure GPIO pin : PA3,PA4 */
Init.Pin = SPI1_MASTER_NSS1 | SPI1_MASTER_NSS2;
Init.Mode = GPIO_MODE_OUTPUT_PP;
Init.Pull = GPIO_NOPULL;
Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SPI1_PORT, &Init);
/*-----------------------------------DMA--------------------------------------------*/
//disable stream0 && stream3
do {
DMA2_Stream0->CR &= ~(DMA_SxCR_EN);
DMA2_Stream3->CR &= ~(DMA_SxCR_EN);
} while( (DMA2_Stream0->CR & DMA_SxCR_EN) && (DMA2_Stream3->CR & DMA_SxCR_EN) );
DMA2->LIFCR = 0xFFFFFFFF; //Clear flags
//DMA receive settings
DMA2_Stream0->PAR = (uint32_t) (&SPI1->DR); //Peripheral address of SPI1->DR
DMA2_Stream0->M0AR = (uint32_t) (&bufRX[0]); //Memory address is variable
DMA2_Stream0->NDTR = SPI_DATLEN_BYTE; //DATA LENTH = 26 bytes
DMA2_Stream0->CR = 0x00 << DMA_SxCR_PL_Pos //priority low
| 0x00 << DMA_SxCR_MSIZE_Pos //memory 8bit
| 0x00 << DMA_SxCR_PSIZE_Pos //peripheral register is 16bit
| 1 << DMA_SxCR_MINC_Pos //increase the memory
| 0 << DMA_SxCR_PINC_Pos //do not increase periph
| 0 << DMA_SxCR_CIRC_Pos //circular off
| 0 << DMA_SxCR_DIR_Pos //'0' from peripheral to memory
| (DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1); //channel 3 connect
//DMA transmit settings
DMA2_Stream3->PAR = (uint32_t) (&SPI1->DR); //Peripheral address of SPI1->DR
DMA2_Stream3->M0AR = (uint32_t) (&bufTX[0]); //Memory address is variable
DMA2_Stream3->NDTR = SPI_DATLEN_BYTE; //DATA LENTH = 26 bytes
DMA2_Stream3->CR
= 0x00 << DMA_SxCR_PL_Pos //priority low
| 0x00 << DMA_SxCR_MSIZE_Pos //memory 8bit
| 0x00 << DMA_SxCR_PSIZE_Pos //peripheral register is 16bit
| 1 << DMA_SxCR_MINC_Pos //increase the memory
| 0 << DMA_SxCR_PINC_Pos //do not increase periph
| 0 << DMA_SxCR_CIRC_Pos //circular off
| 1 << DMA_SxCR_DIR_Pos //'1' from memory to peripheral
| (DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1); //channel 3 connect
/*----------------------------------------------------------------------------------*/
/*-----------------------------------SPI--------------------------------------------*/
// SPI settings
SPI1->CR2 = 0x7 << SPI_CR2_DS_Pos; //frame size 8 bit
SPI1->CR2 |= 1 << SPI_CR2_TXDMAEN_Pos; //Enable DMA requests
SPI1->CR2 |= 1 << SPI_CR2_RXDMAEN_Pos;
SPI1->CR2 |= 0x1 << SPI_CR2_FRXTH_Pos; //1: RXNE event is generated if the FIFO level is greater than or equal to 1/4 (8-bit)
SPI1->CR1
= 0 << SPI_CR1_LSBFIRST_Pos //MSB first
| 1 << SPI_CR1_SSM_Pos //soft SS enable
| 1 << SPI_CR1_SSI_Pos //SS pin high
| 0x01 << SPI_CR1_BR_Pos //speed: F_PCLK/8 (000: fPCLK/2 001: fPCLK/4 010: fPCLK/8 011: fPCLK/16 100: fPCLK/32 101: fPCLK/64 110: fPCLK/128)
| 1 << SPI_CR1_MSTR_Pos //master
| 0 << SPI_CR1_CPOL_Pos | 0 << SPI_CR1_CPHA_Pos; //SPI mode: 0
SPI1->CR1 |= 1 << SPI_CR1_SPE_Pos; //SPI1 enable
/*----------------------------------------------------------------------------------*/
}
void SPI_Send(void)
{
//disable stream0 && stream3
do {
DMA2_Stream0->CR &= ~(DMA_SxCR_EN);
DMA2_Stream3->CR &= ~(DMA_SxCR_EN);
} while( (DMA2_Stream0->CR & DMA_SxCR_EN) && (DMA2_Stream3->CR & DMA_SxCR_EN) );
DMA2->LIFCR = 0xFFFFFFFF;//Clear flags
DMA2_Stream3->NDTR = SPI_DATLEN_BYTE;//DATA LENTH = 26 bytes
DMA2_Stream0->NDTR = SPI_DATLEN_BYTE;//DATA LENTH = 26 bytes
DMA2_Stream0->CR |= 1 << DMA_SxCR_EN_Pos; //enable receive
DMA2_Stream3->CR |= 1 << DMA_SxCR_EN_Pos; //enable transmit
}
void initial(void) {
GPIO_InitTypeDef Init;
uint32_t i;
uint32_t random_num;
HAL_Delay(500);//Wait untill the slave
/*----Count rows-----*/
//fill the bufTX
for (i = 0; i < 26; i++) {
bufTX[i] = i;
}
//clear the bufRX
for (i = 0; i < 26; i++) {
bufRX[i] = 0;
}
//clear the bufRX
for (i = 0; i < 26; i++) {
bufRX[i] = 0;
}
random_num = rnd_between(1, 3);
//printf("RND:%d\n", (random_num);
switch (random_num) {
case 1:
bufTX[0] = NOTHING;
break;
case 2:
bufTX[0] = SEND_ROWS;
break;
case 3:
bufTX[0] = SHUT_DOWN_LEADS;
break;
default:
break;
}
SPI_Send();
HAL_Delay(1000);
for (i = 0; i < 26; i++) {
printf("T[%X]R[%X]\n", bufTX[i], bufRX[i]);
}
printf("-------------------------------------------------\n");
}
Standard FreeRTOS task with default parameters:
void spiSendLoop(void *argument){
while(1){
initial();
}
}
I do not use interrupts!
All registers has the same value as without freertos.
GPIO has normal values.
spiSendLoop task works normally, 'printf' prints values '0' but oscilloscope detect no action on MOSI pin
2021-05-28 11:28 PM
This time GPIOA->AFR register was set to wrong values.
So many mystical in my codes)