2017-01-16 07:10 AM
Hi,
I'm trying to get spi driver working for ad-converter. Adc spi is supporting ~20mhz spi clock. Now my project APB2(Using spi1) clock is 84 Mhz and spi prescale is now 2( Spi clock is 42Mhz) and code is running fine, but some samples is corrupted, so i assumed that the problem is that spi clock is too high(). Problem is when i change prescale to 4 it's get stuck to loop which check if spi running. This code is required call every time dma is complete.
static void stopReceiving()
{ SPI_Cmd(SPI1, DISABLE); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); // STUCK HERE SPI_I2S_ReceiveData(SPI1);}2017-01-16 09:24 AM
Try not to disable SPI. Busy flag tells when the SPI is at rest and its configuration changed (and disabled). Remember that writing a byte for transmit will generate spi clocks, and RXNE will tell when all the clocks have been expelled onto the bus and the slave byte is ready for reading. Any details on which STM32, which SPI mode is used to better understand the context?
When using DMA, configure and activate DMA RX before setting up and activate DMA TX... Or the clock will kick in too early. Also use DMA RX interrupt, not DMA TX one.
2017-01-17 01:54 AM
Hello
I managed to change the APB2 clock 42 MHz. But the it did not solve my problem. I have been using this code SPI-driver for our project for a few years. Now I wanted to try the CUBE and implemented the old SPI-driver to new CUBE code. For some reason I get errors in my adc-values.
The basic function is that I trigger SPI-DMA transfer triggered by ADC-dataready. After pin change STM-IRQ starts DMA transfer. After transfer is done (approx 10 us) stopReceiving() is called. This loop stat over when new ADC-dataready is received. This is working in my old code but new implemention to CUBE seems to generate false values in ADC data.
Ideas where to look? Seems like this could be related to IRQ and timing issues.
The reason for using old SPI-driver is that CUBE documentation stated some SPI speed limitations (2lines RXOnly, master -> FPCLK/64).
Below is SPI and DMA initialization. I'm using STM32F407
static void initSpiHW()
{ NVIC_InitTypeDef NVIC_InitStructure; SPI_InitTypeDef SPI_InitStructure;/* SPI initialization */
SPI_I2S_DeInit(SPI1); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure);/* Configure the SPI interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);/* Enable DMA requests */
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);}static void initDMAHW()
{ DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;DMA_DeInit(DMA2_Stream0);
DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_Channel = DMA_Channel_3; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//DMA_Priority_High;// DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC8;//DMA_MemoryBurst_Single;// DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR); DMA_Init(DMA2_Stream0, &DMA_InitStructure);// DMA generates interrupt on DMA transfer complete and on errors failed
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_TE | DMA_IT_DME, ENABLE);// Peripheral flow control
DMA_FlowControllerConfig(DMA2_Stream0, DMA_FlowCtrl_Memory);// Transfer size
DMA_SetCurrDataCounter(DMA2_Stream0, ADS1278_BLOCK_SIZE);// Enable interrupt for this channel
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ADC_SPI_DMA_INTERRUPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = ADC_SPI_DMA_INTERRUPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}