AnsweredAssumed Answered

Timer triggered DMA SPI stream

Question asked by jakopin.blaz on Jul 20, 2014
Latest reply on Dec 3, 2014 by Femol
Hi guys!

Is there anyone that has some experience in setting up this kind of DMA streaming?

I would like to stream 16-bit data to an external DAC, with no sweat for the processor. I've read that timer triggered DMA transfers to SPI are a viable option, and also found some sample code for it. 

I have configured my TIM1 to run in OC mode, SPI1 relevant pins and the DMA peripheral to DMA2_Stream3 using Channel_6 as is written in the datasheet. 

When I run my code the output is dead, if I look at the DR register for SPI1 is also 0x0000, so no data is pouring in from the DMA.

Does anyone have any suggestions? Should I include some additional code to the main loop, that I am not aware of (I initialize all the peripherals, and in my understanding this should work)?

Here is my initialization function, that I use at startup:
001.void spi1_init(void)
002.{
003. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
004. TIM_OCInitTypeDef          TIM_OCInitStructure;
005. DMA_InitTypeDef                DMA_InitStructure;
006. SPI_InitTypeDef                SPI_InitStruct;
007. GPIO_InitTypeDef               GPIO_InitStructure;
008.  
009. /*
010. *  GPIO configuration
011. */
012. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
013.  
014. /*    Configure pins used by SPI1:
015. *        PA4 = NSS  
016. *        PA5 = SCLK
017. *        PA6 = MISO
018. *        PA7 = MOSI    */
019. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_4;
020. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
021. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
022. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
023. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
024. GPIO_Init(GPIOA, &GPIO_InitStructure);
025.  
026. /* Connect SPI1 pins to SPI alternate function */
027. GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1);
028. GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
029. GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
030. GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
031.  
032. /* Enable the SPI peripheral clock */
033. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
034.  
035. /*    Configure SPI1 in Mode 0:
036. *        CPOL = 0 --> clock is low when idle
037. *        CPHA = 0 --> data is sampled at the first edge
038. *
039. *    SPI Master mode, 8 bits of data, clock prescalar is 256, MSB is
040. *    transmitted first. */
041. SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
042. SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
043. SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
044. SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
045. SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
046. SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
047. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
048. SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
049. SPI_Init(SPI1, &SPI_InitStruct);
050.  
051. /* Enable SPI */
052. SPI_Cmd(SPI1, ENABLE);
053.  
054. /*
055. *    TIM1 Configuration
056. */
057. RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
058.  
059. /* Time base configuration */
060. TIM_TimeBaseStructure.TIM_Period           = 150;
061. TIM_TimeBaseStructure.TIM_Prescaler         = (uint16_t)(SystemCoreClock / 40000000) - 1;
062. TIM_TimeBaseStructure.TIM_ClockDivision     = 0;
063. TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;
064.  
065. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
066.  
067. /* PWM1 Mode configuration: Channel1 */
068. TIM_OCInitStructure.TIM_OCMode             = TIM_OCMode_PWM1;
069. TIM_OCInitStructure.TIM_OutputState         = TIM_OutputState_Enable;
070. TIM_OCInitStructure.TIM_Pulse               =  5;
071. TIM_OCInitStructure.TIM_OCPolarity          = TIM_OCPolarity_High;
072.  
073. TIM_OC1Init(TIM1, &TIM_OCInitStructure);
074. TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
075. TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
076. TIM_ARRPreloadConfig(TIM1, ENABLE);
077. TIM_Cmd(TIM1, ENABLE);
078.  
079. /*
080. *      DMA2 Configuration
081. */
082. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
083.  
084. DMA_DeInit(DMA2_Stream3);
085. DMA_StructInit(&DMA_InitStructure);
086.  
087. DMA_InitStructure.DMA_Channel            = DMA_Channel_6;
088. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
089. DMA_InitStructure.DMA_Memory0BaseAddr    = (uint32_t)&test_buffer;
090. DMA_InitStructure.DMA_DIR                = DMA_DIR_MemoryToPeripheral;
091. DMA_InitStructure.DMA_BufferSize         = TEST_BUFFER_LEN;
092. DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
093. DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
094. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
095. DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
096. DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;
097. DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
098. DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;
099. DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_HalfFull;
100. DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
101. DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;
102.  
103. DMA_ITConfig(DMA2_Stream3, DMA_IT_TC, DISABLE);
104. DMA_Init(DMA2_Stream3, &DMA_InitStructure);
105. DMA_Cmd(DMA2_Stream3, ENABLE);
106.  
107. TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
108.}

Thanks for your suggestions.

BR,
Blaz 



Outcomes